PANOC-ALM  quadratic-penalty
Nonconvex constrained optimization
bicycle_model.py
Go to the documentation of this file.
1 import casadi as cs
2 import numpy as np
3 
4 
5 def _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 
69 def _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
148 def 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  )
panocpy.test.f
f
Definition: test.py:49
bicycle_model.generate_problem
def generate_problem(Ts, N_hor, R_obstacle, multipleshooting)
Definition: bicycle_model.py:148