14
14
show_animation = True
15
15
16
16
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
+
17
57
def mod2pi (theta ):
18
58
return theta - 2.0 * math .pi * math .floor (theta / 2.0 / math .pi )
19
59
@@ -148,14 +188,14 @@ def dubins_path_planning_from_origin(end_x, end_y, end_yaw, curvature,
148
188
alpha = mod2pi (- theta )
149
189
beta = mod2pi (end_yaw - theta )
150
190
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 ]
154
194
155
195
best_cost = float ("inf" )
156
196
bt , bp , bq , best_mode = None , None , None , None
157
197
158
- for planner in planners :
198
+ for planner in planning_funcs :
159
199
t , p , q , mode = planner (alpha , beta , d )
160
200
if t is None :
161
201
continue
@@ -166,10 +206,15 @@ def dubins_path_planning_from_origin(end_x, end_y, end_yaw, curvature,
166
206
best_cost = cost
167
207
lengths = [bt , bp , bq ]
168
208
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 ]
171
216
172
- return x_list , y_list , yaw_list , best_mode , best_cost
217
+ return x_list , y_list , yaw_list , best_mode , lengths
173
218
174
219
175
220
def 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,
203
248
return path_x , path_y , path_yaw , directions
204
249
205
250
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 ,
241
252
step_size ):
242
253
n_point = math .trunc (total_length / step_size ) + len (lengths ) + 4
243
254
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 )]
247
258
directions = [0.0 for _ in range (n_point )]
248
- index = 1
259
+ ind = 1
249
260
250
261
if lengths [0 ] > 0.0 :
251
262
directions [0 ] = 1
@@ -254,7 +265,7 @@ def generate_local_course(total_length, lengths, mode, max_curvature,
254
265
255
266
ll = 0.0
256
267
257
- for (m , length , i ) in zip (mode , lengths , range (len (mode ))):
268
+ for (m , length , i ) in zip (modes , lengths , range (len (modes ))):
258
269
if length == 0.0 :
259
270
continue
260
271
elif length > 0.0 :
@@ -263,54 +274,57 @@ def generate_local_course(total_length, lengths, mode, max_curvature,
263
274
dist = - step_size
264
275
265
276
# 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 ]
268
278
269
- index -= 1
279
+ ind -= 1
270
280
if i >= 1 and (lengths [i - 1 ] * lengths [i ]) > 0 :
271
281
pd = - dist - ll
272
282
else :
273
283
pd = dist - ll
274
284
275
285
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 )
280
295
pd += dist
281
296
282
297
ll = length - pd - dist # calc remain length
283
298
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 )
288
306
289
- if len (path_x ) <= 1 :
307
+ if len (p_x ) <= 1 :
290
308
return [], [], [], []
291
309
292
310
# 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 ()
297
315
directions .pop ()
298
316
299
- return path_x , path_y , path_yaw , directions
317
+ return p_x , p_y , p_yaw , directions
300
318
301
319
302
320
def plot_arrow (x , y , yaw , length = 1.0 , width = 0.5 , fc = "r" ,
303
321
ec = "k" ): # pragma: no cover
304
- """
305
- Plot arrow
306
- """
307
-
308
322
if not isinstance (x , float ):
309
323
for (i_x , i_y , i_yaw ) in zip (x , y , yaw ):
310
324
plot_arrow (i_x , i_y , i_yaw )
311
325
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 )
314
328
plt .plot (x , y )
315
329
316
330
@@ -327,9 +341,13 @@ def main():
327
341
328
342
curvature = 1.0
329
343
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 )
333
351
334
352
if show_animation :
335
353
plt .plot (path_x , path_y , label = "final course " + "" .join (mode ))
0 commit comments