22
33Mobile robot motion planning sample with Dynamic Window Approach
44
5- author: Atsushi Sakai (@Atsushi_twi)
5+ author: Atsushi Sakai (@Atsushi_twi), Goktug Karakasli
66
77"""
88
9+ from enum import Enum
910import math
1011
1112import matplotlib .pyplot as plt
@@ -25,6 +26,9 @@ def dwa_control(x, config, goal, ob):
2526
2627 return u , trajectory
2728
29+ class RobotType (Enum ):
30+ circle = 0
31+ rectangle = 1
2832
2933class Config :
3034 """
@@ -45,8 +49,25 @@ def __init__(self):
4549 self .to_goal_cost_gain = 0.15
4650 self .speed_cost_gain = 1.0
4751 self .obstacle_cost_gain = 1.0
52+ self .robot_type = RobotType .circle
53+
54+ # if robot_type == RobotType.circle
55+ # Also used to check if goal is reached in both types
4856 self .robot_radius = 1.0 # [m] for collision check
4957
58+ # if robot_type == RobotType.rectangle
59+ self .robot_width = 0.5 # [m] for collision check
60+ self .robot_length = 1.2 # [m] for collision check
61+
62+ @property
63+ def robot_type (self ):
64+ return self ._robot_type
65+
66+ @robot_type .setter
67+ def robot_type (self , value ):
68+ if not isinstance (value , RobotType ):
69+ raise TypeError ("robot_type must be an instance of RobotType" )
70+ self ._robot_type = value
5071
5172def motion (x , u , dt ):
5273 """
@@ -141,12 +162,29 @@ def calc_obstacle_cost(trajectory, ob, config):
141162 dx = trajectory [:, 0 ] - ox [:, None ]
142163 dy = trajectory [:, 1 ] - oy [:, None ]
143164 r = np .sqrt (np .square (dx ) + np .square (dy ))
144- if (r <= config .robot_radius ).any ():
145- return float ("Inf" )
165+
166+ if config .robot_type == RobotType .rectangle :
167+ yaw = trajectory [:, 2 ]
168+ rot = np .array ([[np .cos (yaw ), - np .sin (yaw )], [np .sin (yaw ), np .cos (yaw )]])
169+ rot = np .transpose (rot , [2 , 0 , 1 ])
170+ local_ob = ob [:, None ] - trajectory [:, 0 :2 ]
171+ local_ob = local_ob .reshape (- 1 , local_ob .shape [- 1 ])
172+ local_ob = np .array ([local_ob @ - x for x in rot ])
173+ local_ob = local_ob .reshape (- 1 , local_ob .shape [- 1 ])
174+ upper_check = local_ob [:, 0 ] <= config .robot_length / 2
175+ right_check = local_ob [:, 1 ] <= config .robot_width / 2
176+ bottom_check = local_ob [:, 0 ] >= - config .robot_length / 2
177+ left_check = local_ob [:, 1 ] >= - config .robot_width / 2
178+ if (np .logical_and (np .logical_and (upper_check , right_check ),
179+ np .logical_and (bottom_check , left_check ))).any ():
180+ return float ("Inf" )
181+ elif config .robot_type == RobotType .circle :
182+ if (r <= config .robot_radius ).any ():
183+ return float ("Inf" )
184+
146185 min_r = np .min (r )
147186 return 1.0 / min_r # OK
148187
149-
150188def calc_to_goal_cost (trajectory , goal ):
151189 """
152190 calc to goal cost with angle difference
@@ -167,7 +205,30 @@ def plot_arrow(x, y, yaw, length=0.5, width=0.1): # pragma: no cover
167205 plt .plot (x , y )
168206
169207
170- def main (gx = 10.0 , gy = 10.0 ):
208+ def plot_robot (x , y , yaw , config ): # pragma: no cover
209+ if config .robot_type == RobotType .rectangle :
210+ outline = np .array ([[- config .robot_length / 2 , config .robot_length / 2 ,
211+ (config .robot_length / 2 ), - config .robot_length / 2 ,
212+ - config .robot_length / 2 ],
213+ [config .robot_width / 2 , config .robot_width / 2 ,
214+ - config .robot_width / 2 , - config .robot_width / 2 ,
215+ config .robot_width / 2 ]])
216+ Rot1 = np .array ([[math .cos (yaw ), math .sin (yaw )],
217+ [- math .sin (yaw ), math .cos (yaw )]])
218+ outline = (outline .T .dot (Rot1 )).T
219+ outline [0 , :] += x
220+ outline [1 , :] += y
221+ plt .plot (np .array (outline [0 , :]).flatten (),
222+ np .array (outline [1 , :]).flatten (), "-k" )
223+ elif config .robot_type == RobotType .circle :
224+ circle = plt .Circle ((x , y ), config .robot_radius , color = "b" )
225+ plt .gcf ().gca ().add_artist (circle )
226+ out_x , out_y = (np .array ([x , y ]) +
227+ np .array ([np .cos (yaw ), np .sin (yaw )]) * config .robot_radius )
228+ plt .plot ([x , out_x ], [y , out_y ], "-k" )
229+
230+
231+ def main (gx = 10.0 , gy = 10.0 , robot_type = RobotType .circle ):
171232 print (__file__ + " start!!" )
172233 # initial state [x(m), y(m), yaw(rad), v(m/s), omega(rad/s)]
173234 x = np .array ([0.0 , 0.0 , math .pi / 8.0 , 0.0 , 0.0 ])
@@ -194,6 +255,7 @@ def main(gx=10.0, gy=10.0):
194255 # input [forward speed, yawrate]
195256 u = np .array ([0.0 , 0.0 ])
196257 config = Config ()
258+ config .robot_type = robot_type
197259 trajectory = np .array (x )
198260
199261 while True :
@@ -207,6 +269,7 @@ def main(gx=10.0, gy=10.0):
207269 plt .plot (x [0 ], x [1 ], "xr" )
208270 plt .plot (goal [0 ], goal [1 ], "xb" )
209271 plt .plot (ob [:, 0 ], ob [:, 1 ], "ok" )
272+ plot_robot (x [0 ], x [1 ], x [2 ], config )
210273 plot_arrow (x [0 ], x [1 ], x [2 ])
211274 plt .axis ("equal" )
212275 plt .grid (True )
0 commit comments