Apollo 11.0
自动驾驶开放平台
dual_variable_warm_start_ipopt_qp_interface.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
17/*
18 * @file
19 */
20
22
23#include "cyber/common/log.h"
28
29namespace apollo {
30namespace planning {
31
33 size_t horizon,
34 double ts,
35 const Eigen::MatrixXd& ego,
36 const Eigen::MatrixXi& obstacles_edges_num,
37 const size_t obstacles_num,
38 const Eigen::MatrixXd& obstacles_A,
39 const Eigen::MatrixXd& obstacles_b,
40 const Eigen::MatrixXd& xWS,
41 const PlannerOpenSpaceConfig& planner_open_space_config) :
42 ts_(ts),
43 ego_(ego),
44 obstacles_edges_num_(obstacles_edges_num),
45 obstacles_A_(obstacles_A),
46 obstacles_b_(obstacles_b),
47 xWS_(xWS) {
48 ACHECK(horizon < std::numeric_limits<int>::max()) << "Invalid cast on horizon in open space planner";
49 horizon_ = static_cast<int>(horizon);
50 ACHECK(obstacles_num < std::numeric_limits<int>::max()) << "Invalid cast on obstacles_num in open space planner";
51 obstacles_num_ = static_cast<int>(obstacles_num);
52 w_ev_ = ego_(1, 0) + ego_(3, 0);
53 l_ev_ = ego_(0, 0) + ego_(2, 0);
54 g_ = {l_ev_ / 2, w_ev_ / 2, l_ev_ / 2, w_ev_ / 2};
55 offset_ = (ego_(0, 0) + ego_(2, 0)) / 2 - ego_(2, 0);
56 obstacles_edges_sum_ = obstacles_edges_num_.sum();
57 l_start_index_ = 0;
58 n_start_index_ = l_start_index_ + obstacles_edges_sum_ * (horizon_ + 1);
59 l_warm_up_ = Eigen::MatrixXd::Zero(obstacles_edges_sum_, horizon_ + 1);
60 n_warm_up_ = Eigen::MatrixXd::Zero(4 * obstacles_num_, horizon_ + 1);
61 min_safety_distance_ = planner_open_space_config.dual_variable_warm_start_config().min_safety_distance();
62}
63
65 size_t horizon,
66 double ts,
67 const Eigen::MatrixXd& ego,
68 const Eigen::MatrixXi& obstacles_edges_num,
69 const size_t obstacles_num,
70 const Eigen::MatrixXd& obstacles_A,
71 const Eigen::MatrixXd& obstacles_b,
72 const Eigen::MatrixXd& xWS,
73 const DualVariableWarmStartConfig& dual_variable_warm_start_config) :
74 ts_(ts),
75 ego_(ego),
76 obstacles_edges_num_(obstacles_edges_num),
77 obstacles_A_(obstacles_A),
78 obstacles_b_(obstacles_b),
79 xWS_(xWS) {
80 ACHECK(horizon < std::numeric_limits<int>::max()) << "Invalid cast on horizon in open space planner";
81 horizon_ = static_cast<int>(horizon);
82 ACHECK(obstacles_num < std::numeric_limits<int>::max()) << "Invalid cast on obstacles_num in open space planner";
83 obstacles_num_ = static_cast<int>(obstacles_num);
84 w_ev_ = ego_(1, 0) + ego_(3, 0);
85 l_ev_ = ego_(0, 0) + ego_(2, 0);
86 g_ = {l_ev_ / 2, w_ev_ / 2, l_ev_ / 2, w_ev_ / 2};
87 offset_ = (ego_(0, 0) + ego_(2, 0)) / 2 - ego_(2, 0);
88 obstacles_edges_sum_ = obstacles_edges_num_.sum();
89 l_start_index_ = 0;
90 n_start_index_ = l_start_index_ + obstacles_edges_sum_ * (horizon_ + 1);
91 l_warm_up_ = Eigen::MatrixXd::Zero(obstacles_edges_sum_, horizon_ + 1);
92 n_warm_up_ = Eigen::MatrixXd::Zero(4 * obstacles_num_, horizon_ + 1);
93 min_safety_distance_ = dual_variable_warm_start_config.min_safety_distance();
94}
95
97 int& n,
98 int& m,
99 int& nnz_jac_g,
100 int& nnz_h_lag,
101 IndexStyleEnum& index_style) {
102 lambda_horizon_ = obstacles_edges_sum_ * (horizon_ + 1);
103
104 miu_horizon_ = obstacles_num_ * 4 * (horizon_ + 1);
105
106 dual_formulation_horizon_ = obstacles_num_ * (horizon_ + 1);
107
108 num_of_variables_ = lambda_horizon_ + miu_horizon_;
109
110 num_of_constraints_ = 3 * obstacles_num_ * (horizon_ + 1) + num_of_variables_;
111
112 // number of variables
113 n = num_of_variables_;
114
115 // number of constraints
116 m = num_of_constraints_;
117
118 // number of nonzero Jacobian and Lagrangian.
119 generate_tapes(n, m, &nnz_h_lag);
120
121 int tmp = 0;
122 for (int i = 0; i < horizon_ + 1; ++i) {
123 for (int j = 0; j < obstacles_num_; ++j) {
124 int current_edges_num = obstacles_edges_num_(j, 0);
125 tmp += current_edges_num * 3 + 2 + 2 + 4;
126 }
127 }
128 nnz_jac_g = tmp + num_of_variables_;
129
130 ADEBUG << "nnz_jac_g : " << nnz_jac_g;
131 index_style = IndexStyleEnum::C_STYLE;
132 return true;
133}
134
136 int n,
137 bool init_x,
138 double* x,
139 bool init_z,
140 double* z_L,
141 double* z_U,
142 int m,
143 bool init_lambda,
144 double* lambda) {
145 ADEBUG << "get_starting_point";
146 ACHECK(init_x) << "Warm start init_x setting failed";
147 ACHECK(!init_z) << "Warm start init_z setting failed";
148 ACHECK(!init_lambda) << "Warm start init_lambda setting failed";
149
150 int l_index = l_start_index_;
151 int n_index = n_start_index_;
152 ADEBUG << "l_start_index_ : " << l_start_index_;
153 ADEBUG << "n_start_index_ : " << n_start_index_;
154
155 // 1. lagrange constraint l, obstacles_edges_sum_ * (horizon_+1)
156 for (int i = 0; i < horizon_ + 1; ++i) {
157 for (int j = 0; j < obstacles_edges_sum_; ++j) {
158 x[l_index] = 0.5;
159 ++l_index;
160 }
161 }
162
163 // 2. lagrange constraint n, 4*obstacles_num * (horizon_+1)
164 for (int i = 0; i < horizon_ + 1; ++i) {
165 for (int j = 0; j < 4 * obstacles_num_; ++j) {
166 x[n_index] = 1.0;
167 ++n_index;
168 }
169 }
170
171 ADEBUG << "get_starting_point out";
172 return true;
173}
174
176 int n,
177 double* x_l,
178 double* x_u,
179 int m,
180 double* g_l,
181 double* g_u) {
182 int variable_index = 0;
183 // 1. lagrange constraint l, [0, obstacles_edges_sum_ - 1] * [0,
184 // horizon_]
185 for (int i = 0; i < horizon_ + 1; ++i) {
186 for (int j = 0; j < obstacles_edges_sum_; ++j) {
187 x_l[variable_index] = -2e19;
188 x_u[variable_index] = 2e19;
189 ++variable_index;
190 }
191 }
192 ADEBUG << "variable_index after adding lagrange l : " << variable_index;
193
194 // 2. lagrange constraint n, [0, 4*obstacles_num-1] * [0, horizon_]
195 for (int i = 0; i < horizon_ + 1; ++i) {
196 for (int j = 0; j < 4 * obstacles_num_; ++j) {
197 x_l[variable_index] = -2e19;
198 x_u[variable_index] = 2e19; // nlp_upper_bound_limit
199 ++variable_index;
200 }
201 }
202 ADEBUG << "variable_index after adding lagrange n : " << variable_index;
203
204 int constraint_index = 0;
205 for (int i = 0; i < horizon_ + 1; ++i) {
206 for (int j = 0; j < obstacles_num_; ++j) {
207 // a. G'*mu + R'*A*lambda = 0
208 g_l[constraint_index] = 0.0;
209 g_u[constraint_index] = 0.0;
210 g_l[constraint_index + 1] = 0.0;
211 g_u[constraint_index + 1] = 0.0;
212
213 // b. (-g'*mu + (A*t - b)*lambda) >= 0
214 g_l[constraint_index + 2] = min_safety_distance_;
215 g_u[constraint_index + 2] = 2e19;
216 constraint_index += 3;
217 }
218 }
219
220 int l_index = l_start_index_;
221 int n_index = n_start_index_;
222
223 for (int i = 0; i < lambda_horizon_; ++i) {
224 g_l[constraint_index] = 0.0;
225 g_u[constraint_index] = 2e19;
226 constraint_index++;
227 l_index++;
228 }
229 for (int i = 0; i < miu_horizon_; ++i) {
230 g_l[constraint_index] = 0.0;
231 g_u[constraint_index] = 2e19;
232 constraint_index++;
233 n_index++;
234 }
235
236 ADEBUG << "constraint_index after adding obstacles constraints: " << constraint_index;
237
238 return true;
239}
240
241bool DualVariableWarmStartIPOPTQPInterface::eval_f(int n, const double* x, bool new_x, double& obj_value) {
242 eval_obj(n, x, &obj_value);
243 return true;
244}
245
246bool DualVariableWarmStartIPOPTQPInterface::eval_grad_f(int n, const double* x, bool new_x, double* grad_f) {
247 std::fill(grad_f, grad_f + n, 0.0);
248 int l_index = l_start_index_;
249 for (int i = 0; i < horizon_ + 1; ++i) {
250 int edges_counter = 0;
251 // assume: stationary obstacles
252 for (int j = 0; j < obstacles_num_; ++j) {
253 int current_edges_num = obstacles_edges_num_(j, 0);
254 Eigen::MatrixXd Aj = obstacles_A_.block(edges_counter, 0, current_edges_num, 2);
255 Eigen::MatrixXd bj = obstacles_b_.block(edges_counter, 0, current_edges_num, 1);
256
257 // norm(A* lambda)
258 double tmp1 = 0.0;
259 double tmp2 = 0.0;
260 for (int k = 0; k < current_edges_num; ++k) {
261 tmp1 += Aj(k, 0) * x[l_index + k];
262 tmp2 += Aj(k, 1) * x[l_index + k];
263 }
264 for (int k = 0; k < current_edges_num; ++k) {
265 grad_f[l_index + k] += 2.0 * tmp1 * Aj(k, 0) + 2.0 * tmp2 * Aj(k, 1);
266 }
267
268 // Update index
269 edges_counter += current_edges_num;
270 l_index += current_edges_num;
271 }
272 }
273
274 return true;
275}
276
277bool DualVariableWarmStartIPOPTQPInterface::eval_g(int n, const double* x, bool new_x, int m, double* g) {
278 eval_constraints(n, x, m, g);
279 return true;
280}
281
283 int n,
284 const double* x,
285 bool new_x,
286 int m,
287 int nele_jac,
288 int* iRow,
289 int* jCol,
290 double* values) {
291 ADEBUG << "eval_jac_g";
292
293 if (values == nullptr) {
294 int nz_index = 0;
295 int constraint_index = 0;
296
297 // 1. Three obstacles related equal constraints, one equality
298 // constraints,
299 // [0, horizon_] * [0, obstacles_num_-1] * 3
300 int l_index = l_start_index_;
301 int n_index = n_start_index_;
302 for (int i = 0; i < horizon_ + 1; ++i) {
303 for (int j = 0; j < obstacles_num_; ++j) {
304 int current_edges_num = obstacles_edges_num_(j, 0);
305
306 // 1. G' * mu + R' * lambda == 0, part 1
307 // with respect to l
308 for (int k = 0; k < current_edges_num; ++k) {
309 iRow[nz_index] = constraint_index;
310 jCol[nz_index] = l_index + k;
311 ++nz_index;
312 }
313
314 // With respect to n
315 iRow[nz_index] = constraint_index;
316 jCol[nz_index] = n_index;
317 ++nz_index;
318
319 iRow[nz_index] = constraint_index;
320 jCol[nz_index] = n_index + 2;
321 ++nz_index;
322
323 // 2. G' * mu + R' * lambda == 0, part 2
324 // with respect to l
325 for (int k = 0; k < current_edges_num; ++k) {
326 iRow[nz_index] = constraint_index + 1;
327 jCol[nz_index] = l_index + k;
328 ++nz_index;
329 }
330
331 // With respect to n
332 iRow[nz_index] = constraint_index + 1;
333 jCol[nz_index] = n_index + 1;
334 ++nz_index;
335
336 iRow[nz_index] = constraint_index + 1;
337 jCol[nz_index] = n_index + 3;
338 ++nz_index;
339
340 // 3. -g'*mu + (A*t - b)*lambda > 0
341 // with respect to l
342 for (int k = 0; k < current_edges_num; ++k) {
343 iRow[nz_index] = constraint_index + 2;
344 jCol[nz_index] = l_index + k;
345 ++nz_index;
346 }
347
348 // with respect to n
349 for (int k = 0; k < 4; ++k) {
350 iRow[nz_index] = constraint_index + 2;
351 jCol[nz_index] = n_index + k;
352 ++nz_index;
353 }
354
355 // Update index
356 l_index += current_edges_num;
357 n_index += 4;
358 constraint_index += 3;
359 }
360 }
361
362 l_index = l_start_index_;
363 n_index = n_start_index_;
364 for (int i = 0; i < lambda_horizon_; ++i) {
365 iRow[nz_index] = constraint_index;
366 jCol[nz_index] = l_index;
367 ++nz_index;
368 ++constraint_index;
369 ++l_index;
370 }
371 for (int i = 0; i < miu_horizon_; ++i) {
372 iRow[nz_index] = constraint_index;
373 jCol[nz_index] = n_index;
374 ++nz_index;
375 ++constraint_index;
376 ++n_index;
377 }
378
379 CHECK_EQ(constraint_index, m) << "No. of constraints wrong in eval_jac_g.";
380
381 ADEBUG << "nz_index here : " << nz_index << " nele_jac is : " << nele_jac;
382 } else {
383 std::fill(values, values + nele_jac, 0.0);
384 int nz_index = 0;
385
386 // 1. Three obstacles related equal constraints, one equality
387 // constraints,
388 // [0, horizon_] * [0, obstacles_num_-1] * 3
389 int l_index = l_start_index_;
390 int n_index = n_start_index_;
391
392 for (int i = 0; i < horizon_ + 1; ++i) {
393 int edges_counter = 0;
394 for (int j = 0; j < obstacles_num_; ++j) {
395 int current_edges_num = obstacles_edges_num_(j, 0);
396 Eigen::MatrixXd Aj = obstacles_A_.block(edges_counter, 0, current_edges_num, 2);
397 Eigen::MatrixXd bj = obstacles_b_.block(edges_counter, 0, current_edges_num, 1);
398
399 double tmp1 = 0;
400 double tmp2 = 0;
401 for (int k = 0; k < current_edges_num; ++k) {
402 // TODO(QiL) : replace this one directly with x
403 tmp1 += Aj(k, 0) * x[l_index + k];
404 tmp2 += Aj(k, 1) * x[l_index + k];
405 }
406
407 // 1. G' * mu + R' * lambda == 0, part 1
408 // with respect to l
409 for (int k = 0; k < current_edges_num; ++k) {
410 values[nz_index] = std::cos(xWS_(2, i)) * Aj(k, 0) + std::sin(xWS_(2, i)) * Aj(k, 1); // v0~vn
411 ++nz_index;
412 }
413
414 // With respect to n
415 values[nz_index] = 1.0; // w0
416 ++nz_index;
417
418 values[nz_index] = -1.0; // w2
419 ++nz_index;
420
421 ADEBUG << "eval_jac_g, after adding part 2";
422 // 1. G' * mu + R' * lambda == 0, part 2
423
424 // with respect to l
425 for (int k = 0; k < current_edges_num; ++k) {
426 values[nz_index] = -std::sin(xWS_(2, i)) * Aj(k, 0) + std::cos(xWS_(2, i)) * Aj(k, 1); // y0~yn
427 ++nz_index;
428 }
429
430 // With respect to n
431 values[nz_index] = 1.0; // z1
432 ++nz_index;
433
434 values[nz_index] = -1.0; // z3
435 ++nz_index;
436
437 // 2. -g'*mu + (A*t - b)*lambda > 0
438 // TODO(QiL): Revise dual variables modeling here.
439 double tmp3 = 0.0;
440 double tmp4 = 0.0;
441 for (int k = 0; k < 4; ++k) {
442 tmp3 += -g_[k] * x[n_index + k];
443 }
444
445 for (int k = 0; k < current_edges_num; ++k) {
446 tmp4 += bj(k, 0) * x[l_index + k];
447 }
448
449 // with respect to l
450 for (int k = 0; k < current_edges_num; ++k) {
451 values[nz_index] = (xWS_(0, i) + std::cos(xWS_(2, i)) * offset_) * Aj(k, 0)
452 + (xWS_(1, i) + std::sin(xWS_(2, i)) * offset_) * Aj(k, 1) - bj(k, 0); // ddk
453 ++nz_index;
454 }
455
456 // with respect to n
457 for (int k = 0; k < 4; ++k) {
458 values[nz_index] = -g_[k]; // eek
459 ++nz_index;
460 }
461
462 // Update index
463 edges_counter += current_edges_num;
464 l_index += current_edges_num;
465 n_index += 4;
466 }
467 }
468
469 for (int i = 0; i < lambda_horizon_; ++i) {
470 values[nz_index] = 1.0;
471 ++nz_index;
472 }
473 for (int i = 0; i < miu_horizon_; ++i) {
474 values[nz_index] = 1.0;
475 ++nz_index;
476 }
477
478 ADEBUG << "eval_jac_g, fulfilled obstacle constraint values";
479 CHECK_EQ(nz_index, nele_jac);
480 }
481
482 ADEBUG << "eval_jac_g done";
483 return true;
484}
485
487 int n,
488 const double* x,
489 bool new_x,
490 double obj_factor,
491 int m,
492 const double* lambda,
493 bool new_lambda,
494 int nele_hess,
495 int* iRow,
496 int* jCol,
497 double* values) {
498 if (values == nullptr) {
499 // return the structure. This is a symmetric matrix, fill the lower left
500 // triangle only.
501 for (int idx = 0; idx < nnz_L; idx++) {
502 iRow[idx] = rind_L[idx];
503 jCol[idx] = cind_L[idx];
504 }
505 } else {
506 // return the values. This is a symmetric matrix, fill the lower left
507 // triangle only
508 obj_lam[0] = obj_factor;
509 for (int idx = 0; idx < m; idx++) {
510 obj_lam[1 + idx] = lambda[idx];
511 }
512 set_param_vec(tag_L, m + 1, obj_lam);
513 sparse_hess(tag_L, n, 1, const_cast<double*>(x), &nnz_L, &rind_L, &cind_L, &hessval, options_L);
514
515 for (int idx = 0; idx < nnz_L; idx++) {
516 values[idx] = hessval[idx];
517 }
518 }
519
520 return true;
521}
522
524 Ipopt::SolverReturn status,
525 int n,
526 const double* x,
527 const double* z_L,
528 const double* z_U,
529 int m,
530 const double* g,
531 const double* lambda,
532 double obj_value,
533 const Ipopt::IpoptData* ip_data,
534 Ipopt::IpoptCalculatedQuantities* ip_cq) {
535 int variable_index = 0;
536 // 1. lagrange constraint l, [0, obstacles_edges_sum_ - 1] * [0,
537 // horizon_]
538 for (int i = 0; i < horizon_ + 1; ++i) {
539 for (int j = 0; j < obstacles_edges_sum_; ++j) {
540 l_warm_up_(j, i) = x[variable_index];
541 ++variable_index;
542 }
543 }
544 ADEBUG << "variable_index after adding lagrange l : " << variable_index;
545
546 // 2. lagrange constraint n, [0, 4*obstacles_num-1] * [0, horizon_]
547 for (int i = 0; i < horizon_ + 1; ++i) {
548 for (int j = 0; j < 4 * obstacles_num_; ++j) {
549 n_warm_up_(j, i) = x[variable_index];
550 ++variable_index;
551 }
552 }
553 ADEBUG << "variable_index after adding lagrange n : " << variable_index;
554
555 // memory deallocation of ADOL-C variables
556 delete[] obj_lam;
557 free(rind_L);
558 free(cind_L);
559 free(hessval);
560}
561
563 Eigen::MatrixXd* l_warm_up,
564 Eigen::MatrixXd* n_warm_up) const {
565 *l_warm_up = l_warm_up_;
566 *n_warm_up = n_warm_up_;
567}
568
570 const Eigen::MatrixXd& l_warm_up,
571 const Eigen::MatrixXd& n_warm_up) {
572 // wrap input solution
573 int kNumVariables = num_of_variables_;
574 double x[kNumVariables];
575 int variable_index = 0;
576 // 1. lagrange constraint l, [0, obstacles_edges_sum_ - 1] * [0,
577 // horizon_]
578 for (int i = 0; i < horizon_ + 1; ++i) {
579 for (int j = 0; j < obstacles_edges_sum_; ++j) {
580 x[variable_index] = l_warm_up(j, i);
581 ++variable_index;
582 }
583 }
584
585 // 2. lagrange constraint n, [0, 4*obstacles_num-1] * [0, horizon_]
586 for (int i = 0; i < horizon_ + 1; ++i) {
587 for (int j = 0; j < 4 * obstacles_num_; ++j) {
588 x[variable_index] = n_warm_up(j, i);
589 ++variable_index;
590 }
591 }
592
593 // evaluate constraints
594 int kNumConstraint = num_of_constraints_;
595 double g[kNumConstraint];
596 eval_g(num_of_variables_, x, true, num_of_constraints_, g);
597
598 // get the boundaries
599 double x_l[kNumVariables];
600 double x_u[kNumVariables];
601 double g_l[kNumConstraint];
602 double g_u[kNumConstraint];
603 get_bounds_info(num_of_variables_, x_l, x_u, num_of_constraints_, g_l, g_u);
604
605 // compare g with g_l & g_u
606 int constraint_index = 0;
607
608 for (int i = 0; i < horizon_ + 1; ++i) {
609 for (int j = 0; j < obstacles_num_; ++j) {
610 // G' * mu + R' * A * lambda == 0
611 if (g_l[constraint_index + 0] > g[constraint_index + 0]
612 || g_u[constraint_index + 0] < g[constraint_index + 0]) {
613 AERROR << "G' * mu + R' * A * lambda == 0 constraint fails, "
614 << "constraint_index: " << constraint_index + 0 << ", g: " << g[constraint_index + 0];
615 }
616
617 if (g_l[constraint_index + 1] > g[constraint_index + 1]
618 || g_u[constraint_index + 1] < g[constraint_index + 1]) {
619 AERROR << "G' * mu + R' * A * lambda == 0 constraint fails, "
620 << "constraint_index: " << constraint_index + 1 << ", g: " << g[constraint_index + 1];
621 }
622
623 // -g' * mu + (A * t - b) * lambda) >= d_min
624 if (g_l[constraint_index + 2] > g[constraint_index + 2]
625 || g_u[constraint_index + 2] < g[constraint_index + 2]) {
626 AERROR << "-g' * mu + (A * t - b) * lambda) >= d_min constraint fails, "
627 << "constraint_index: " << constraint_index + 2 << ", g: " << g[constraint_index + 2];
628 }
629
630 // Update index
631 constraint_index += 3;
632 }
633 }
634
635 for (int i = 0; i < lambda_horizon_; ++i) {
636 if (g_l[constraint_index] > g[constraint_index] || g_u[constraint_index] < g[constraint_index]) {
637 AERROR << "lambda box constraint fails, "
638 << "constraint_index: " << constraint_index << ", g: " << g[constraint_index];
639 }
640
641 constraint_index++;
642 }
643
644 for (int i = 0; i < miu_horizon_; ++i) {
645 if (g_l[constraint_index] > g[constraint_index] || g_u[constraint_index] < g[constraint_index]) {
646 AERROR << "miu box constraint fails, "
647 << "constraint_index: " << constraint_index << ", g: " << g[constraint_index];
648 }
649 constraint_index++;
650 }
651}
652
653//*************** start ADOL-C part ***********************************
655template <class T>
656bool DualVariableWarmStartIPOPTQPInterface::eval_obj(int n, const T* x, T* obj_value) {
657 ADEBUG << "eval_obj";
658 *obj_value = 0.0;
659 int l_index = l_start_index_;
660 for (int i = 0; i < horizon_ + 1; ++i) {
661 int edges_counter = 0;
662 // assume: stationary obstacles
663 for (int j = 0; j < obstacles_num_; ++j) {
664 int current_edges_num = obstacles_edges_num_(j, 0);
665 Eigen::MatrixXd Aj = obstacles_A_.block(edges_counter, 0, current_edges_num, 2);
666 Eigen::MatrixXd bj = obstacles_b_.block(edges_counter, 0, current_edges_num, 1);
667
668 // norm(A* lambda) <= 1
669 T tmp1 = 0.0;
670 T tmp2 = 0.0;
671 for (int k = 0; k < current_edges_num; ++k) {
672 tmp1 += Aj(k, 0) * x[l_index + k];
673 tmp2 += Aj(k, 1) * x[l_index + k];
674 }
675 *obj_value += tmp1 * tmp1 + tmp2 * tmp2;
676
677 // Update index
678 edges_counter += current_edges_num;
679 l_index += current_edges_num;
680 }
681 }
682
683 return true;
684}
685
687template <class T>
689 ADEBUG << "eval_constraints";
690 // state start index
691
692 // 1. Three obstacles related equal constraints, one equality constraints,
693 // [0, horizon_] * [0, obstacles_num_-1] * 4
694
695 int l_index = l_start_index_;
696 int n_index = n_start_index_;
697 int constraint_index = 0;
698
699 for (int i = 0; i < horizon_ + 1; ++i) {
700 int edges_counter = 0;
701 // assume: stationary obstacles
702 for (int j = 0; j < obstacles_num_; ++j) {
703 int current_edges_num = obstacles_edges_num_(j, 0);
704 Eigen::MatrixXd Aj = obstacles_A_.block(edges_counter, 0, current_edges_num, 2);
705 Eigen::MatrixXd bj = obstacles_b_.block(edges_counter, 0, current_edges_num, 1);
706
707 // A * lambda
708 T tmp1 = 0.0;
709 T tmp2 = 0.0;
710 for (int k = 0; k < current_edges_num; ++k) {
711 tmp1 += Aj(k, 0) * x[l_index + k];
712 tmp2 += Aj(k, 1) * x[l_index + k];
713 }
714
715 // G' * mu + R' * A * lambda == 0
716 g[constraint_index + 0] = x[n_index] - x[n_index + 2] + cos(xWS_(2, i)) * tmp1 + sin(xWS_(2, i)) * tmp2;
717
718 g[constraint_index + 1] = x[n_index + 1] - x[n_index + 3] - sin(xWS_(2, i)) * tmp1 + cos(xWS_(2, i)) * tmp2;
719
720 // (-g' * mu + (A * t - b) * lambda) >= d_min
721 T tmp3 = 0.0;
722 for (int k = 0; k < 4; ++k) {
723 tmp3 += g_[k] * x[n_index + k];
724 }
725
726 T tmp4 = 0.0;
727 for (int k = 0; k < current_edges_num; ++k) {
728 tmp4 += bj(k, 0) * x[l_index + k];
729 }
730
731 g[constraint_index + 2] = -tmp3 + (xWS_(0, i) + cos(xWS_(2, i)) * offset_) * tmp1
732 + (xWS_(1, i) + sin(xWS_(2, i)) * offset_) * tmp2 - tmp4;
733
734 // Update index
735 edges_counter += current_edges_num;
736 l_index += current_edges_num;
737 n_index += 4;
738 constraint_index += 3;
739 }
740 }
741 l_index = l_start_index_;
742 n_index = n_start_index_;
743 for (int i = 0; i < lambda_horizon_; ++i) {
744 g[constraint_index] = x[l_index];
745 constraint_index++;
746 l_index++;
747 }
748 for (int i = 0; i < miu_horizon_; ++i) {
749 g[constraint_index] = x[n_index];
750 constraint_index++;
751 n_index++;
752 }
753
754 CHECK_EQ(constraint_index, m) << "No. of constraints wrong in eval_g. n : " << n;
755 return true;
756}
757
760 std::vector<double> xp(n);
761 std::vector<double> lamp(m);
762 std::vector<double> zl(m);
763 std::vector<double> zu(m);
764
765 std::vector<adouble> xa(n);
766 std::vector<adouble> g(m);
767 std::vector<double> lam(m);
768
769 double sig = 0.0;
770 adouble obj_value;
771
772 double dummy = 0.0;
773
774 obj_lam = new double[m + 1];
775
776 get_starting_point(n, 1, &xp[0], 0, &zl[0], &zu[0], m, 0, &lamp[0]);
777
778 // trace_on(tag_f);
779
780 // for (int idx = 0; idx < n; idx++) xa[idx] <<= xp[idx];
781
782 // eval_obj(n, xa, &obj_value);
783
784 // obj_value >>= dummy;
785
786 // trace_off();
787
788 // trace_on(tag_g);
789
790 // for (int idx = 0; idx < n; idx++) xa[idx] <<= xp[idx];
791
792 // eval_constraints(n, xa, m, g);
793
794 // for (int idx = 0; idx < m; idx++) g[idx] >>= dummy;
795
796 // trace_off();
797
798 trace_on(tag_L);
799
800 for (int idx = 0; idx < n; idx++) {
801 xa[idx] <<= xp[idx];
802 }
803 for (int idx = 0; idx < m; idx++) {
804 lam[idx] = 1.0;
805 }
806 sig = 1.0;
807
808 eval_obj(n, &xa[0], &obj_value);
809
810 obj_value *= mkparam(sig);
811 eval_constraints(n, &xa[0], m, &g[0]);
812
813 for (int idx = 0; idx < m; idx++) {
814 obj_value += g[idx] * mkparam(lam[idx]);
815 }
816
817 obj_value >>= dummy;
818
819 trace_off();
820
821 rind_L = nullptr;
822 cind_L = nullptr;
823
824 hessval = nullptr;
825
826 options_L[0] = 0;
827 options_L[1] = 1;
828
829 sparse_hess(tag_L, n, 0, &xp[0], &nnz_L, &rind_L, &cind_L, &hessval, options_L);
830 *nnz_h_lag = nnz_L;
831}
832//*************** end ADOL-C part ***********************************
833
834} // namespace planning
835} // namespace apollo
bool eval_h(int n, const double *x, bool new_x, double obj_factor, int m, const double *lambda, bool new_lambda, int nele_hess, int *iRow, int *jCol, double *values) override
Method to return: 1) The structure of the hessian of the lagrangian (if "values" is nullptr) 2) The v...
void generate_tapes(int n, int m, int *nnz_h_lag)
Method to generate the required tapes
bool eval_g(int n, const double *x, bool new_x, int m, double *g) override
Method to return the constraint residuals
bool get_bounds_info(int n, double *x_l, double *x_u, int m, double *g_l, double *g_u) override
Method to return the bounds for my problem
DualVariableWarmStartIPOPTQPInterface(size_t horizon, double ts, const Eigen::MatrixXd &ego, const Eigen::MatrixXi &obstacles_edges_num, const size_t obstacles_num, const Eigen::MatrixXd &obstacles_A, const Eigen::MatrixXd &obstacles_b, const Eigen::MatrixXd &xWS, const PlannerOpenSpaceConfig &planner_open_space_config)
bool eval_grad_f(int n, const double *x, bool new_x, double *grad_f) override
Method to return the gradient of the objective
void finalize_solution(Ipopt::SolverReturn status, int n, const double *x, const double *z_L, const double *z_U, int m, const double *g, const double *lambda, double obj_value, const Ipopt::IpoptData *ip_data, Ipopt::IpoptCalculatedQuantities *ip_cq) override
This method is called when the algorithm is complete so the TNLP can store/write the solution
bool eval_f(int n, const double *x, bool new_x, double &obj_value) override
Method to return the objective value
bool eval_constraints(int n, const T *x, int m, T *g)
Template to compute constraints
bool eval_jac_g(int n, const double *x, bool new_x, int m, int nele_jac, int *iRow, int *jCol, double *values) override
Method to return: 1) The structure of the jacobian (if "values" is nullptr) 2) The values of the jaco...
void get_optimization_results(Eigen::MatrixXd *l_warm_up, Eigen::MatrixXd *n_warm_up) const
bool get_nlp_info(int &n, int &m, int &nnz_jac_g, int &nnz_h_lag, IndexStyleEnum &index_style) override
Method to return some info about the nlp
void check_solution(const Eigen::MatrixXd &l_warm_up, const Eigen::MatrixXd &n_warm_up)
bool get_starting_point(int n, bool init_x, double *x, bool init_z, double *z_L, double *z_U, int m, bool init_lambda, double *lambda) override
Method to return the starting point for the algorithm
bool eval_obj(int n, const T *x, T *obj_value)
Template to return the objective value
Planning module main class.
Math-related util functions.
#define tag_L
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
Some util functions.
class register implement
Definition arena_queue.h:37
optional DualVariableWarmStartConfig dual_variable_warm_start_config