alpaqa 0.0.1
Nonconvex constrained optimization
bicycle_model.py
Go to the documentation of this file.
1import casadi as cs
2import numpy as np
3
4
5def _generate_problem_ss(
6 Ts,
7 N_hor,
8 R_obstacle,
9 n_states,
10 n_inputs,
11 initial_state,
12 desired_state,
13 f,
14 Q,
15 R,
16 states_lb,
17 states_ub,
18 inputs_lb,
19 inputs_ub,
20):
21 objective = 0
22 state_constr = []
23 collision_constr = []
24
25 U = cs.SX.sym("U", n_inputs, N_hor)
26 xk = initial_state
27 # Forward Euler
28 for k in range(N_hor):
29 uk = U[:, k]
30 err = xk - desired_state
31 objective += err.T @ Q @ err + uk.T @ R @ uk
32 next_euler = xk + Ts * f(xk, uk)
33 if k > 0:
34 state_constr = cs.vertcat(state_constr, xk)
35 collision_constr = cs.vertcat(
36 collision_constr, xk[0:2].T @ xk[0:2]
37 ) # ball around (0,0)
38
39 xk = next_euler
40
41 err = xk - desired_state
42 objective += 10 * err.T @ Q @ err # Terminal cost
43 state_constr = cs.vertcat(state_constr, xk)
44 collision_constr = cs.vertcat(collision_constr, xk[0:2].T @ xk[0:2])
45
46 states_constr_lb = np.tile(states_lb, N_hor)
47 states_constr_ub = np.tile(states_ub, N_hor)
48
49 collision_constr_lb = R_obstacle ** 2 * np.ones((N_hor,))
50 collision_constr_ub = +np.inf * np.ones((N_hor,))
51
52 nlp = {
53 "f": objective,
54 "g": cs.vertcat(state_constr, collision_constr),
55 "x": U.reshape((N_hor * n_inputs, 1)),
56 "p": cs.vertcat(initial_state, desired_state),
57 }
58 bounds = {
59 "lbx": np.tile(inputs_lb, N_hor),
60 "ubx": np.tile(inputs_ub, N_hor),
61 "lbg": np.concatenate((states_constr_lb, collision_constr_lb)),
62 "ubg": np.concatenate((states_constr_ub, collision_constr_ub)),
63 }
64 first_input_idx = 0
65
66 return f, nlp, bounds, n_states, n_inputs, first_input_idx
67
68
69def _generate_problem_ms(
70 Ts,
71 N_hor,
72 R_obstacle,
73 n_states,
74 n_inputs,
75 initial_state,
76 desired_state,
77 f,
78 Q,
79 R,
80 states_lb,
81 states_ub,
82 inputs_lb,
83 inputs_ub,
84):
85 X, U = cs.SX.sym("X", n_states, N_hor), cs.SX.sym("U", n_inputs, N_hor)
86 X0X = cs.horzcat(initial_state, X)
87 objective = 0
88 dynamics_constr = []
89 collision_constr = []
90
91 # Forward Euler
92 for k in range(N_hor):
93 xk, uk = X0X[:, k], U[:, k]
94 xkp1 = X0X[:, k + 1]
95 err = xk - desired_state
96 objective += err.T @ Q @ err + uk.T @ R @ uk
97 next_euler = xk + Ts * f(xk, uk)
98 dynamics_constr = cs.vertcat(dynamics_constr, xkp1 - next_euler)
99 if k > 0:
100 collision_constr = cs.vertcat(
101 collision_constr, xk[0:2].T @ xk[0:2]
102 ) # ball around (0,0)
103
104 xN = X0X[:, N_hor]
105 err = xN - desired_state
106 objective += 10 * err.T @ Q @ err # Terminal cost
107 collision_constr = cs.vertcat(collision_constr, xN[0:2].T @ xN[0:2])
108
109 dynamics_constr_lb = np.zeros((N_hor * n_states,))
110 dynamics_constr_ub = np.zeros((N_hor * n_states,))
111
112 collision_constr_lb = R_obstacle ** 2 * np.ones((N_hor,))
113 collision_constr_ub = +np.inf * np.ones((N_hor,))
114
115 assert dynamics_constr_lb.size == dynamics_constr.size1()
116 assert dynamics_constr_ub.size == dynamics_constr.size1()
117 assert collision_constr_lb.size == collision_constr.size1()
118 assert collision_constr_ub.size == collision_constr.size1()
119
120 nlp = {
121 "f": objective,
122 "g": cs.vertcat(dynamics_constr, collision_constr),
123 "x": cs.vertcat(
124 X.reshape((N_hor * n_states, 1)), U.reshape((N_hor * n_inputs, 1))
125 ),
126 "p": cs.vertcat(initial_state, desired_state),
127 }
128 bounds = {
129 "lbx": np.concatenate((np.tile(states_lb, N_hor), np.tile(inputs_lb, N_hor))),
130 "ubx": np.concatenate((np.tile(states_ub, N_hor), np.tile(inputs_ub, N_hor))),
131 "lbg": np.concatenate((dynamics_constr_lb, collision_constr_lb)),
132 "ubg": np.concatenate((dynamics_constr_ub, collision_constr_ub)),
133 }
134 first_input_idx = N_hor * n_states
135
136 return f, nlp, bounds, n_states, n_inputs, first_input_idx
137
138
139# States:
140# [0] p_x longitudinal position
141# [1] p_y lateral position
142# [2] ψ heading angle
143# [3] v longitudinal velocity
144#
145# Inputs:
146# [0] a longitudinal acceleration
147# [1] δ_f steering angle
148def generate_problem(Ts, N_hor, R_obstacle, multipleshooting):
149
150 n_states = 4
151 n_inputs = 2
152
153 initial_state = cs.SX.sym("x0", n_states)
154 desired_state = cs.SX.sym("xd", n_states)
155
156 # state weights matrix
157 Q = cs.diagcat(100, 100, 10, 10)
158 # controls weights matrix
159 R = cs.diagcat(1e-1, 1e-5)
160
161 # physical constants
162 l = 0.5
163 l_r = l / 2
164 l_f = l / 2
165
166 # state and input constraints
167 states_lb = np.array([-10, -10, -np.pi / 3, -3])
168 states_ub = np.array([+10, +10, +np.pi / 3, +3])
169
170 inputs_lb = np.array([-5, -np.pi / 4])
171 inputs_ub = np.array([+5, +np.pi / 4])
172
173 x, u = cs.SX.sym("x", n_states), cs.SX.sym("u", n_inputs)
174 p_x, p_y, ψ, v = cs.vertsplit(x)
175 a, δ_f = cs.vertsplit(u)
176 β = cs.atan(l_r / (l_f + l_r) * cs.tan(δ_f))
177 continuous_dynamics = cs.vertcat(
178 v * cs.cos(ψ + β),
179 v * cs.sin(ψ + β),
180 v / l_r * cs.sin(β),
181 a,
182 )
183 f = cs.Function("f", [x, u], [continuous_dynamics])
184
185 gen = _generate_problem_ms if multipleshooting else _generate_problem_ss
186 return gen(
187 Ts,
188 N_hor,
189 R_obstacle,
190 n_states,
191 n_inputs,
192 initial_state,
193 desired_state,
194 f,
195 Q,
196 R,
197 states_lb,
198 states_ub,
199 inputs_lb,
200 inputs_ub,
201 )
def generate_problem(Ts, N_hor, R_obstacle, multipleshooting)