|
|
|
@ -24,7 +24,7 @@ SOURCES = ['lead0', 'lead1', 'cruise'] |
|
|
|
|
|
|
|
|
|
X_DIM = 3 |
|
|
|
|
U_DIM = 1 |
|
|
|
|
PARAM_DIM= 4 |
|
|
|
|
PARAM_DIM = 4 |
|
|
|
|
COST_E_DIM = 5 |
|
|
|
|
COST_DIM = COST_E_DIM + 1 |
|
|
|
|
CONSTR_DIM = 4 |
|
|
|
@ -34,7 +34,7 @@ X_EGO_COST = 0. |
|
|
|
|
V_EGO_COST = 0. |
|
|
|
|
A_EGO_COST = 0. |
|
|
|
|
J_EGO_COST = 5.0 |
|
|
|
|
A_CHANGE_COST = .5 |
|
|
|
|
A_CHANGE_COST = 200. |
|
|
|
|
DANGER_ZONE_COST = 100. |
|
|
|
|
CRASH_DISTANCE = .5 |
|
|
|
|
LIMIT_COST = 1e6 |
|
|
|
@ -136,7 +136,7 @@ def gen_long_mpc_solver(): |
|
|
|
|
x_ego, |
|
|
|
|
v_ego, |
|
|
|
|
a_ego, |
|
|
|
|
20*(a_ego - prev_a), |
|
|
|
|
a_ego - prev_a, |
|
|
|
|
j_ego] |
|
|
|
|
ocp.model.cost_y_expr = vertcat(*costs) |
|
|
|
|
ocp.model.cost_y_expr_e = vertcat(*costs[:-1]) |
|
|
|
@ -176,7 +176,7 @@ def gen_long_mpc_solver(): |
|
|
|
|
ocp.solver_options.hessian_approx = 'GAUSS_NEWTON' |
|
|
|
|
ocp.solver_options.integrator_type = 'ERK' |
|
|
|
|
ocp.solver_options.nlp_solver_type = 'SQP_RTI' |
|
|
|
|
ocp.solver_options.qp_solver_cond_N = N//4 |
|
|
|
|
ocp.solver_options.qp_solver_cond_N = 1 |
|
|
|
|
|
|
|
|
|
# More iterations take too much time and less lead to inaccurate convergence in |
|
|
|
|
# some situations. Ideally we would run just 1 iteration to ensure fixed runtime. |
|
|
|
@ -197,7 +197,7 @@ class LongitudinalMpc: |
|
|
|
|
self.source = SOURCES[2] |
|
|
|
|
|
|
|
|
|
def reset(self): |
|
|
|
|
self.solver = AcadosOcpSolverFast('long', N, EXPORT_DIR) |
|
|
|
|
self.solver = AcadosOcpSolverFast('long', N) |
|
|
|
|
self.v_solution = np.zeros(N+1) |
|
|
|
|
self.a_solution = np.zeros(N+1) |
|
|
|
|
self.prev_a = np.array(self.a_solution) |
|
|
|
@ -215,7 +215,11 @@ class LongitudinalMpc: |
|
|
|
|
self.status = False |
|
|
|
|
self.crash_cnt = 0.0 |
|
|
|
|
self.solution_status = 0 |
|
|
|
|
# timers |
|
|
|
|
self.solve_time = 0.0 |
|
|
|
|
self.time_qp_solution = 0.0 |
|
|
|
|
self.time_linearization = 0.0 |
|
|
|
|
self.time_integrator = 0.0 |
|
|
|
|
self.x0 = np.zeros(X_DIM) |
|
|
|
|
self.set_weights() |
|
|
|
|
|
|
|
|
@ -232,6 +236,7 @@ class LongitudinalMpc: |
|
|
|
|
a_change_cost = A_CHANGE_COST if prev_accel_constraint else 0 |
|
|
|
|
W = np.asfortranarray(np.diag([X_EGO_OBSTACLE_COST, X_EGO_COST, V_EGO_COST, A_EGO_COST, a_change_cost, J_EGO_COST])) |
|
|
|
|
for i in range(N): |
|
|
|
|
# reduce the cost on (a-a_prev) later in the horizon. |
|
|
|
|
W[4,4] = a_change_cost * np.interp(T_IDXS[i], [0.0, 1.0, 2.0], [1.0, 1.0, 0.0]) |
|
|
|
|
self.solver.cost_set(i, 'W', W) |
|
|
|
|
# Setting the slice without the copy make the array not contiguous, |
|
|
|
@ -257,14 +262,12 @@ class LongitudinalMpc: |
|
|
|
|
self.solver.cost_set(i, 'Zl', Zl) |
|
|
|
|
|
|
|
|
|
def set_cur_state(self, v, a): |
|
|
|
|
if abs(self.x0[1] - v) > 2.: |
|
|
|
|
v_prev = self.x0[1] |
|
|
|
|
self.x0[1] = v |
|
|
|
|
self.x0[2] = a |
|
|
|
|
if abs(v_prev - v) > 2.: # probably only helps if v < v_prev |
|
|
|
|
for i in range(0, N+1): |
|
|
|
|
self.solver.set(i, 'x', self.x0) |
|
|
|
|
else: |
|
|
|
|
self.x0[1] = v |
|
|
|
|
self.x0[2] = a |
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
|
def extrapolate_lead(x_lead, v_lead, a_lead, a_lead_tau): |
|
|
|
@ -355,9 +358,17 @@ class LongitudinalMpc: |
|
|
|
|
self.solver.constraints_set(0, "lbx", self.x0) |
|
|
|
|
self.solver.constraints_set(0, "ubx", self.x0) |
|
|
|
|
|
|
|
|
|
t = sec_since_boot() |
|
|
|
|
self.solution_status = self.solver.solve() |
|
|
|
|
self.solve_time = sec_since_boot() - t |
|
|
|
|
self.solve_time = float(self.solver.get_stats('time_tot')[0]) |
|
|
|
|
self.time_qp_solution = float(self.solver.get_stats('time_qp')[0]) |
|
|
|
|
self.time_linearization = float(self.solver.get_stats('time_lin')[0]) |
|
|
|
|
self.time_integrator = float(self.solver.get_stats('time_sim')[0]) |
|
|
|
|
|
|
|
|
|
# qp_iter = self.solver.get_stats('statistics')[-1][-1] # SQP_RTI specific |
|
|
|
|
# print(f"long_mpc timings: tot {self.solve_time:.2e}, qp {self.time_qp_solution:.2e}, lin {self.time_linearization:.2e}, integrator {self.time_integrator:.2e}, qp_iter {qp_iter}") |
|
|
|
|
# res = self.solver.get_residuals() |
|
|
|
|
# print(f"long_mpc residuals: {res[0]:.2e}, {res[1]:.2e}, {res[2]:.2e}, {res[3]:.2e}") |
|
|
|
|
# self.solver.print_statistics() |
|
|
|
|
|
|
|
|
|
for i in range(N+1): |
|
|
|
|
self.x_sol[i] = self.solver.get(i, 'x') |
|
|
|
@ -370,6 +381,7 @@ class LongitudinalMpc: |
|
|
|
|
|
|
|
|
|
self.prev_a = np.interp(T_IDXS + 0.05, T_IDXS, self.a_solution) |
|
|
|
|
|
|
|
|
|
t = sec_since_boot() |
|
|
|
|
if self.solution_status != 0: |
|
|
|
|
if t > self.last_cloudlog_t + 5.0: |
|
|
|
|
self.last_cloudlog_t = t |
|
|
|
|