@@ -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+
298442def 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