6
6
co-author Videh Patel(@videh25) : Added the missing RS paths
7
7
8
8
"""
9
- import sys
10
9
import pathlib
10
+ import sys
11
+
11
12
sys .path .append (str (pathlib .Path (__file__ ).parent .parent .parent ))
12
13
13
14
import math
15
+ from typing import List , Tuple
14
16
15
17
import matplotlib .pyplot as plt
16
18
import numpy as np
19
+ from numpy .typing import NDArray
20
+
17
21
from utils .angle import angle_mod
18
22
19
23
show_animation = True
@@ -342,63 +346,88 @@ def generate_path(q0, q1, max_curvature, step_size):
342
346
return paths
343
347
344
348
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 ]] = []
347
351
for length in lengths :
348
352
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
+
351
359
interpolate_dists_list .append (interp_dists )
352
360
353
361
return interpolate_dists_list
354
362
355
363
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 ]]:
357
370
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 )
358
376
359
377
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
376
394
377
395
return xs , ys , yaws , directions
378
396
379
397
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 ]]:
382
407
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 )
386
411
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 )
390
415
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
398
426
x = origin_x + gdx
399
427
y = origin_y + gdy
400
428
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 )
402
431
403
432
404
433
def 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):
407
436
408
437
paths = generate_path (q0 , q1 , maxc , step_size )
409
438
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 )
413
440
414
441
# 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
423
456
424
457
return paths
425
458
0 commit comments