Skip to content

Commit f8baa15

Browse files
added turn rate and accel limits to planner in
trajectory_generation_dynamics
1 parent d7eae0c commit f8baa15

1 file changed

Lines changed: 144 additions & 0 deletions

File tree

GEMstack/onboard/planning/racing_planning.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,150 @@ def dynamics_constraints(p):
295295

296296
return x_full, y_full, psi_full, c_full, v_full, eps_, final_error
297297

298+
######## more dynamics version
299+
def trajectory_generation_dynamics(init_state, final_state, N=30, Lr=1.5,
300+
a_min=-3.0, a_max=3.0,
301+
eps_min=-0.2, eps_max=0.2,
302+
v_min=2.0, v_max=11.0,
303+
T_min = 0.5, T_max = 1000.0,
304+
waypoints=None, waypoint_penalty_weight=10, waypoint_headings=None):
305+
"""
306+
Generate a dynamically feasible trajectory between init_state and final_state
307+
using curvature-based vehicle dynamics and nonlinear optimization.
308+
309+
Now supports multiple waypoints.
310+
311+
Parameters:
312+
- init_state (dict): Initial vehicle state with keys 'x', 'y', 'psi', 'c', 'v'.
313+
- final_state (dict): Target vehicle state with keys 'x', 'y', 'psi', 'c'.
314+
- N (int): Number of discrete time steps in the trajectory.
315+
- T (float): Duration of each time step (in seconds).
316+
- Lr (float): Distance from the vehicle's center to the rear axle.
317+
- w_c (float): Weight for penalizing curvature (smoothness of turns).
318+
- w_eps (float): Weight for penalizing curvature rate (reduces sharp steering changes).
319+
- w_vvar (float): Weight for penalizing speed variance (encourages speed smoothness).
320+
- w_terminal (float): Weight for penalizing final state deviation (soft constraint).
321+
- v_min (float): Minimum allowed speed (in m/s).
322+
- v_max (float): Maximum allowed speed (in m/s).
323+
- waypoints (list or None): Optional list of (x, y) coordinates that the trajectory should pass near.
324+
- waypoint_penalty_weight (float): Penalty weight for distance from waypoints (soft constraint).
325+
326+
Returns:
327+
- x, y, psi, c, v, eps (np.ndarray): Arrays of optimized state and control values.
328+
- final_error (dict): Final state errors in x, y, psi, and c.
329+
"""
330+
def cost(p):
331+
T_total = p[-1]
332+
return T_total
333+
334+
def dynamics_constraints(p):
335+
# x_, y_, psi_, c_, v_, eps_ = np.split(p, [N - 1, 2 * (N - 1), 3 * (N - 1), 4 * (N - 1), 5 * (N - 1)])
336+
# print("x_: " +str(x_))
337+
split_idx = 5 *(N - 1)
338+
x_, y_, psi_, c_, v_= np.split(p[:split_idx], 5)
339+
340+
a = p[split_idx:split_idx + (N - 1)]
341+
eps = p[split_idx + (N - 1):-1]
342+
T_total = p[-1]
343+
T_k = T_total / (N - 1)
344+
345+
constraints = []
346+
x_prev, y_prev, psi_prev, c_prev, v_prev = init_state['x'], init_state['y'], init_state['psi'], init_state['c'], init_state['v']
347+
348+
for k in range(N - 1):
349+
dx = v_prev * np.cos(psi_prev + c_prev * Lr) * T_k
350+
dy = v_prev * np.sin(psi_prev + c_prev * Lr) * T_k
351+
dpsi = v_prev * c_prev * T_k
352+
dv = a[k] * T_k
353+
dc = eps[k] * T_k
354+
constraints.extend([
355+
x_[k] - (x_prev + dx),
356+
y_[k] - (y_prev + dy),
357+
psi_[k] - (psi_prev + dpsi),
358+
v_[k] - (v_prev + dv),
359+
c_[k] - (c_prev + dc)
360+
])
361+
x_prev, y_prev, psi_prev, c_prev, v_prev = x_[k], y_[k], psi_[k], c_[k], v_[k]
362+
return constraints
363+
364+
def waypoint_penalty(p):
365+
if waypoints is None or len(waypoints) == 0:
366+
return 0.0
367+
368+
split_idx = 5 *(N - 1)
369+
x_, y_, psi_, c_, v_= np.split(p[:split_idx], 5)
370+
# x_ = p[:N -1]
371+
# y_ = p[N - 1:2 * (N-1)]
372+
# psi_ = [ 3 * (N - 1)]
373+
# Calculate equally spaced indices for each waypoint
374+
num_waypoints = len(waypoints)
375+
indices = [int((i + 1) * (N - 1) / (num_waypoints + 1)) for i in range(num_waypoints)]
376+
penalty = 0.0
377+
alignment_threshold = 0.3
378+
# Sum penalties for each waypoint at its corresponding index
379+
for wp_idx, waypoint in enumerate(waypoints):
380+
traj_idx = indices[wp_idx]
381+
penalty += waypoint_penalty_weight * (
382+
(x_[traj_idx] - waypoint[0])**2 + (y_[traj_idx] - waypoint[1])**2
383+
)
384+
return penalty
385+
386+
# Initial guesses
387+
x_vals = np.linspace(init_state['x'], final_state['x'], N)
388+
y_vals = np.linspace(init_state['y'], final_state['y'], N)
389+
psi_vals = np.linspace(init_state['psi'], final_state['psi'], N)
390+
c_vals = np.linspace(init_state['c'], final_state['c'], N)
391+
v_vals = np.ones(N) * init_state['v']
392+
393+
a_vals = np.zeros(N - 1)
394+
eps_vals = np.zeros(N - 1)
395+
T_guess = 60.0
396+
397+
p0 = np.concatenate([x_vals[1:], y_vals[1:], psi_vals[1:], c_vals[1:], v_vals[1:],
398+
a_vals, eps_vals, [T_guess]])
399+
num_vars = len(p0)
400+
bounds = ([(None, None)] * (4 * (N - 1)) +
401+
[(v_min, v_max)] * (N - 1) +
402+
[(a_min, a_max)] * (N - 1) +
403+
[(eps_min, eps_max)] * (N - 1) +
404+
[(T_min, T_max)]
405+
)
406+
def total_cost(p):
407+
return cost(p) + waypoint_penalty(p)
408+
409+
result = minimize(total_cost,
410+
p0,
411+
bounds=bounds,
412+
constraints={'type': 'eq', 'fun': dynamics_constraints},
413+
options={'maxiter': 1000})
414+
415+
# print("result.x:" + str(result.x))
416+
if not result.success:
417+
raise RuntimeError("Optimization failed")
418+
419+
split_idx = 5 *(N - 1)
420+
x_, y_, psi_, c_, v_= np.split(result.x[:split_idx], 5)
421+
422+
a = result.x[split_idx:split_idx + (N - 1)]
423+
eps = result.x[split_idx + (N - 1):-1]
424+
T_total = result.x[-1]
425+
426+
x_full = np.concatenate(([init_state['x']], x_))
427+
y_full = np.concatenate(([init_state['y']], y_))
428+
psi_full = np.concatenate(([init_state['psi']], psi_))
429+
c_full = np.concatenate(([init_state['c']], c_))
430+
v_full = np.concatenate(([init_state['v']], v_))
431+
432+
final_error = {
433+
'x_error': abs(x_full[-1] - final_state['x']),
434+
'y_error': abs(y_full[-1] - final_state['y']),
435+
'psi_error': abs(psi_full[-1] - final_state['psi']),
436+
'c_error': abs(c_full[-1] - final_state['c']),
437+
}
438+
439+
return x_full, y_full, psi_full, c_full, v_full, a, eps, T_total, final_error
440+
#########
441+
298442
def feasibility_check(trajectory, cone_map, car_width=2.0, safety_margin=0.3, v=10.0, Lr=1.5, T=0.1):
299443
"""
300444
Check if the car trajectory collides with any cones.

0 commit comments

Comments
 (0)