44import cvxpy as cp
55
66
7- def solve_car_control (x_final , L = 0.1 , N = 2 , h = 0.1 , gamma = 10 ):
7+ def solve_car_control (x_final , L = 0.1 , N = 10 , h = 0.1 , gamma = 10 ):
88 """
99 Solve the nonlinear optimal control problem for car trajectory planning.
1010
@@ -22,11 +22,12 @@ def solve_car_control(x_final, L=0.1, N=2, h=0.1, gamma=10):
2222
2323 # Variables
2424 # States: x[k] = [p1(k), p2(k), theta(k)]
25- x = cp .Variable ((N + 1 , 3 ))
25+ x = [ cp .Variable (3 ) for _ in range (N + 1 )]
2626 # Controls: u[k] = [s(k), phi(k)]
27- u = cp .Variable (( N , 2 ))
27+ u = [ cp .Variable (2 ) for _ in range ( N )]
2828 # initial guess for controls between 0 and 1
29- u .value = np .random .uniform (0 , 1 , (N , 2 ))
29+ for k in range (N ):
30+ u [k ].value = np .random .uniform (0 , 1 , 2 )
3031 # Initial state (starting at origin with zero orientation)
3132 x_init = np .array ([0 , 0 , 0 ])
3233
@@ -35,45 +36,41 @@ def solve_car_control(x_final, L=0.1, N=2, h=0.1, gamma=10):
3536
3637 # Sum of squared control inputs
3738 for k in range (N ):
38- objective += cp .sum_squares (u [k , :])
39+ objective += cp .sum_squares (u [k ][ :])
3940
4041 # Control smoothness term
4142 for k in range (N - 1 ):
42- objective += gamma * cp .sum_squares (u [k + 1 , :] - u [k , :])
43-
43+ objective += gamma * cp .sum_squares (u [k + 1 ][ :] - u [k ][ :])
44+
4445 # Constraints
4546 constraints = []
46- constraints .append (x [0 , :] == x_init )
47+ constraints .append (x [0 ][ :] == x_init )
4748
4849 for k in range (N ):
4950 # x[k+1] = f(x[k], u[k])
5051 # where f(x, u) = x + h * [u[0]*cos(x[2]), u[0]*sin(x[2]), u[0]*tan(u[1])/L]
5152
5253 # Position dynamics
53- constraints .append (x [k + 1 , 0 ] == x [k , 0 ] + h * u [k , 0 ] * cp .cos (x [k , 2 ]))
54- constraints .append (x [k + 1 , 1 ] == x [k , 1 ] + h * u [k , 0 ] * cp .sin (x [k , 2 ]))
55-
54+ constraints .append (x [k + 1 ][ 0 ] == x [k ][ 0 ] + h * u [k ][ 0 ] * cp .cos (x [k ][ 2 ]))
55+ constraints .append (x [k + 1 ][ 1 ] == x [k ][ 1 ] + h * u [k ][ 0 ] * cp .sin (x [k ][ 2 ]))
56+
5657 # Orientation dynamics
57- constraints .append (x [k + 1 , 2 ] == x [k , 2 ] + h * (u [k , 0 ] / L ) * cp .tan (u [k , 1 ]))
58-
58+ constraints .append (x [k + 1 ][ 2 ] == x [k ][ 2 ] + h * (u [k ][ 0 ] / L ) * cp .tan (u [k ][ 1 ]))
59+
5960 # Final state constraint
60- constraints .append (x [N , :] == x_final )
61-
61+ constraints .append (x [N ][ :] == x_final )
62+
6263 # Steering angle limits (optional but realistic)
6364 # Assuming max steering angle of 45 degrees
6465 max_steering = np .pi / 4
65- constraints .append (u [:, 1 ] >= - max_steering )
66- constraints .append (u [:, 1 ] <= max_steering )
66+ constraints .append (u [:][ 1 ] >= - max_steering )
67+ constraints .append (u [:][ 1 ] <= max_steering )
6768
6869 # Create and solve the problem
6970 problem = cp .Problem (cp .Minimize (objective ), constraints )
7071 problem .solve (solver = cp .IPOPT , nlp = True , verbose = True )
71-
72- # Extract solution
73- x_opt = x .value
74- u_opt = u .value
75-
76- return x_opt , u_opt
72+
73+ return x , u
7774
7875
7976def plot_trajectory (x_opt , u_opt , L , h , title = "Car Trajectory" ):
@@ -82,6 +79,9 @@ def plot_trajectory(x_opt, u_opt, L, h, title="Car Trajectory"):
8279 """
8380 fig , ax = plt .subplots (1 , 1 , figsize = (8 , 8 ))
8481
82+ # Convert x_opt to numpy array for easier indexing
83+ x_opt = np .array ([xi .value for xi in x_opt ])
84+ u_opt = np .array ([ui .value for ui in u_opt ])
8585 # Plot trajectory
8686 ax .plot (x_opt [:, 0 ], x_opt [:, 1 ], 'b-' , linewidth = 2 , label = 'Trajectory' )
8787
@@ -133,35 +133,29 @@ def plot_trajectory(x_opt, u_opt, L, h, title="Car Trajectory"):
133133 # Test cases from the figure
134134 test_cases = [
135135 ((0 , 1 , 0 ), "Move forward to (0, 1)" ),
136- # ((0, 1, np.pi/2), "Move to (0, 1) and turn 90°"),
137- # ((0, 0.5, 0), "Move forward to (0, 0.5)"),
138- # ((0.5, 0.5, -np.pi/2), "Move to (0.5, 0.5) and turn -90°")
136+ ((0 , 1 , np .pi / 2 ), "Move to (0, 1) and turn 90°" ),
137+ ((0 , 0.5 , 0 ), "Move forward to (0, 0.5)" ),
138+ ((0.5 , 0.5 , - np .pi / 2 ), "Move to (0.5, 0.5) and turn -90°" )
139139 ]
140140
141141 # Solve for each test case
142142 for x_final , description in test_cases :
143143 print (f"\n Solving for: { description } " )
144144 print (f"Target state: p1={ x_final [0 ]} , p2={ x_final [1 ]} , theta={ x_final [2 ]:.2f} " )
145-
146- try :
147- x_opt , u_opt = solve_car_control (x_final )
145+ x_opt , u_opt = solve_car_control (x_final )
146+ if x_opt is not None and u_opt is not None :
147+ print ("Optimization successful!" )
148+ print (
149+ f"Final position: p1={ x_opt [- 1 ].value [0 ]:.3f} , "
150+ f"p2={ x_opt [- 1 ].value [1 ]:.3f} , "
151+ f"theta={ x_opt [- 1 ].value [2 ]:.3f} "
152+ )
148153
149- if x_opt is not None and u_opt is not None :
150- print ("Optimization successful!" )
151- print (
152- f"Final position: p1={ x_opt [- 1 , 0 ]:.3f} , "
153- f"p2={ x_opt [- 1 , 1 ]:.3f} , "
154- f"theta={ x_opt [- 1 , 2 ]:.3f} "
155- )
156-
157- # Plot the trajectory
158- fig , ax = plot_trajectory (x_opt , u_opt , L = 0.1 , h = 0.1 , title = description )
159- plt .show ()
160- else :
161- print ("Optimization failed!" )
162-
163- except Exception as e :
164- print (f"Error: { e } " )
154+ # Plot the trajectory
155+ fig , ax = plot_trajectory (x_opt , u_opt , L = 0.1 , h = 0.1 , title = description )
156+ plt .show ()
157+ else :
158+ print ("Optimization failed!" )
165159 """
166160 # Additional analysis: plot control inputs
167161 if x_opt is not None and u_opt is not None:
0 commit comments