66co-author Videh Patel(@videh25) : Added the missing RS paths
77
88"""
9- import sys
109import pathlib
10+ import sys
11+
1112sys .path .append (str (pathlib .Path (__file__ ).parent .parent .parent ))
1213
1314import math
15+ from typing import List , Tuple
1416
1517import matplotlib .pyplot as plt
1618import numpy as np
19+ from numpy .typing import NDArray
20+
1721from utils .angle import angle_mod
1822
1923show_animation = True
@@ -342,63 +346,88 @@ def generate_path(q0, q1, max_curvature, step_size):
342346 return paths
343347
344348
345- def calc_interpolate_dists_list (lengths , step_size ) :
346- interpolate_dists_list = []
349+ def calc_interpolate_dists_list (lengths : List [ float ] , step_size : float ) -> List [ NDArray [ np . floating ]] :
350+ interpolate_dists_list : List [ NDArray [ np . floating ]] = []
347351 for length in lengths :
348352 d_dist = step_size if length >= 0.0 else - step_size
349- interp_dists = np .arange (0.0 , length , d_dist )
350- interp_dists = np .append (interp_dists , length )
353+
354+ interp_core = np .arange (0.0 , length , d_dist , dtype = np .float64 )
355+ interp_dists = np .empty (len (interp_core ) + 1 , dtype = np .float64 )
356+ interp_dists [:- 1 ] = interp_core
357+ interp_dists [- 1 ] = length
358+
351359 interpolate_dists_list .append (interp_dists )
352360
353361 return interpolate_dists_list
354362
355363
356- def generate_local_course (lengths , modes , max_curvature , step_size ):
364+ def generate_local_course (
365+ lengths : List [float ],
366+ modes : List [str ],
367+ max_curvature : float ,
368+ step_size : float ,
369+ ) -> Tuple [NDArray [np .floating ], NDArray [np .floating ], NDArray [np .floating ], NDArray [np .signedinteger ]]:
357370 interpolate_dists_list = calc_interpolate_dists_list (lengths , step_size * max_curvature )
371+ total_len = sum (len (arr ) for arr in interpolate_dists_list )
372+ xs = np .empty (total_len , dtype = np .float64 )
373+ ys = np .empty_like (xs )
374+ yaws = np .empty_like (xs )
375+ directions = np .empty_like (xs , dtype = np .int32 )
358376
359377 origin_x , origin_y , origin_yaw = 0.0 , 0.0 , 0.0
360-
361- xs , ys , yaws , directions = [], [], [], []
362- for ( interp_dists , mode , length ) in zip (interpolate_dists_list , modes ,
363- lengths ):
364-
365- for dist in interp_dists :
366- x , y , yaw , direction = interpolate ( dist , length , mode ,
367- max_curvature , origin_x ,
368- origin_y , origin_yaw )
369- xs . append ( x )
370- ys . append ( y )
371- yaws . append ( yaw )
372- directions . append ( direction )
373- origin_x = xs [- 1 ]
374- origin_y = ys [- 1 ]
375- origin_yaw = yaws [ - 1 ]
378+ idx = 0
379+
380+ for interp_dists , mode , length in zip (interpolate_dists_list , modes , lengths ):
381+ n = len ( interp_dists )
382+ x_arr , y_arr , yaw_arr , dir_arr = interpolate_vectorized (
383+ interp_dists , length , mode , max_curvature , origin_x , origin_y , origin_yaw
384+ )
385+ xs [ idx : idx + n ] = x_arr
386+ ys [ idx : idx + n ] = y_arr
387+ yaws [ idx : idx + n ] = yaw_arr
388+ directions [ idx : idx + n ] = dir_arr
389+
390+ origin_x = x_arr [ - 1 ]
391+ origin_y = y_arr [- 1 ]
392+ origin_yaw = yaw_arr [- 1 ]
393+ idx += n
376394
377395 return xs , ys , yaws , directions
378396
379397
380- def interpolate (dist , length , mode , max_curvature , origin_x , origin_y ,
381- origin_yaw ):
398+ def interpolate_vectorized (
399+ dists : NDArray [np .floating ],
400+ length : float ,
401+ mode : str ,
402+ max_curvature : float ,
403+ origin_x : float ,
404+ origin_y : float ,
405+ origin_yaw : float ,
406+ ) -> Tuple [NDArray [np .floating ], NDArray [np .floating ], NDArray [np .floating ], NDArray [np .signedinteger ]]:
382407 if mode == "S" :
383- x = origin_x + dist / max_curvature * math .cos (origin_yaw )
384- y = origin_y + dist / max_curvature * math .sin (origin_yaw )
385- yaw = origin_yaw
408+ x = origin_x + dists / max_curvature * math .cos (origin_yaw )
409+ y = origin_y + dists / max_curvature * math .sin (origin_yaw )
410+ yaw = np . full_like ( dists , origin_yaw )
386411 else : # curve
387- ldx = math .sin (dist ) / max_curvature
388- ldy = 0.0
389- yaw = None
412+ ldx = np .sin (dists ) / max_curvature
413+ ldy = np . zeros_like ( dists )
414+ yaw = np . zeros_like ( dists )
390415 if mode == "L" : # left turn
391- ldy = (1.0 - math .cos (dist )) / max_curvature
392- yaw = origin_yaw + dist
393- elif mode == "R" : # right turn
394- ldy = (1.0 - math .cos (dist )) / - max_curvature
395- yaw = origin_yaw - dist
396- gdx = math .cos (- origin_yaw ) * ldx + math .sin (- origin_yaw ) * ldy
397- gdy = - math .sin (- origin_yaw ) * ldx + math .cos (- origin_yaw ) * ldy
416+ ldy = (1.0 - np .cos (dists )) / max_curvature
417+ yaw = origin_yaw + dists
418+ else : # elif mode == "R": # right turn
419+ ldy = (1.0 - np .cos (dists )) / (- max_curvature )
420+ yaw = origin_yaw - dists
421+
422+ cos_oy = math .cos (- origin_yaw )
423+ sin_oy = math .sin (- origin_yaw )
424+ gdx = cos_oy * ldx + sin_oy * ldy
425+ gdy = - sin_oy * ldx + cos_oy * ldy
398426 x = origin_x + gdx
399427 y = origin_y + gdy
400428
401- return x , y , yaw , 1 if length > 0.0 else - 1
429+ direction = 1 if length > 0 else - 1
430+ return x , y , yaw , np .full_like (dists , direction , dtype = np .int32 )
402431
403432
404433def calc_paths (sx , sy , syaw , gx , gy , gyaw , maxc , step_size ):
@@ -407,19 +436,23 @@ def calc_paths(sx, sy, syaw, gx, gy, gyaw, maxc, step_size):
407436
408437 paths = generate_path (q0 , q1 , maxc , step_size )
409438 for path in paths :
410- xs , ys , yaws , directions = generate_local_course (path .lengths ,
411- path .ctypes , maxc ,
412- step_size )
439+ xs , ys , yaws , directions = generate_local_course (path .lengths , path .ctypes , maxc , step_size )
413440
414441 # convert global coordinate
415- path .x = [math .cos (- q0 [2 ]) * ix + math .sin (- q0 [2 ]) * iy + q0 [0 ] for
416- (ix , iy ) in zip (xs , ys )]
417- path .y = [- math .sin (- q0 [2 ]) * ix + math .cos (- q0 [2 ]) * iy + q0 [1 ] for
418- (ix , iy ) in zip (xs , ys )]
419- path .yaw = [pi_2_pi (yaw + q0 [2 ]) for yaw in yaws ]
420- path .directions = directions
421- path .lengths = [length / maxc for length in path .lengths ]
422- path .L = path .L / maxc
442+ local_pts = np .vstack ([xs , ys , np .ones_like (xs )]) # shape: [3, N]
443+ cos_y = np .cos (syaw )
444+ sin_y = np .sin (syaw )
445+ se2 = np .array ([[cos_y , - sin_y , sx ],[sin_y , cos_y , sy ],[0 , 0 , 1 ]])
446+ global_pts = se2 @ local_pts # shape: [3, N]
447+
448+ path .x = global_pts [0 , :].tolist ()
449+ path .y = global_pts [1 , :].tolist ()
450+
451+ path .yaw = ((yaws + syaw + np .pi ) % (2 * np .pi ) - np .pi ).tolist ()
452+
453+ path .directions = directions .tolist ()
454+ path .lengths = [l / maxc for l in path .lengths ]
455+ path .L /= maxc
423456
424457 return paths
425458
0 commit comments