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