@@ -14,6 +14,12 @@ class DynamicPathPlannerGoal():
1414 def __init__ (self , endPose :Pose2d ):
1515 self .endPose = endPose
1616 self .baseMap = GradientDescentCostMap (self .endPose )
17+ self .baseMap .add_obstacle (Translation2d (5.56 , 2.74 ),100 ,0.75 )
18+ self .baseMap .add_obstacle (Translation2d (3.45 , 4.07 ),100 ,0.75 )
19+ self .baseMap .add_obstacle (Translation2d (5.56 , 5.35 ),100 ,0.75 )
20+ self .baseMap .add_obstacle (Translation2d (11.0 , 2.74 ),100 ,0.75 )
21+ self .baseMap .add_obstacle (Translation2d (13.27 , 4.07 ),100 ,0.75 )
22+ self .baseMap .add_obstacle (Translation2d (11.0 , 5.35 ),100 ,0.75 )
1723
1824GOAL_PICKUP = DynamicPathPlannerGoal (Pose2d .fromFeet (40 ,5 ,Rotation2d .fromDegrees (0.0 )))
1925GOAL_SPEAKER = DynamicPathPlannerGoal (Pose2d .fromFeet (3 ,20 ,Rotation2d .fromDegrees (0.0 )))
@@ -54,7 +60,12 @@ def addObstacleObservation(self, obs:ObstacleObservation):
5460 def _obstacleCostHeuristic (timeToLive :float )-> float :
5561 """ return the "height" used in pathplanning based on the alive time"""
5662 return timeToLive * 2.0
57-
63+
64+ def _getHolonomicRotation (self , time_s :float )-> Rotation2d :
65+ if (self .curTraj is not None and self .trajStartTime_s is not None ):
66+ initialPose = self .trajCfg
67+
68+
5869 def get (self ) -> DrivetrainCommand :
5970 if (self .curTraj is not None and self .trajStartTime_s is not None ):
6071 # Trajectory doesn't work great for holonomic drivetrains.
@@ -66,9 +77,14 @@ def get(self) -> DrivetrainCommand:
6677 nextTime = curTime + 0.01
6778 deltaTime = nextTime - prevTime
6879
69- prevSample = self .curTraj .sample (prevTime ).pose
70- curSample = self .curTraj .sample (curTime ).pose
71- nextSample = self .curTraj .sample (nextTime ).pose
80+ prevSampleTrans = self .curTraj .sample (prevTime ).pose .translation ()
81+ curSampleTrans = self .curTraj .sample (curTime ).pose .translation ()
82+ nextSampleTrans = self .curTraj .sample (nextTime ).pose .translation ()
83+
84+ # Adjust the sample poses to have the correct holonomic rotation
85+ prevSample = Pose2d (prevSampleTrans , Rotation2d ())
86+ curSample = Pose2d (curSampleTrans , Rotation2d ())
87+ nextSample = Pose2d (nextSampleTrans , Rotation2d ())
7288
7389 xVel = (nextSample .translation ().X () - prevSample .translation ().X ())/ deltaTime
7490 yVel = (nextSample .translation ().Y () - prevSample .translation ().Y ())/ deltaTime
@@ -116,8 +132,44 @@ def _do_replan(self, curPose:Pose2d) -> np.ndarray:
116132 # Calc a new path
117133 self .waypoints = workingMap .calculate_path (curPose )
118134
135+ # Get start/end poses for feeding to the trajectory generation
136+ # These should be in the same translations as start/end points
137+ # But with rotations that reflect the intended velocity vector of the robot
138+ # at the start and end.
139+ # This is needed because the trajectory generator is designed around tank drives
140+ # but since we have a swerve drive, robot heading and velocity vector heading are decoupled
141+ if (len (self .waypoints ) > 2 ):
142+ startTrajPose = Pose2d (
143+ translation = curPose .translation (),
144+ rotation = self ._getDirection (self .waypoints [0 ], self .waypoints [1 ])
145+ )
146+ endTrajPose = Pose2d (
147+ translation = self .curGoal .endPose .translation (),
148+ rotation = self ._getDirection ( self .waypoints [- 2 ],self .waypoints [- 1 ])
149+ )
150+ else :
151+ startTrajPose = Pose2d (
152+ translation = curPose .translation (),
153+ rotation = self ._getDirection (curPose .translation (),
154+ self .curGoal .endPose .translation ())
155+ )
156+ endTrajPose = Pose2d (
157+ translation = self .curGoal .endPose .translation (),
158+ rotation = self ._getDirection (curPose .translation (),
159+ self .curGoal .endPose .translation ())
160+ )
161+
162+
119163 # TODO - initial velocity
120- self .curTraj = TrajectoryGenerator .generateTrajectory (curPose , self .waypoints , self .curGoal .endPose , self .trajCfg )
121- self .trajStartTime_s = Timer .getFPGATimestamp ()
164+ self .curTraj = TrajectoryGenerator .generateTrajectory (startTrajPose , self .waypoints , endTrajPose , self .trajCfg )
122165
166+
167+ self .trajStartTime_s = Timer .getFPGATimestamp ()
123168 return workingMap .base_grid
169+
170+ @staticmethod
171+ def _getDirection (from_tans :Translation2d , to_trans :Translation2d ) -> Rotation2d :
172+ deltaX = (to_trans .X () - from_tans .X ())
173+ deltaY = (to_trans .Y () - from_tans .Y ())
174+ return Rotation2d (x = deltaX , y = deltaY )
175+
0 commit comments