Apollo 11.0
自动驾驶开放平台
fem_pos_deviation_ipopt_interface.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2019 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
22
23#include "cyber/common/log.h"
24
25namespace apollo {
26namespace planning {
27
29 std::vector<std::pair<double, double>> points, std::vector<double> bounds) {
30 CHECK_GT(points.size(), 1U);
31 CHECK_GT(bounds.size(), 1U);
32 bounds_around_refs_ = std::move(bounds);
33 ref_points_ = std::move(points);
34 num_of_points_ = ref_points_.size();
35}
36
38 std::vector<double>* ptr_x, std::vector<double>* ptr_y) const {
39 *ptr_x = opt_x_;
40 *ptr_y = opt_y_;
41}
42
43bool FemPosDeviationIpoptInterface::get_nlp_info(int& n, int& m, int& nnz_jac_g,
44 int& nnz_h_lag,
45 IndexStyleEnum& index_style) {
46 CHECK_GT(num_of_points_, 3U);
47 // Number of variables
48 // Variables include 2D points and curvature constraints slack variable
49 num_of_slack_var_ = num_of_points_ - 2;
50 n = static_cast<int>(num_of_points_ * 2 + num_of_slack_var_);
51 num_of_variables_ = n;
52
53 // Number of constraints
54 // Constraints includes positional constraints, curvature constraints and
55 // slack variable constraints
56 num_of_curvature_constr_ = num_of_points_ - 2;
57 num_of_slack_constr_ = num_of_points_ - 2;
58 m = static_cast<int>(num_of_points_ * 2 + num_of_curvature_constr_ +
59 num_of_slack_constr_);
60 num_of_constraints_ = m;
61
62 // Indexes for variables and constraints,
63 // Start index is actual first index and end index is one index after the
64 // actual final index
65 slack_var_start_index_ = num_of_points_ * 2;
66 slack_var_end_index_ = slack_var_start_index_ + num_of_slack_var_;
67 curvature_constr_start_index_ = num_of_points_ * 2;
68 curvature_constr_end_index_ =
69 curvature_constr_start_index_ + num_of_curvature_constr_;
70 slack_constr_start_index_ = curvature_constr_end_index_;
71 slack_constr_end_index_ = slack_constr_start_index_ + num_of_slack_constr_;
72
73 generate_tapes(n, m, &nnz_jac_g, &nnz_h_lag);
74
75 index_style = IndexStyleEnum::C_STYLE;
76 return true;
77}
78
80 double* x_u, int m,
81 double* g_l, double* g_u) {
82 CHECK_EQ(static_cast<size_t>(n), num_of_variables_);
83 CHECK_EQ(static_cast<size_t>(m), num_of_constraints_);
84 // variables
85 // a. for x, y
86 for (size_t i = 0; i < num_of_points_; ++i) {
87 size_t index = i * 2;
88 // x
89 x_l[index] = -1e20;
90 x_u[index] = 1e20;
91
92 // y
93 x_l[index + 1] = -1e20;
94 x_u[index + 1] = 1e20;
95 }
96 // b. for slack var
97 for (size_t i = slack_var_start_index_; i < slack_var_end_index_; ++i) {
98 x_l[i] = -1e20;
99 x_u[i] = 1e20;
100 }
101
102 // constraints
103 // a. positional deviation constraints
104 for (size_t i = 0; i < num_of_points_; ++i) {
105 size_t index = i * 2;
106 // x
107 g_l[index] = ref_points_[i].first - bounds_around_refs_[i];
108 g_u[index] = ref_points_[i].first + bounds_around_refs_[i];
109
110 // y
111 g_l[index + 1] = ref_points_[i].second - bounds_around_refs_[i];
112 g_u[index + 1] = ref_points_[i].second + bounds_around_refs_[i];
113 }
114
115 // b. curvature constraints
116 double ref_total_length = 0.0;
117 auto pre_point = ref_points_.front();
118 for (size_t i = 1; i < num_of_points_; ++i) {
119 auto cur_point = ref_points_[i];
120 double x_diff = cur_point.first - pre_point.first;
121 double y_diff = cur_point.second - pre_point.second;
122 ref_total_length += std::sqrt(x_diff * x_diff + y_diff * y_diff);
123 pre_point = cur_point;
124 }
125 double average_delta_s =
126 ref_total_length / static_cast<double>(num_of_points_ - 1);
127 double curvature_constr_upper =
128 average_delta_s * average_delta_s * curvature_constraint_;
129
130 for (size_t i = curvature_constr_start_index_;
131 i < curvature_constr_end_index_; ++i) {
132 g_l[i] = -1e20;
133 g_u[i] = curvature_constr_upper * curvature_constr_upper;
134 }
135
136 // c. slack var constraints
137 for (size_t i = slack_constr_start_index_; i < slack_constr_end_index_; ++i) {
138 g_l[i] = 0.0;
139 g_u[i] = 1e20;
140 }
141
142 return true;
143}
144
146 double* x, bool init_z,
147 double* z_L, double* z_U,
148 int m, bool init_lambda,
149 double* lambda) {
150 CHECK_EQ(static_cast<size_t>(n), num_of_variables_);
151 for (size_t i = 0; i < num_of_points_; ++i) {
152 size_t index = i * 2;
153 x[index] = ref_points_[i].first;
154 x[index + 1] = ref_points_[i].second;
155 }
156
157 for (size_t i = slack_var_start_index_; i < slack_var_end_index_; ++i) {
158 x[i] = 0.0;
159 }
160
161 return true;
162}
163
164bool FemPosDeviationIpoptInterface::eval_f(int n, const double* x, bool new_x,
165 double& obj_value) {
166 CHECK_EQ(static_cast<size_t>(n), num_of_variables_);
167
168 eval_obj(n, x, &obj_value);
169 return true;
170}
171
173 bool new_x, double* grad_f) {
174 CHECK_EQ(static_cast<size_t>(n), num_of_variables_);
175
176 gradient(tag_f, n, x, grad_f);
177 return true;
178}
179
180bool FemPosDeviationIpoptInterface::eval_g(int n, const double* x, bool new_x,
181 int m, double* g) {
182 CHECK_EQ(static_cast<size_t>(n), num_of_variables_);
183 CHECK_EQ(static_cast<size_t>(m), num_of_constraints_);
184
185 eval_constraints(n, x, m, g);
186 return true;
187}
188
190 bool new_x, int m, int nele_jac,
191 int* iRow, int* jCol,
192 double* values) {
193 CHECK_EQ(static_cast<size_t>(n), num_of_variables_);
194 CHECK_EQ(static_cast<size_t>(m), num_of_constraints_);
195
196 if (values == nullptr) {
197 // return the structure of the jacobian
198 for (int idx = 0; idx < nnz_jac_; idx++) {
199 iRow[idx] = rind_g_[idx];
200 jCol[idx] = cind_g_[idx];
201 }
202 } else {
203 // return the values of the jacobian of the constraints
204 sparse_jac(tag_g, m, n, 1, x, &nnz_jac_, &rind_g_, &cind_g_, &jacval_,
205 options_g_);
206 for (int idx = 0; idx < nnz_jac_; idx++) {
207 values[idx] = jacval_[idx];
208 }
209 }
210 return true;
211}
212
213bool FemPosDeviationIpoptInterface::eval_h(int n, const double* x, bool new_x,
214 double obj_factor, int m,
215 const double* lambda,
216 bool new_lambda, int nele_hess,
217 int* iRow, int* jCol,
218 double* values) {
219 if (values == nullptr) {
220 // return the structure. This is a symmetric matrix, fill the lower left
221 // triangle only.
222 for (int idx = 0; idx < nnz_L_; idx++) {
223 iRow[idx] = rind_L_[idx];
224 jCol[idx] = cind_L_[idx];
225 }
226 } else {
227 // return the values. This is a symmetric matrix, fill the lower left
228 // triangle only
229 obj_lam_[0] = obj_factor;
230 for (int idx = 0; idx < m; idx++) {
231 obj_lam_[1 + idx] = lambda[idx];
232 }
233 set_param_vec(tag_L, m + 1, &obj_lam_[0]);
234 sparse_hess(tag_L, n, 1, const_cast<double*>(x), &nnz_L_, &rind_L_,
235 &cind_L_, &hessval_, options_L_);
236
237 for (int idx = 0; idx < nnz_L_; idx++) {
238 values[idx] = hessval_[idx];
239 }
240 }
241 return true;
242}
243
245 Ipopt::SolverReturn status, int n, const double* x, const double* z_L,
246 const double* z_U, int m, const double* g, const double* lambda,
247 double obj_value, const Ipopt::IpoptData* ip_data,
248 Ipopt::IpoptCalculatedQuantities* ip_cq) {
249 opt_x_.reserve(num_of_points_);
250 opt_y_.reserve(num_of_points_);
251 for (size_t i = 0; i < num_of_points_; ++i) {
252 size_t index = i * 2;
253 opt_x_.emplace_back(x[index]);
254 opt_y_.emplace_back(x[index + 1]);
255 }
256 free(rind_g_);
257 free(cind_g_);
258 free(rind_L_);
259 free(cind_L_);
260 free(jacval_);
261 free(hessval_);
262}
263
264//*************** start ADOL-C part ***********************************
265
267template <class T>
268bool FemPosDeviationIpoptInterface::eval_obj(int n, const T* x, T* obj_value) {
269 *obj_value = 0.0;
270
271 // Distance to refs
272 for (size_t i = 0; i < num_of_points_; ++i) {
273 size_t index = i * 2;
274 *obj_value +=
275 weight_ref_deviation_ *
276 ((x[index] - ref_points_[i].first) * (x[index] - ref_points_[i].first) +
277 (x[index + 1] - ref_points_[i].second) *
278 (x[index + 1] - ref_points_[i].second));
279 }
280
281 // Fem_pos_deviation
282 for (size_t i = 0; i + 2 < num_of_points_; ++i) {
283 size_t findex = i * 2;
284 size_t mindex = findex + 2;
285 size_t lindex = mindex + 2;
286
287 *obj_value += weight_fem_pos_deviation_ *
288 (((x[findex] + x[lindex]) - 2.0 * x[mindex]) *
289 ((x[findex] + x[lindex]) - 2.0 * x[mindex]) +
290 ((x[findex + 1] + x[lindex + 1]) - 2.0 * x[mindex + 1]) *
291 ((x[findex + 1] + x[lindex + 1]) - 2.0 * x[mindex + 1]));
292 }
293
294 // Total length
295 for (size_t i = 0; i + 1 < num_of_points_; ++i) {
296 size_t findex = i * 2;
297 size_t nindex = findex + 2;
298 *obj_value +=
299 weight_path_length_ *
300 ((x[findex] - x[nindex]) * (x[findex] - x[nindex]) +
301 (x[findex + 1] - x[nindex + 1]) * (x[findex + 1] - x[nindex + 1]));
302 }
303
304 // Slack variable minimization
305 for (size_t i = slack_var_start_index_; i < slack_var_end_index_; ++i) {
306 *obj_value += weight_curvature_constraint_slack_var_ * x[i];
307 }
308
309 return true;
310}
311
313template <class T>
315 T* g) {
316 // a. positional deviation constraints
317 for (size_t i = 0; i < num_of_points_; ++i) {
318 size_t index = i * 2;
319 g[index] = x[index];
320 g[index + 1] = x[index + 1];
321 }
322
323 // b. curvature constraints
324 for (size_t i = 0; i + 2 < num_of_points_; ++i) {
325 size_t findex = i * 2;
326 size_t mindex = findex + 2;
327 size_t lindex = mindex + 2;
328 g[curvature_constr_start_index_ + i] =
329 (((x[findex] + x[lindex]) - 2.0 * x[mindex]) *
330 ((x[findex] + x[lindex]) - 2.0 * x[mindex]) +
331 ((x[findex + 1] + x[lindex + 1]) - 2.0 * x[mindex + 1]) *
332 ((x[findex + 1] + x[lindex + 1]) - 2.0 * x[mindex + 1])) -
333 x[slack_var_start_index_ + i];
334 }
335
336 // c. slack var constraints
337 size_t slack_var_index = 0;
338 for (size_t i = slack_constr_start_index_; i < slack_constr_end_index_; ++i) {
339 g[i] = x[slack_var_start_index_ + slack_var_index];
340 ++slack_var_index;
341 }
342 return true;
343}
344
346void FemPosDeviationIpoptInterface::generate_tapes(int n, int m, int* nnz_jac_g,
347 int* nnz_h_lag) {
348 std::vector<double> xp(n, 0.0);
349 std::vector<double> lamp(m, 0.0);
350 std::vector<double> zl(m, 0.0);
351 std::vector<double> zu(m, 0.0);
352 std::vector<adouble> xa(n, 0.0);
353 std::vector<adouble> g(m, 0.0);
354 std::vector<double> lam(m, 0.0);
355
356 double sig = 0.0;
357 adouble obj_value;
358
359 double dummy = 0.0;
360 obj_lam_.clear();
361 obj_lam_.resize(m + 1, 0.0);
362 get_starting_point(n, 1, &xp[0], 0, &zl[0], &zu[0], m, 0, &lamp[0]);
363
364 // Trace on Objectives
365 trace_on(tag_f);
366 for (int idx = 0; idx < n; idx++) {
367 xa[idx] <<= xp[idx];
368 }
369 eval_obj(n, &xa[0], &obj_value);
370 obj_value >>= dummy;
371 trace_off();
372
373 // Trace on Jacobian
374 trace_on(tag_g);
375 for (int idx = 0; idx < n; idx++) {
376 xa[idx] <<= xp[idx];
377 }
378 eval_constraints(n, &xa[0], m, &g[0]);
379 for (int idx = 0; idx < m; idx++) {
380 g[idx] >>= dummy;
381 }
382 trace_off();
383
384 // Trace on Hessian
385 trace_on(tag_L);
386 for (int idx = 0; idx < n; idx++) {
387 xa[idx] <<= xp[idx];
388 }
389 for (int idx = 0; idx < m; idx++) {
390 lam[idx] = 1.0;
391 }
392 sig = 1.0;
393 eval_obj(n, &xa[0], &obj_value);
394 obj_value *= mkparam(sig);
395 eval_constraints(n, &xa[0], m, &g[0]);
396 for (int idx = 0; idx < m; idx++) {
397 obj_value += g[idx] * mkparam(lam[idx]);
398 }
399 obj_value >>= dummy;
400 trace_off();
401
402 rind_g_ = nullptr;
403 cind_g_ = nullptr;
404 rind_L_ = nullptr;
405 cind_L_ = nullptr;
406
407 options_g_[0] = 0; /* sparsity pattern by index domains (default) */
408 options_g_[1] = 0; /* safe mode (default) */
409 options_g_[2] = 0;
410 options_g_[3] = 0; /* column compression (default) */
411
412 jacval_ = nullptr;
413 hessval_ = nullptr;
414
415 sparse_jac(tag_g, m, n, 0, &xp[0], &nnz_jac_, &rind_g_, &cind_g_, &jacval_,
416 options_g_);
417 *nnz_jac_g = nnz_jac_;
418 options_L_[0] = 0;
419 options_L_[1] = 1;
420 sparse_hess(tag_L, n, 0, &xp[0], &nnz_L_, &rind_L_, &cind_L_, &hessval_,
421 options_L_);
422 *nnz_h_lag = nnz_L_;
423}
424} // namespace planning
425} // namespace apollo
void get_optimization_results(std::vector< double > *ptr_x, std::vector< double > *ptr_y) const
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
bool eval_g(int n, const double *x, bool new_x, int m, double *g) override
Method to return the constraint residuals
bool eval_grad_f(int n, const double *x, bool new_x, double *grad_f) override
Method to return the gradient of the objective
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
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
FemPosDeviationIpoptInterface(std::vector< std::pair< double, double > > points, std::vector< double > bounds)
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_constraints(int n, const T *x, int m, T *g)
Template to compute contraints
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...
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...
virtual void generate_tapes(int n, int m, int *nnz_jac_g, int *nnz_h_lag)
Method to generate the required tapes
bool eval_f(int n, const double *x, bool new_x, double &obj_value) override
Method to return the objective value
Planning module main class.
#define tag_f
#define tag_g
#define tag_L
class register implement
Definition arena_queue.h:37