Apollo 11.0
自动驾驶开放平台
piecewise_jerk_speed_nonlinear_optimizer.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 <coin/IpIpoptApplication.hpp>
24#include <coin/IpSolveStatistics.hpp>
25
26#include "modules/common_msgs/basic_msgs/pnc_point.pb.h"
27#include "modules/planning/planning_base/proto/ipopt_return_status.pb.h"
37
38namespace apollo {
39namespace planning {
40
45
48 smoothed_speed_limit_(0.0, 0.0, 0.0),
49 smoothed_path_curvature_(0.0, 0.0, 0.0) {}
50
52 const std::string& config_dir, const std::string& name,
53 const std::shared_ptr<DependencyInjector>& injector) {
54 if (!SpeedOptimizer::Init(config_dir, name, injector)) {
55 return false;
56 }
57 // Load the config_ this task.
58 if (SpeedOptimizer::LoadConfig<PiecewiseJerkNonlinearSpeedOptimizerConfig>(
59 &config_)) {
60 AERROR << "Failed to load config of PiecewiseJerkSpeedNonlinearOptimizer "
61 << Name();
62 }
63 return true;
64}
65
66Status PiecewiseJerkSpeedNonlinearOptimizer::Process(
67 const PathData& path_data, const TrajectoryPoint& init_point,
68 SpeedData* const speed_data) {
69 if (speed_data == nullptr) {
70 const std::string msg = "Null speed_data pointer";
71 AERROR << msg;
72 return Status(ErrorCode::PLANNING_ERROR, msg);
73 }
74
75 if (path_data.discretized_path().empty()) {
76 const std::string msg = "Speed Optimizer receives empty path data";
77 AERROR << msg;
78 return Status(ErrorCode::PLANNING_ERROR, msg);
79 }
80
82 return Status::OK();
83 }
84
85 const auto problem_setups_status =
86 SetUpStatesAndBounds(path_data, *speed_data);
87 if (!problem_setups_status.ok()) {
88 speed_data->clear();
89 return problem_setups_status;
90 }
91
92 std::vector<double> distance;
93 std::vector<double> velocity;
94 std::vector<double> acceleration;
95
96 const auto qp_start = std::chrono::system_clock::now();
97
98 const auto qp_smooth_status =
99 OptimizeByQP(speed_data, &distance, &velocity, &acceleration);
100
101 const auto qp_end = std::chrono::system_clock::now();
102 std::chrono::duration<double> qp_diff = qp_end - qp_start;
103 ADEBUG << "speed qp optimization takes " << qp_diff.count() * 1000.0 << " ms";
104
105 if (!qp_smooth_status.ok()) {
106 speed_data->clear();
107 return qp_smooth_status;
108 }
109
110 const bool speed_limit_check_status = CheckSpeedLimitFeasibility();
111
112 if (speed_limit_check_status) {
113 const auto curvature_smooth_start = std::chrono::system_clock::now();
114
115 const auto path_curvature_smooth_status = SmoothPathCurvature(path_data);
116
117 const auto curvature_smooth_end = std::chrono::system_clock::now();
118 std::chrono::duration<double> curvature_smooth_diff =
119 curvature_smooth_end - curvature_smooth_start;
120 ADEBUG << "path curvature smoothing for nlp optimization takes "
121 << curvature_smooth_diff.count() * 1000.0 << " ms";
122
123 if (!path_curvature_smooth_status.ok()) {
124 speed_data->clear();
125 return path_curvature_smooth_status;
126 }
127
128 const auto speed_limit_smooth_start = std::chrono::system_clock::now();
129
130 const auto speed_limit_smooth_status = SmoothSpeedLimit();
131
132 const auto speed_limit_smooth_end = std::chrono::system_clock::now();
133 std::chrono::duration<double> speed_limit_smooth_diff =
134 speed_limit_smooth_end - speed_limit_smooth_start;
135 ADEBUG << "speed limit smoothing for nlp optimization takes "
136 << speed_limit_smooth_diff.count() * 1000.0 << " ms";
137
138 if (!speed_limit_smooth_status.ok()) {
139 speed_data->clear();
140 return speed_limit_smooth_status;
141 }
142
143 const auto nlp_start = std::chrono::system_clock::now();
144
145 const auto nlp_smooth_status =
146 OptimizeByNLP(&distance, &velocity, &acceleration);
147
148 const auto nlp_end = std::chrono::system_clock::now();
149 std::chrono::duration<double> nlp_diff = nlp_end - nlp_start;
150 ADEBUG << "speed nlp optimization takes " << nlp_diff.count() * 1000.0
151 << " ms";
152
153 if (!nlp_smooth_status.ok()) {
154 speed_data->clear();
155 return nlp_smooth_status;
156 }
157
158 // Record speed_constraint
159 StGraphData* st_graph_data = reference_line_info_->mutable_st_graph_data();
160 auto* speed_constraint =
161 st_graph_data->mutable_st_graph_debug()->mutable_speed_constraint();
162 for (int i = 0; i < num_of_knots_; ++i) {
163 double t = i * delta_t_;
164 speed_constraint->add_t(t);
165 speed_constraint->add_upper_bound(
166 smoothed_speed_limit_.Evaluate(0, distance[i]));
167 }
168 }
169
170 speed_data->clear();
171 speed_data->AppendSpeedPoint(distance[0], 0.0, velocity[0], acceleration[0],
172 0.0);
173 for (int i = 1; i < num_of_knots_; ++i) {
174 // Avoid the very last points when already stopped
175 if (velocity[i] < 0.0) {
176 break;
177 }
178 speed_data->AppendSpeedPoint(
179 distance[i], delta_t_ * i, velocity[i], acceleration[i],
180 (acceleration[i] - acceleration[i - 1]) / delta_t_);
181 }
183
184 StGraphData* st_graph_data = reference_line_info_->mutable_st_graph_data();
185 RecordDebugInfo(*speed_data, st_graph_data->mutable_st_graph_debug());
186 return Status::OK();
187}
188
189Status PiecewiseJerkSpeedNonlinearOptimizer::SetUpStatesAndBounds(
190 const PathData& path_data, const SpeedData& speed_data) {
191 // Set st problem dimensions
192 const StGraphData& st_graph_data =
194 // TODO(Jinyun): move to confs
195 delta_t_ = 0.1;
196 total_length_ = st_graph_data.path_length();
197 total_time_ = st_graph_data.total_time_by_conf();
198 num_of_knots_ = static_cast<int>(total_time_ / delta_t_) + 1;
199
200 // Set initial values
201 s_init_ = 0.0;
202 s_dot_init_ = st_graph_data.init_point().v();
203 s_ddot_init_ = st_graph_data.init_point().a();
204
205 // Set s_dot bounary
206 s_dot_max_ = std::fmax(FLAGS_planning_upper_speed_limit,
207 st_graph_data.init_point().v());
208
209 // Set s_ddot boundary
210 const auto& veh_param =
212 s_ddot_max_ = veh_param.max_acceleration();
213 s_ddot_min_ = -1.0 * std::abs(veh_param.max_deceleration());
214
215 // Set s_dddot boundary
216 // TODO(Jinyun): allow the setting of jerk_lower_bound and move jerk config_
217 // to a better place
218 s_dddot_min_ = -std::abs(FLAGS_longitudinal_jerk_lower_bound);
219 s_dddot_max_ = FLAGS_longitudinal_jerk_upper_bound;
220
221 // Set s boundary
223 s_bounds_.clear();
224 s_soft_bounds_.clear();
225 // TODO(Jinyun): move to confs
226 for (int i = 0; i < num_of_knots_; ++i) {
227 double curr_t = i * delta_t_;
228 double s_lower_bound = 0.0;
229 double s_upper_bound = total_length_;
230 double s_soft_lower_bound = 0.0;
231 double s_soft_upper_bound = total_length_;
232 for (const STBoundary* boundary : st_graph_data.st_boundaries()) {
233 double s_lower = 0.0;
234 double s_upper = 0.0;
235 if (!boundary->GetUnblockSRange(curr_t, &s_upper, &s_lower)) {
236 continue;
237 }
238 SpeedPoint sp;
239 switch (boundary->boundary_type()) {
242 s_upper_bound = std::fmin(s_upper_bound, s_upper);
243 s_soft_upper_bound = std::fmin(s_soft_upper_bound, s_upper);
244 break;
246 s_upper_bound = std::fmin(s_upper_bound, s_upper);
247 if (!speed_data.EvaluateByTime(curr_t, &sp)) {
248 const std::string msg =
249 "rough speed profile estimation for soft follow fence failed";
250 AERROR << msg;
251 return Status(ErrorCode::PLANNING_ERROR, msg);
252 }
253 s_soft_upper_bound = std::fmin(
254 s_soft_upper_bound, s_upper - std::min(7.0, 2.5 * sp.v()));
255 break;
257 s_lower_bound = std::fmax(s_lower_bound, s_lower);
258 s_soft_lower_bound = std::fmax(s_soft_lower_bound, s_lower + 10.0);
259 break;
260 default:
261 break;
262 }
263 }
264 if (s_lower_bound > s_upper_bound) {
265 const std::string msg =
266 "s_lower_bound larger than s_upper_bound on STGraph";
267 AERROR << msg;
268 return Status(ErrorCode::PLANNING_ERROR, msg);
269 }
270 s_soft_bounds_.emplace_back(s_soft_lower_bound, s_soft_upper_bound);
271 s_bounds_.emplace_back(s_lower_bound, s_upper_bound);
272 }
273 } else {
274 s_bounds_.clear();
275 // TODO(Jinyun): move to confs
276 for (int i = 0; i < num_of_knots_; ++i) {
277 double curr_t = i * delta_t_;
278 double s_lower_bound = 0.0;
279 double s_upper_bound = total_length_;
280 for (const STBoundary* boundary : st_graph_data.st_boundaries()) {
281 double s_lower = 0.0;
282 double s_upper = 0.0;
283 if (!boundary->GetUnblockSRange(curr_t, &s_upper, &s_lower)) {
284 continue;
285 }
286 SpeedPoint sp;
287 switch (boundary->boundary_type()) {
290 s_upper_bound = std::fmin(s_upper_bound, s_upper);
291 break;
293 s_upper_bound = std::fmin(s_upper_bound, s_upper - 8.0);
294 break;
296 s_lower_bound = std::fmax(s_lower_bound, s_lower);
297 break;
298 default:
299 break;
300 }
301 }
302 if (s_lower_bound > s_upper_bound) {
303 const std::string msg =
304 "s_lower_bound larger than s_upper_bound on STGraph";
305 AERROR << msg;
306 return Status(ErrorCode::PLANNING_ERROR, msg);
307 }
308 s_bounds_.emplace_back(s_lower_bound, s_upper_bound);
309 }
310 }
311
312 speed_limit_ = st_graph_data.speed_limit();
313 cruise_speed_ = reference_line_info_->GetCruiseSpeed();
314 return Status::OK();
315}
316
317bool PiecewiseJerkSpeedNonlinearOptimizer::CheckSpeedLimitFeasibility() {
318 // a naive check on first point of speed limit
319 static constexpr double kEpsilon = 1e-6;
320 const double init_speed_limit = speed_limit_.GetSpeedLimitByS(s_init_);
321 if (init_speed_limit + kEpsilon < s_dot_init_) {
322 AERROR << "speed limit [" << init_speed_limit
323 << "] lower than initial speed[" << s_dot_init_ << "]";
324 return false;
325 }
326 return true;
327}
328
329Status PiecewiseJerkSpeedNonlinearOptimizer::SmoothSpeedLimit() {
330 // using piecewise_jerk_path to fit a curve of speed_ref
331 // TODO(Hongyi): move smooth configs to gflags
332 double delta_s = 2.0;
333 PrintCurves debug;
334 std::vector<double> speed_ref;
335 for (int i = 0; i < 100; ++i) {
336 double path_s = i * delta_s;
337 double limit = speed_limit_.GetSpeedLimitByS(path_s);
338 speed_ref.emplace_back(limit);
339 debug.AddPoint("coarse_v_bounds_upper", path_s, limit);
340 }
341 std::array<double, 3> init_state = {speed_ref[0], 0.0, 0.0};
342 PiecewiseJerkPathProblem piecewise_jerk_problem(speed_ref.size(), delta_s,
343 init_state);
344 piecewise_jerk_problem.set_x_bounds(0.0, 50.0);
345 piecewise_jerk_problem.set_dx_bounds(-100.0, 100.0);
346 piecewise_jerk_problem.set_ddx_bounds(-1000.0, 1000.0);
347 piecewise_jerk_problem.set_dddx_bound(-10000.0, 100000.0);
348
349 piecewise_jerk_problem.set_weight_x(0.0);
350 piecewise_jerk_problem.set_weight_dx(1.0);
351 piecewise_jerk_problem.set_weight_ddx(1.0);
352 piecewise_jerk_problem.set_weight_dddx(1.0);
353
354 piecewise_jerk_problem.set_x_ref(10.0, std::move(speed_ref));
355
356 if (!piecewise_jerk_problem.Optimize(4000)) {
357 const std::string msg = "Smoothing speed limit failed";
358 AERROR << msg;
359 return Status(ErrorCode::PLANNING_ERROR, msg);
360 }
361
362 std::vector<double> opt_x;
363 std::vector<double> opt_dx;
364 std::vector<double> opt_ddx;
365
366 opt_x = piecewise_jerk_problem.opt_x();
367 opt_dx = piecewise_jerk_problem.opt_dx();
368 opt_ddx = piecewise_jerk_problem.opt_ddx();
369 PiecewiseJerkTrajectory1d smoothed_speed_limit(opt_x.front(), opt_dx.front(),
370 opt_ddx.front());
371
372 for (size_t i = 1; i < opt_ddx.size(); ++i) {
373 double j = (opt_ddx[i] - opt_ddx[i - 1]) / delta_s;
374 smoothed_speed_limit.AppendSegment(j, delta_s);
375 }
376 for (size_t i = 0; i < opt_x.size(); i++) {
377 debug.AddPoint("smooth_v_bounds_upper", i * delta_s, opt_x[i]);
378 }
379 // debug.PrintToLog();
380 smoothed_speed_limit_ = smoothed_speed_limit;
381
382 return Status::OK();
383}
384
385Status PiecewiseJerkSpeedNonlinearOptimizer::SmoothPathCurvature(
386 const PathData& path_data) {
387 // using piecewise_jerk_path to fit a curve of path kappa profile
388 // TODO(Jinyun): move smooth configs to gflags
389 const auto& cartesian_path = path_data.discretized_path();
390 const double delta_s = 0.5;
391 std::vector<double> path_curvature;
392 PrintCurves debug;
393 for (double path_s = cartesian_path.front().s();
394 path_s < cartesian_path.back().s() + delta_s; path_s += delta_s) {
395 const auto& path_point = cartesian_path.Evaluate(path_s);
396 path_curvature.push_back(path_point.kappa());
397 debug.AddPoint("sk_corase", path_s, path_point.kappa());
398 }
399 const auto& path_init_point = cartesian_path.front();
400 std::array<double, 3> init_state = {path_init_point.kappa(),
401 path_init_point.dkappa(),
402 path_init_point.ddkappa()};
403 PiecewiseJerkPathProblem piecewise_jerk_problem(path_curvature.size(),
404 delta_s, init_state);
405 piecewise_jerk_problem.set_x_bounds(-1.0, 1.0);
406 piecewise_jerk_problem.set_dx_bounds(-10.0, 10.0);
407 piecewise_jerk_problem.set_ddx_bounds(-10.0, 10.0);
408 piecewise_jerk_problem.set_dddx_bound(-10.0, 10.0);
409
410 piecewise_jerk_problem.set_weight_x(0.0);
411 piecewise_jerk_problem.set_weight_dx(10.0);
412 piecewise_jerk_problem.set_weight_ddx(10.0);
413 piecewise_jerk_problem.set_weight_dddx(10.0);
414
415 piecewise_jerk_problem.set_x_ref(10.0, std::move(path_curvature));
416
417 if (!piecewise_jerk_problem.Optimize(1000)) {
418 const std::string msg = "Smoothing path curvature failed";
419 AERROR << msg;
420 return Status(ErrorCode::PLANNING_ERROR, msg);
421 }
422
423 std::vector<double> opt_x;
424 std::vector<double> opt_dx;
425 std::vector<double> opt_ddx;
426
427 opt_x = piecewise_jerk_problem.opt_x();
428 opt_dx = piecewise_jerk_problem.opt_dx();
429 opt_ddx = piecewise_jerk_problem.opt_ddx();
430
431 PiecewiseJerkTrajectory1d smoothed_path_curvature(
432 opt_x.front(), opt_dx.front(), opt_ddx.front());
433
434 for (size_t i = 1; i < opt_ddx.size(); ++i) {
435 double j = (opt_ddx[i] - opt_ddx[i - 1]) / delta_s;
436 smoothed_path_curvature.AppendSegment(j, delta_s);
437 }
438
439 for (size_t i = 0; i < opt_x.size(); ++i) {
440 debug.AddPoint("sk_smooth", delta_s * i, opt_x[i]);
441 }
442 // debug.PrintToLog();
443 smoothed_path_curvature_ = smoothed_path_curvature;
444
445 return Status::OK();
446}
447
448Status PiecewiseJerkSpeedNonlinearOptimizer::OptimizeByQP(
449 SpeedData* const speed_data, std::vector<double>* distance,
450 std::vector<double>* velocity, std::vector<double>* acceleration) {
451 std::array<double, 3> init_states = {s_init_, s_dot_init_, s_ddot_init_};
452 PiecewiseJerkSpeedProblem piecewise_jerk_problem(num_of_knots_, delta_t_,
453 init_states);
454 piecewise_jerk_problem.set_dx_bounds(
455 0.0, std::fmax(FLAGS_planning_upper_speed_limit, init_states[1]));
456 piecewise_jerk_problem.set_ddx_bounds(s_ddot_min_, s_ddot_max_);
457 piecewise_jerk_problem.set_dddx_bound(s_dddot_min_, s_dddot_max_);
458 piecewise_jerk_problem.set_x_bounds(s_bounds_);
459
460 // TODO(Jinyun): parameter tunnings
461 piecewise_jerk_problem.set_weight_x(0.0);
462 piecewise_jerk_problem.set_weight_dx(0.0);
463 piecewise_jerk_problem.set_weight_ddx(config_.acc_weight());
464 piecewise_jerk_problem.set_weight_dddx(config_.jerk_weight());
465 PrintCurves debug;
466 std::vector<double> x_ref;
467 for (int i = 0; i < num_of_knots_; ++i) {
468 const double curr_t = i * delta_t_;
469 // get path_s
470 SpeedPoint sp;
471 speed_data->EvaluateByTime(curr_t, &sp);
472 x_ref.emplace_back(sp.s());
473 debug.AddPoint("dp_st_curve", curr_t, sp.s());
474 }
475 piecewise_jerk_problem.set_x_ref(config_.ref_s_weight(), std::move(x_ref));
476
477 // Solve the problem
478 if (!piecewise_jerk_problem.Optimize()) {
479 const std::string msg =
480 "Speed Optimization by Quadratic Programming failed. "
481 "st boundary is infeasible.";
482 AERROR << msg;
483 return Status(ErrorCode::PLANNING_ERROR, msg);
484 }
485
486 *distance = piecewise_jerk_problem.opt_x();
487 *velocity = piecewise_jerk_problem.opt_dx();
488 *acceleration = piecewise_jerk_problem.opt_ddx();
489 for (size_t i = 0; i < distance->size(); i++) {
490 const double curr_t = i * delta_t_;
491 debug.AddPoint("warm_start_st", curr_t, distance->at(i));
492 debug.AddPoint("warm_start_vt", curr_t, velocity->at(i));
493 debug.AddPoint("warm_start_at", curr_t, acceleration->at(i));
494 }
495 // debug.PrintToLog();
496 return Status::OK();
497}
498
499Status PiecewiseJerkSpeedNonlinearOptimizer::OptimizeByNLP(
500 std::vector<double>* distance, std::vector<double>* velocity,
501 std::vector<double>* acceleration) {
502 static std::mutex mutex_tnlp;
503 UNIQUE_LOCK_MULTITHREAD(mutex_tnlp);
504 // Set optimizer instance
505 auto ptr_interface = new PiecewiseJerkSpeedNonlinearIpoptInterface(
506 s_init_, s_dot_init_, s_ddot_init_, delta_t_, num_of_knots_,
507 total_length_, s_dot_max_, s_ddot_min_, s_ddot_max_, s_dddot_min_,
508 s_dddot_max_);
509 PrintCurves debug;
510 ptr_interface->set_safety_bounds(s_bounds_);
511 for (size_t i = 0; i < s_bounds_.size(); i++) {
512 debug.AddPoint("st_bounds_lower", i * delta_t_, s_bounds_[i].first);
513 debug.AddPoint("st_bounds_upper", i * delta_t_, s_bounds_[i].second);
514 }
515 if (config_.use_warm_start()) {
516 const auto& warm_start_distance = *distance;
517 const auto& warm_start_velocity = *velocity;
518 const auto& warm_start_acceleration = *acceleration;
519 if (warm_start_distance.empty() || warm_start_velocity.empty() ||
520 warm_start_acceleration.empty() ||
521 warm_start_distance.size() != warm_start_velocity.size() ||
522 warm_start_velocity.size() != warm_start_acceleration.size()) {
523 const std::string msg =
524 "Piecewise jerk speed nonlinear optimizer warm start invalid!";
525 AERROR << msg;
526 return Status(ErrorCode::PLANNING_ERROR, msg);
527 }
528 std::vector<std::vector<double>> warm_start;
529 std::size_t size = warm_start_distance.size();
530 for (std::size_t i = 0; i < size; ++i) {
531 warm_start.emplace_back(std::initializer_list<double>(
532 {warm_start_distance[i], warm_start_velocity[i],
533 warm_start_acceleration[i]}));
534 }
535 ptr_interface->set_warm_start(warm_start);
536 }
537
538 if (config_.use_smoothed_dp_guide_line()) {
539 ptr_interface->set_reference_spatial_distance(*distance);
540 // TODO(Jinyun): move to confs
541 ptr_interface->set_w_reference_spatial_distance(10.0);
542 } else {
543 std::vector<double> spatial_potantial(num_of_knots_, total_length_);
544 ptr_interface->set_reference_spatial_distance(spatial_potantial);
545 ptr_interface->set_w_reference_spatial_distance(
546 config_.s_potential_weight());
547 }
548
550 ptr_interface->set_soft_safety_bounds(s_soft_bounds_);
551 ptr_interface->set_w_soft_s_bound(config_.soft_s_bound_weight());
552 }
553
554 ptr_interface->set_w_overall_a(config_.acc_weight());
555 ptr_interface->set_w_overall_j(config_.jerk_weight());
556 ptr_interface->set_w_overall_centripetal_acc(config_.lat_acc_weight());
557
558 ptr_interface->set_reference_speed(cruise_speed_);
559 ptr_interface->set_w_reference_speed(config_.ref_v_weight());
560
561 Ipopt::SmartPtr<Ipopt::TNLP> problem = ptr_interface;
562 Ipopt::SmartPtr<Ipopt::IpoptApplication> app = IpoptApplicationFactory();
563
564 app->Options()->SetIntegerValue("print_level", 0);
565 app->Options()->SetIntegerValue("max_iter", 1000);
566
567 Ipopt::ApplicationReturnStatus status = app->Initialize();
568 if (status != Ipopt::Solve_Succeeded) {
569 const std::string msg =
570 "Piecewise jerk speed nonlinear optimizer failed during initialization";
571 AERROR << msg;
572 return Status(ErrorCode::PLANNING_ERROR, msg);
573 }
574
575 const auto start_timestamp = std::chrono::system_clock::now();
576 status = app->OptimizeTNLP(problem);
577
578 const auto end_timestamp = std::chrono::system_clock::now();
579 std::chrono::duration<double> diff = end_timestamp - start_timestamp;
580 ADEBUG << "*** The optimization problem take time: " << diff.count() * 1000.0
581 << " ms.";
582
583 if (status == Ipopt::Solve_Succeeded ||
584 status == Ipopt::Solved_To_Acceptable_Level) {
585 // Retrieve some statistics about the solve
586 Ipopt::Index iter_count = app->Statistics()->IterationCount();
587 ADEBUG << "*** The problem solved in " << iter_count << " iterations!";
588 Ipopt::Number final_obj = app->Statistics()->FinalObjective();
589 ADEBUG << "*** The final value of the objective function is " << final_obj
590 << '.';
591 } else {
592 const auto& ipopt_return_status =
593 IpoptReturnStatus_Name(static_cast<IpoptReturnStatus>(status));
594 if (ipopt_return_status.empty()) {
595 AERROR << "Solver ends with unknown failure code: "
596 << static_cast<int>(status);
597 } else {
598 AERROR << "Solver failure case is : " << ipopt_return_status;
599 }
600 const std::string msg = "Piecewise jerk speed nonlinear optimizer failed";
601 AERROR << msg;
602 return Status(ErrorCode::PLANNING_ERROR, msg);
603 }
604
605 ptr_interface->get_optimization_results(distance, velocity, acceleration);
606 for (size_t i = 0; i < distance->size(); i++) {
607 debug.AddPoint("optimize_st_curve", i * delta_t_, (*distance)[i]);
608 debug.AddPoint("optimize_vt_curve", i * delta_t_, (*velocity)[i]);
609 debug.AddPoint("optimize_at_curve", i * delta_t_, (*acceleration)[i]);
610 debug.AddPoint("optimize_sv_curve", (*distance)[i], (*velocity)[i]);
611 }
612 // debug.PrintToLog();
613 return Status::OK();
614}
615} // namespace planning
616} // namespace apollo
A general class to denote the return status of an API call.
Definition status.h:43
static Status OK()
generate a success status.
Definition status.h:60
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
const DiscretizedPath & discretized_path() const
Definition path_data.cc:90
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
double Evaluate(const std::uint32_t order, const double param) const
void AppendSpeedPoint(const double s, const double time, const double v, const double a, const double da)
Definition speed_data.cc:48
double GetSpeedLimitByS(const double s) const
void RecordDebugInfo(const SpeedData &speed_data)
static void FillEnoughSpeedPoints(SpeedData *const speed_data)
planning_internal::STGraphDebug * mutable_st_graph_debug()
const std::string & Name() const
Definition task.cc:58
ReferenceLineInfo * reference_line_info_
Definition task.h:58
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
Definition task.cc:40
Planning module main class.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
Some util functions.
#define UNIQUE_LOCK_MULTITHREAD(mutex_type)
Definition util.h:162
float diff(Image< float > *I, int x1, int y1, int x2, int y2)
Dissimilarity measure between pixels
class register implement
Definition arena_queue.h:37
: data with map info and obstacle info
optional VehicleParam vehicle_param