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