1414show_animation = True
1515
1616
17+ def dubins_path_planning (s_x , s_y , s_yaw , g_x , g_y , g_yaw , curvature ,
18+ step_size = 0.1 ):
19+ """
20+ Dubins path planner
21+
22+ :param s_x: x position of start point [m]
23+ :param s_y: y position of start point [m]
24+ :param s_yaw: yaw angle of start point [rad]
25+ :param g_x: x position of end point [m]
26+ :param g_y: y position of end point [m]
27+ :param g_yaw: yaw angle of end point [rad]
28+ :param curvature: curvature for curve [1/m]
29+ :param step_size: (optional) step size between two path points [m]
30+ :return:
31+ x_list: x positions of a path
32+ y_list: y positions of a path
33+ yaw_list: yaw angles of a path
34+ modes: mode list of a path
35+ lengths: length of path segments.
36+ """
37+
38+ g_x -= s_x
39+ g_y -= s_y
40+
41+ l_rot = Rot .from_euler ('z' , s_yaw ).as_matrix ()[0 :2 , 0 :2 ]
42+ le_xy = np .stack ([g_x , g_y ]).T @ l_rot
43+ le_yaw = g_yaw - s_yaw
44+
45+ lp_x , lp_y , lp_yaw , modes , lengths = dubins_path_planning_from_origin (
46+ le_xy [0 ], le_xy [1 ], le_yaw , curvature , step_size )
47+
48+ rot = Rot .from_euler ('z' , - s_yaw ).as_matrix ()[0 :2 , 0 :2 ]
49+ converted_xy = np .stack ([lp_x , lp_y ]).T @ rot
50+ x_list = converted_xy [:, 0 ] + s_x
51+ y_list = converted_xy [:, 1 ] + s_y
52+ yaw_list = [pi_2_pi (i_yaw + s_yaw ) for i_yaw in lp_yaw ]
53+
54+ return x_list , y_list , yaw_list , modes , lengths
55+
56+
1757def mod2pi (theta ):
1858 return theta - 2.0 * math .pi * math .floor (theta / 2.0 / math .pi )
1959
@@ -148,14 +188,14 @@ def dubins_path_planning_from_origin(end_x, end_y, end_yaw, curvature,
148188 alpha = mod2pi (- theta )
149189 beta = mod2pi (end_yaw - theta )
150190
151- planners = [left_straight_left , right_straight_right , left_straight_right ,
152- right_straight_left , right_left_right ,
153- left_right_left ]
191+ planning_funcs = [left_straight_left , right_straight_right ,
192+ left_straight_right , right_straight_left ,
193+ right_left_right , left_right_left ]
154194
155195 best_cost = float ("inf" )
156196 bt , bp , bq , best_mode = None , None , None , None
157197
158- for planner in planners :
198+ for planner in planning_funcs :
159199 t , p , q , mode = planner (alpha , beta , d )
160200 if t is None :
161201 continue
@@ -166,10 +206,15 @@ def dubins_path_planning_from_origin(end_x, end_y, end_yaw, curvature,
166206 best_cost = cost
167207 lengths = [bt , bp , bq ]
168208
169- x_list , y_list , yaw_list , directions = generate_local_course (
170- sum (lengths ), lengths , best_mode , curvature , step_size )
209+ x_list , y_list , yaw_list , directions = generate_local_course (sum (lengths ),
210+ lengths ,
211+ best_mode ,
212+ curvature ,
213+ step_size )
214+
215+ lengths = [length / curvature for length in lengths ]
171216
172- return x_list , y_list , yaw_list , best_mode , best_cost
217+ return x_list , y_list , yaw_list , best_mode , lengths
173218
174219
175220def interpolate (ind , length , mode , max_curvature , origin_x , origin_y ,
@@ -203,49 +248,15 @@ def interpolate(ind, length, mode, max_curvature, origin_x, origin_y,
203248 return path_x , path_y , path_yaw , directions
204249
205250
206- def dubins_path_planning (s_x , s_y , s_yaw , g_x , g_y , g_yaw , c , step_size = 0.1 ):
207- """
208- Dubins path planner
209-
210- input:
211- s_x x position of start point [m]
212- s_y y position of start point [m]
213- s_yaw yaw angle of start point [rad]
214- g_x x position of end point [m]
215- g_y y position of end point [m]
216- g_yaw yaw angle of end point [rad]
217- c curvature [1/m]
218-
219- """
220-
221- g_x = g_x - s_x
222- g_y = g_y - s_y
223-
224- l_rot = Rot .from_euler ('z' , s_yaw ).as_matrix ()[0 :2 , 0 :2 ]
225- le_xy = np .stack ([g_x , g_y ]).T @ l_rot
226- le_yaw = g_yaw - s_yaw
227-
228- lp_x , lp_y , lp_yaw , mode , lengths = dubins_path_planning_from_origin (
229- le_xy [0 ], le_xy [1 ], le_yaw , c , step_size )
230-
231- rot = Rot .from_euler ('z' , - s_yaw ).as_matrix ()[0 :2 , 0 :2 ]
232- converted_xy = np .stack ([lp_x , lp_y ]).T @ rot
233- x_list = converted_xy [:, 0 ] + s_x
234- y_list = converted_xy [:, 1 ] + s_y
235- yaw_list = [pi_2_pi (i_yaw + s_yaw ) for i_yaw in lp_yaw ]
236-
237- return x_list , y_list , yaw_list , mode , lengths
238-
239-
240- def generate_local_course (total_length , lengths , mode , max_curvature ,
251+ def generate_local_course (total_length , lengths , modes , max_curvature ,
241252 step_size ):
242253 n_point = math .trunc (total_length / step_size ) + len (lengths ) + 4
243254
244- path_x = [0.0 for _ in range (n_point )]
245- path_y = [0.0 for _ in range (n_point )]
246- path_yaw = [0.0 for _ in range (n_point )]
255+ p_x = [0.0 for _ in range (n_point )]
256+ p_y = [0.0 for _ in range (n_point )]
257+ p_yaw = [0.0 for _ in range (n_point )]
247258 directions = [0.0 for _ in range (n_point )]
248- index = 1
259+ ind = 1
249260
250261 if lengths [0 ] > 0.0 :
251262 directions [0 ] = 1
@@ -254,7 +265,7 @@ def generate_local_course(total_length, lengths, mode, max_curvature,
254265
255266 ll = 0.0
256267
257- for (m , length , i ) in zip (mode , lengths , range (len (mode ))):
268+ for (m , length , i ) in zip (modes , lengths , range (len (modes ))):
258269 if length == 0.0 :
259270 continue
260271 elif length > 0.0 :
@@ -263,54 +274,57 @@ def generate_local_course(total_length, lengths, mode, max_curvature,
263274 dist = - step_size
264275
265276 # set origin state
266- origin_x , origin_y , origin_yaw = \
267- path_x [index ], path_y [index ], path_yaw [index ]
277+ origin_x , origin_y , origin_yaw = p_x [ind ], p_y [ind ], p_yaw [ind ]
268278
269- index -= 1
279+ ind -= 1
270280 if i >= 1 and (lengths [i - 1 ] * lengths [i ]) > 0 :
271281 pd = - dist - ll
272282 else :
273283 pd = dist - ll
274284
275285 while abs (pd ) <= abs (length ):
276- index += 1
277- path_x , path_y , path_yaw , directions = interpolate (
278- index , pd , m , max_curvature , origin_x , origin_y , origin_yaw ,
279- path_x , path_y , path_yaw , directions )
286+ ind += 1
287+ p_x , p_y , p_yaw , directions = interpolate (ind , pd , m ,
288+ max_curvature ,
289+ origin_x ,
290+ origin_y ,
291+ origin_yaw ,
292+ p_x , p_y ,
293+ p_yaw ,
294+ directions )
280295 pd += dist
281296
282297 ll = length - pd - dist # calc remain length
283298
284- index += 1
285- path_x , path_y , path_yaw , directions = interpolate (
286- index , length , m , max_curvature , origin_x , origin_y , origin_yaw ,
287- path_x , path_y , path_yaw , directions )
299+ ind += 1
300+ p_x , p_y , p_yaw , directions = interpolate (ind , length , m ,
301+ max_curvature ,
302+ origin_x , origin_y ,
303+ origin_yaw ,
304+ p_x , p_y , p_yaw ,
305+ directions )
288306
289- if len (path_x ) <= 1 :
307+ if len (p_x ) <= 1 :
290308 return [], [], [], []
291309
292310 # remove unused data
293- while len (path_x ) >= 1 and path_x [- 1 ] == 0.0 :
294- path_x .pop ()
295- path_y .pop ()
296- path_yaw .pop ()
311+ while len (p_x ) >= 1 and p_x [- 1 ] == 0.0 :
312+ p_x .pop ()
313+ p_y .pop ()
314+ p_yaw .pop ()
297315 directions .pop ()
298316
299- return path_x , path_y , path_yaw , directions
317+ return p_x , p_y , p_yaw , directions
300318
301319
302320def plot_arrow (x , y , yaw , length = 1.0 , width = 0.5 , fc = "r" ,
303321 ec = "k" ): # pragma: no cover
304- """
305- Plot arrow
306- """
307-
308322 if not isinstance (x , float ):
309323 for (i_x , i_y , i_yaw ) in zip (x , y , yaw ):
310324 plot_arrow (i_x , i_y , i_yaw )
311325 else :
312- plt .arrow (x , y , length * math .cos (yaw ), length * math .sin (yaw ),
313- fc = fc , ec = ec , head_width = width , head_length = width )
326+ plt .arrow (x , y , length * math .cos (yaw ), length * math .sin (yaw ), fc = fc ,
327+ ec = ec , head_width = width , head_length = width )
314328 plt .plot (x , y )
315329
316330
@@ -327,9 +341,13 @@ def main():
327341
328342 curvature = 1.0
329343
330- path_x , path_y , path_yaw , mode , path_length = dubins_path_planning (
331- start_x , start_y , start_yaw ,
332- end_x , end_y , end_yaw , curvature )
344+ path_x , path_y , path_yaw , mode , lengths = dubins_path_planning (start_x ,
345+ start_y ,
346+ start_yaw ,
347+ end_x ,
348+ end_y ,
349+ end_yaw ,
350+ curvature )
333351
334352 if show_animation :
335353 plt .plot (path_x , path_y , label = "final course " + "" .join (mode ))
0 commit comments