15
15
import time
16
16
import os
17
17
18
- #
19
18
# Vehicle steering dynamics
20
- #
21
- # The vehicle dynamics are given by a simple bicycle model. We take the state
22
- # of the system as (x, y, theta) where (x, y) is the position of the vehicle
23
- # in the plane and theta is the angle of the vehicle with respect to
24
- # horizontal. The vehicle input is given by (v, phi) where v is the forward
25
- # velocity of the vehicle and phi is the angle of the steering wheel. The
26
- # model includes saturation of the vehicle steering angle.
27
- #
28
- # System state: x, y, theta
29
- # System input: v, phi
30
- # System output: x, y
31
- # System parameters: wheelbase, maxsteer
32
- #
33
19
def vehicle_update (t ,x ,u ,params ):
34
20
# Get the parameters for the model
35
21
l = params .get ('wheelbase' ,3. )# vehicle wheelbase
@@ -45,14 +31,14 @@ def vehicle_update(t, x, u, params):
45
31
(u [0 ]/ l )* math .tan (phi )# thdot = v/l tan(phi)
46
32
])
47
33
48
-
49
34
def vehicle_output (t ,x ,u ,params ):
50
35
return x # return x, y, theta (full state)
51
36
52
37
vehicle = ct .NonlinearIOSystem (
53
38
vehicle_update ,vehicle_output ,states = 3 ,name = 'vehicle' ,
54
39
inputs = ('v' ,'phi' ),outputs = ('x' ,'y' ,'theta' ))
55
40
41
+ # Initial and final conditions
56
42
x0 = [0. ,- 2. ,0. ];u0 = [10. ,0. ]
57
43
xf = [100. ,2. ,0. ];uf = [10. ,0. ]
58
44
Tf = 10
@@ -63,7 +49,7 @@ def vehicle_output(t, x, u, params):
63
49
# Provide an intial guess (will be extended to entire horizon)
64
50
bend_left = [10 ,0.01 ]# slight left veer
65
51
66
- def time_integrated_cost ():
52
+ def time_steering_integrated_cost ():
67
53
# Set up the cost functions
68
54
Q = np .diag ([.1 ,10 ,.1 ])# keep lateral error low
69
55
R = np .diag ([.1 ,1 ])# minimize applied inputs
@@ -81,7 +67,7 @@ def time_integrated_cost():
81
67
# Only count this as a benchmark if we converged
82
68
assert res .success
83
69
84
- def time_terminal_cost ():
70
+ def time_steering_terminal_cost ():
85
71
# Define cost and constraints
86
72
traj_cost = opt .quadratic_cost (
87
73
vehicle ,None ,np .diag ([0.1 ,1 ]),u0 = uf )
@@ -93,14 +79,35 @@ def time_terminal_cost():
93
79
res = opt .solve_ocp (
94
80
vehicle ,horizon ,x0 ,traj_cost ,constraints ,
95
81
terminal_cost = term_cost ,initial_guess = bend_left ,print_summary = False ,
96
- # solve_ivp_kwargs={'atol': 1e-4, 'rtol': 1e-2},
97
- minimize_method = 'SLSQP' ,minimize_options = {'eps' :0.01 }
82
+ solve_ivp_kwargs = {'atol' :1e-4 ,'rtol' :1e-2 },
83
+ # minimize_method='SLSQP', minimize_options={'eps': 0.01}
84
+ minimize_method = 'trust-constr' ,
85
+ minimize_options = {'finite_diff_rel_step' :0.01 },
98
86
)
99
-
100
87
# Only count this as a benchmark if we converged
101
88
assert res .success
102
89
103
- def time_terminal_constraint ():
90
+ # Define integrator and minimizer methods and options/keywords
91
+ integrator_table = {
92
+ 'RK23_default' : ('RK23' , {'atol' :1e-4 ,'rtol' :1e-2 }),
93
+ 'RK23_sloppy' : ('RK23' , {}),
94
+ 'RK45_default' : ('RK45' , {}),
95
+ 'RK45_sloppy' : ('RK45' , {'atol' :1e-4 ,'rtol' :1e-2 }),
96
+ }
97
+
98
+ minimizer_table = {
99
+ 'trust_default' : ('trust-constr' , {}),
100
+ 'trust_bigstep' : ('trust-constr' , {'finite_diff_rel_step' :0.01 }),
101
+ 'SLSQP_default' : ('SLSQP' , {}),
102
+ 'SLSQP_bigstep' : ('SLSQP' , {'eps' :0.01 }),
103
+ }
104
+
105
+
106
+ def time_steering_terminal_constraint (integrator_name ,minimizer_name ):
107
+ # Get the integrator and minimizer parameters to use
108
+ integrator = integrator_table [integrator_name ]
109
+ minimizer = minimizer_table [minimizer_name ]
110
+
104
111
# Input cost and terminal constraints
105
112
R = np .diag ([1 ,1 ])# minimize applied inputs
106
113
cost = opt .quadratic_cost (vehicle ,np .zeros ((3 ,3 )),R ,u0 = uf )
@@ -111,58 +118,59 @@ def time_terminal_constraint():
111
118
res = opt .solve_ocp (
112
119
vehicle ,horizon ,x0 ,cost ,constraints ,
113
120
terminal_constraints = terminal ,initial_guess = bend_left ,log = False ,
114
- solve_ivp_kwargs = {'atol' :1e-3 ,'rtol' :1e-2 },
115
- # solve_ivp_kwargs={'atol': 1e-4, 'rtol': 1e-2},
116
- minimize_method = 'trust-constr' ,
117
- # minimize_method='SLSQP', minimize_options={'eps': 0.01}
121
+ solve_ivp_method = integrator [0 ],solve_ivp_kwargs = integrator [1 ],
122
+ minimize_method = minimizer [0 ],minimize_options = minimizer [1 ],
118
123
)
119
-
120
124
# Only count this as a benchmark if we converged
121
125
assert res .success
122
126
123
127
# Reset the timeout value to allow for longer runs
124
- time_terminal_constraint .timeout = 120
128
+ time_steering_terminal_constraint .timeout = 120
129
+
130
+ # Parameterize the test against different choices of integrator and minimizer
131
+ time_steering_terminal_constraint .param_names = ['integrator' ,'minimizer' ]
132
+ time_steering_terminal_constraint .params = (
133
+ ['RK23_default' ,'RK23_sloppy' ,'RK45_default' ,'RK45_sloppy' ],
134
+ ['trust_default' ,'trust_bigstep' ,'SLSQP_default' ,'SLSQP_bigstep' ]
135
+ )
125
136
126
- def time_optimal_basis_vehicle ( ):
137
+ def time_steering_bezier_basis ( nbasis , ntimes ):
127
138
# Set up costs and constriants
128
139
Q = np .diag ([.1 ,10 ,.1 ])# keep lateral error low
129
140
R = np .diag ([1 ,1 ])# minimize applied inputs
130
141
cost = opt .quadratic_cost (vehicle ,Q ,R ,x0 = xf ,u0 = uf )
131
142
constraints = [opt .input_range_constraint (vehicle , [0 ,- 0.1 ], [20 ,0.1 ]) ]
132
143
terminal = [opt .state_range_constraint (vehicle ,xf ,xf ) ]
133
- bend_left = [10 ,0.05 ]# slight left veer
134
- near_optimal = [
135
- [1.15073736e+01 ,1.16838616e+01 ,1.15413395e+01 ,
136
- 1.11585544e+01 ,1.06142537e+01 ,9.98718468e+00 ,
137
- 9.35609454e+00 ,8.79973057e+00 ,8.39684004e+00 ,
138
- 8.22617023e+00 ],
139
- [- 9.99830506e-02 ,8.98139594e-03 ,5.26385615e-02 ,
140
- 4.96635954e-02 ,1.87316470e-02 ,- 2.14821345e-02 ,
141
- - 5.23025996e-02 ,- 5.50545990e-02 ,- 1.10629834e-02 ,
142
- 9.83473965e-02 ] ]
143
144
144
145
# Set up horizon
145
- horizon = np .linspace (0 ,Tf ,10 ,endpoint = True )
146
+ horizon = np .linspace (0 ,Tf ,ntimes ,endpoint = True )
146
147
147
148
# Set up the optimal control problem
148
149
res = opt .solve_ocp (
149
150
vehicle ,horizon ,x0 ,cost ,
150
151
constraints ,
151
152
terminal_constraints = terminal ,
152
- initial_guess = near_optimal ,
153
- basis = flat .BezierFamily (4 ,T = Tf ),
153
+ initial_guess = bend_left ,
154
+ basis = flat .BezierFamily (nbasis ,T = Tf ),
155
+ # solve_ivp_kwargs={'atol': 1e-4, 'rtol': 1e-2},
154
156
minimize_method = 'trust-constr' ,
157
+ minimize_options = {'finite_diff_rel_step' :0.01 },
155
158
# minimize_method='SLSQP', minimize_options={'eps': 0.01},
156
- solve_ivp_kwargs = {'atol' :1e-4 ,'rtol' :1e-2 },
157
159
return_states = True ,print_summary = False
158
160
)
159
161
t ,u ,x = res .time ,res .inputs ,res .states
160
162
161
163
# Make sure we found a valid solution
162
164
assert res .success
163
- np .testing .assert_almost_equal (x [:,- 1 ],xf ,decimal = 4 )
164
165
165
- def time_mpc_iosystem ():
166
+ # Reset the timeout value to allow for longer runs
167
+ time_steering_bezier_basis .timeout = 120
168
+
169
+ # Set the parameter values for the number of times and basis vectors
170
+ time_steering_bezier_basis .param_names = ['nbasis' ,'ntimes' ]
171
+ time_steering_bezier_basis .params = ([2 ,4 ,6 ], [5 ,10 ,20 ])
172
+
173
+ def time_aircraft_mpc ():
166
174
# model of an aircraft discretized with 0.2s sampling time
167
175
# Source: https://www.mpt3.org/UI/RegulationProblem
168
176
A = [[0.99 ,0.01 ,0.18 ,- 0.09 ,0 ],