27#include "modules/planning/planning_open_space/proto/planner_open_space_config.pb.h"
49 const auto& vehicle_param = common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param();
50 ego_length_ = vehicle_param.length();
51 ego_width_ = vehicle_param.width();
52 center_shift_distance_ = ego_length_ / 2.0 - vehicle_param.back_edge_to_center();
53 planner_open_space_config_ = planner_open_space_config;
55 AINFO <<
"config:" << planner_open_space_config_.DebugString();
60 const auto& vehicle_param = common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param();
61 ego_length_ = vehicle_param.length();
62 ego_width_ = vehicle_param.width();
63 center_shift_distance_ = ego_length_ / 2.0 - vehicle_param.back_edge_to_center();
64 iterative_anchoring_config_ = iterative_anchoring_config;
65 AINFO <<
"config:" << iterative_anchoring_config_.DebugString();
69 const Eigen::MatrixXd& xWS,
72 const std::vector<std::vector<Vec2d>>& obstacles_vertices_vec,
75 AERROR <<
"reference points size smaller than two, smoother early "
79 const auto start_timestamp = std::chrono::system_clock::now();
82 gear_ = CheckGear(xWS);
85 std::vector<std::vector<LineSegment2d>> obstacles_linesegments_vec;
86 for (
const auto& obstacle_vertices : obstacles_vertices_vec) {
87 size_t vertices_num = obstacle_vertices.size();
88 std::vector<LineSegment2d> obstacle_linesegments;
89 for (
size_t i = 0; i + 1 < vertices_num; ++i) {
91 obstacle_linesegments.emplace_back(line_segment);
93 obstacles_linesegments_vec.emplace_back(obstacle_linesegments);
95 obstacles_linesegments_vec_ = std::move(obstacles_linesegments_vec);
99 size_t xWS_size = xWS.cols();
100 double accumulated_s = 0.0;
101 Vec2d last_path_point(xWS(0, 0), xWS(1, 0));
102 for (
size_t i = 0; i < xWS_size; ++i) {
103 Vec2d cur_path_point(xWS(0, i), xWS(1, i));
104 accumulated_s += cur_path_point.
DistanceTo(last_path_point);
106 path_point.set_x(xWS(0, i));
107 path_point.set_y(xWS(1, i));
108 path_point.set_theta(xWS(2, i));
109 path_point.set_s(accumulated_s);
110 warm_start_path.push_back(std::move(path_point));
111 last_path_point = cur_path_point;
113 if (std::fabs(accumulated_s) < 0.1) {
114 AERROR <<
"warm_start_path smaller than 0.1 m, can't enforce "
115 "heading continuity";
120 std::vector<std::pair<double, double>> interpolated_warm_start_point2ds;
121 double path_length = warm_start_path.
Length();
122 int count = std::ceil(path_length / interpolated_delta_s);
123 double delta_s = path_length / (count < 4 ? 4 : count);
124 path_length += delta_s * 1.0e-6;
125 for (
double s = 0; s < path_length; s += delta_s) {
126 const auto point2d = warm_start_path.
Evaluate(s);
127 interpolated_warm_start_point2ds.emplace_back(point2d.x(), point2d.y());
130 const size_t interpolated_size = interpolated_warm_start_point2ds.size();
131 if (interpolated_size < 6) {
132 ADEBUG <<
"interpolated_warm_start_path smaller than 4, can't enforce "
133 "initial zero kappa";
134 enforce_initial_kappa_ =
false;
136 enforce_initial_kappa_ =
true;
140 AdjustStartEndHeading(xWS, &interpolated_warm_start_point2ds);
144 if (!SetPathProfile(interpolated_warm_start_point2ds, &interpolated_warm_start_path)) {
145 AERROR <<
"Set path profile fails";
150 std::vector<double> bounds;
151 if (!GenerateInitialBounds(interpolated_warm_start_path, &bounds)) {
152 AERROR <<
"Generate initial bounds failed, path point to close to obstacle";
158 input_colliding_point_index_.clear();
159 if (!CheckCollisionAvoidance(interpolated_warm_start_path, &input_colliding_point_index_)) {
160 AERROR <<
"Interpolated input path points colliding with obstacle";
167 const auto path_smooth_start_timestamp = std::chrono::system_clock::now();
171 if (!SmoothPath(interpolated_warm_start_path, bounds, &smoothed_path_points)) {
196 const auto path_smooth_end_timestamp = std::chrono::system_clock::now();
197 std::chrono::duration<double> path_smooth_diff = path_smooth_end_timestamp - path_smooth_start_timestamp;
198 ADEBUG <<
"iterative anchoring path smoother time: " << path_smooth_diff.count() * 1000.0 <<
" ms.";
200 const auto speed_smooth_start_timestamp = std::chrono::system_clock::now();
204 if (!SmoothSpeed(init_a, init_v, smoothed_path_points.
Length(), &smoothed_speeds)) {
215 const auto speed_smooth_end_timestamp = std::chrono::system_clock::now();
216 std::chrono::duration<double> speed_smooth_diff = speed_smooth_end_timestamp - speed_smooth_start_timestamp;
217 ADEBUG <<
"iterative anchoring speed smoother time: " << speed_smooth_diff.count() * 1000.0 <<
" ms.";
220 if (!CombinePathAndSpeed(smoothed_path_points, smoothed_speeds, discretized_trajectory)) {
224 AdjustPathAndSpeedByGear(discretized_trajectory);
226 const auto end_timestamp = std::chrono::system_clock::now();
227 std::chrono::duration<double> diff = end_timestamp - start_timestamp;
228 ADEBUG <<
"iterative anchoring smoother total time: " << diff.count() * 1000.0 <<
" ms.";
230 ADEBUG <<
"discretized_trajectory size " << discretized_trajectory->size();
234void IterativeAnchoringSmoother::AdjustStartEndHeading(
235 const Eigen::MatrixXd& xWS,
236 std::vector<std::pair<double, double>>*
const point2d) {
238 CHECK_NOTNULL(point2d);
239 CHECK_GT(xWS.cols(), 1);
240 CHECK_GT(point2d->size(), 3U);
243 const double initial_heading = xWS(2, 0);
244 const double end_heading = xWS(2, xWS.cols() - 1);
249 const double first_to_second_dx = point2d->at(1).first - point2d->at(0).first;
250 const double first_to_second_dy = point2d->at(1).second - point2d->at(0).second;
251 const double first_to_second_s
252 = std::sqrt(first_to_second_dx * first_to_second_dx + first_to_second_dy * first_to_second_dy);
253 Vec2d first_point(point2d->at(0).first, point2d->at(0).second);
254 Vec2d initial_vec(first_to_second_s, 0);
255 initial_vec.SelfRotate(gear_ ? initial_heading : NormalizeAngle(initial_heading + M_PI));
256 initial_vec += first_point;
257 point2d->at(1) = std::make_pair(initial_vec.x(), initial_vec.y());
259 const size_t path_size = point2d->size();
260 const double second_last_to_last_dx = point2d->at(path_size - 1).first - point2d->at(path_size - 2).first;
261 const double second_last_to_last_dy = point2d->at(path_size - 1).second - point2d->at(path_size - 2).second;
262 const double second_last_to_last_s = std::sqrt(
263 second_last_to_last_dx * second_last_to_last_dx + second_last_to_last_dy * second_last_to_last_dy);
264 Vec2d last_point(point2d->at(path_size - 1).first, point2d->at(path_size - 1).second);
265 Vec2d end_vec(second_last_to_last_s, 0);
266 end_vec.SelfRotate(gear_ ? NormalizeAngle(end_heading + M_PI) : end_heading);
267 end_vec += last_point;
268 point2d->at(path_size - 2) = std::make_pair(end_vec.x(), end_vec.y());
271bool IterativeAnchoringSmoother::ReAnchoring(
272 const std::vector<size_t>& colliding_point_index,
273 DiscretizedPath* path_points) {
274 CHECK_NOTNULL(path_points);
275 if (colliding_point_index.empty()) {
276 ADEBUG <<
"no point needs to be re-anchored";
280 CHECK_GT(path_points->size(), *(std::max_element(colliding_point_index.begin(), colliding_point_index.end())));
282 for (
const auto index : colliding_point_index) {
283 if (index == 0 || index == path_points->size() - 1) {
284 AERROR <<
"Initial and end points collision avoid condition failed.";
287 if (index == 1 || index == path_points->size() - 2) {
288 AERROR <<
"second to last point or second point pos reanchored. Heading "
289 "discontinuity might "
295 const size_t reanchoring_trails_num =
static_cast<size_t>(iterative_anchoring_config_.
reanchoring_trails_num());
298 std::random_device rd;
299 std::default_random_engine gen = std::default_random_engine(rd());
300 std::normal_distribution<> pos_dis{0, reanchoring_pos_stddev};
301 std::normal_distribution<> length_dis{0, reanchoring_length_stddev};
303 for (
const auto index : colliding_point_index) {
304 bool reanchoring_success =
false;
305 for (
size_t i = 0; i < reanchoring_trails_num; ++i) {
307 bool is_colliding =
false;
308 for (
size_t j = index - 1; j < index + 2; ++j) {
310 = gear_ ? path_points->at(j).theta() :
NormalizeAngle(path_points->at(j).theta() + M_PI);
312 {path_points->at(j).x() + center_shift_distance_ * std::cos(heading),
313 path_points->at(j).y() + center_shift_distance_ * std::sin(heading)},
317 for (
const auto& obstacle_linesegments : obstacles_linesegments_vec_) {
318 for (
const LineSegment2d& linesegment : obstacle_linesegments) {
319 if (ego_box.HasOverlap(linesegment)) {
336 const double adjust_theta = path_points->at(index - 1).theta();
337 const double delta_s = std::abs(path_points->at(index).s() - path_points->at(index - 1).s());
339 double adjusted_delta_s = delta_s * (1.0 + rand_dev);
340 path_points->at(index).set_x(
341 path_points->at(index - 1).x() + adjusted_delta_s * std::cos(adjust_theta));
342 path_points->at(index).set_y(
343 path_points->at(index - 1).y() + adjusted_delta_s * std::sin(adjust_theta));
344 }
else if (index == path_points->size() - 2) {
345 const double adjust_theta =
NormalizeAngle(path_points->at(index + 1).theta() + M_PI);
346 const double delta_s = std::abs(path_points->at(index + 1).s() - path_points->at(index).s());
348 double adjusted_delta_s = delta_s * (1.0 + rand_dev);
349 path_points->at(index).set_x(
350 path_points->at(index + 1).x() + adjusted_delta_s * std::cos(adjust_theta));
351 path_points->at(index).set_y(
352 path_points->at(index + 1).y() + adjusted_delta_s * std::sin(adjust_theta));
355 pos_dis(gen), 2.0 * reanchoring_pos_stddev, -2.0 * reanchoring_pos_stddev);
357 pos_dis(gen), 2.0 * reanchoring_pos_stddev, -2.0 * reanchoring_pos_stddev);
358 path_points->at(index).set_x(path_points->at(index).x() + rand_dev_x);
359 path_points->at(index).set_y(path_points->at(index).y() + rand_dev_y);
365 for (
size_t i = index - 1; i < index + 2; ++i) {
366 path_points->at(i).set_theta(CalcHeadings(*path_points, i));
369 reanchoring_success =
true;
374 if (!reanchoring_success) {
375 AERROR <<
"interpolated points at index " << index <<
"can't be successfully reanchored";
382bool IterativeAnchoringSmoother::GenerateInitialBounds(
383 const DiscretizedPath& path_points,
384 std::vector<double>* initial_bounds) {
385 CHECK_NOTNULL(initial_bounds);
386 initial_bounds->clear();
388 const bool estimate_bound = iterative_anchoring_config_.
estimate_bound();
389 const double default_bound = iterative_anchoring_config_.
default_bound();
391 const double kEpislon = 1e-8;
393 if (!estimate_bound) {
394 std::vector<double> default_bounds(path_points.size(), default_bound);
395 *initial_bounds = std::move(default_bounds);
400 for (
const auto& path_point : path_points) {
401 double min_bound = std::numeric_limits<double>::infinity();
402 for (
const auto& obstacle_linesegments : obstacles_linesegments_vec_) {
403 for (
const LineSegment2d& linesegment : obstacle_linesegments) {
404 min_bound = std::min(min_bound, linesegment.DistanceTo({path_point.x(), path_point.y()}));
407 min_bound -= vehicle_shortest_dimension;
408 min_bound = min_bound < kEpislon ? 0.0 : min_bound;
409 initial_bounds->push_back(min_bound);
414bool IterativeAnchoringSmoother::SmoothPath(
415 const DiscretizedPath& raw_path_points,
416 const std::vector<double>& bounds,
417 DiscretizedPath* smoothed_path_points,
418 std::vector<std::vector<common::math::Vec2d>> point_box) {
419 std::vector<std::pair<double, double>> raw_point2d;
420 std::vector<double> flexible_bounds;
421 for (
const auto& path_point : raw_path_points) {
422 raw_point2d.emplace_back(path_point.x(), path_point.y());
424 flexible_bounds = bounds;
429 const size_t max_iteration_num = 50;
431 bool is_collision_free =
false;
432 std::vector<size_t> colliding_point_index;
433 std::vector<std::pair<double, double>> smoothed_point2d;
436 while (!is_collision_free) {
437 if (counter > max_iteration_num) {
438 AERROR <<
"Maximum iteration reached, path smoother early stops";
442 AdjustPathBounds(colliding_point_index, &flexible_bounds);
444 std::vector<double> opt_x;
445 std::vector<double> opt_y;
446 if (!fem_pos_smoother.Solve(raw_point2d, flexible_bounds, &opt_x, &opt_y)) {
447 AERROR <<
"Smoothing path fails";
451 if (opt_x.size() < 2 || opt_y.size() < 2) {
452 AERROR <<
"Return by fem_pos_smoother is wrong. Size smaller than 2 ";
456 CHECK_EQ(opt_x.size(), opt_y.size());
458 size_t point_size = opt_x.size();
459 smoothed_point2d.clear();
460 for (
size_t i = 0; i < point_size; ++i) {
461 smoothed_point2d.emplace_back(opt_x[i], opt_y[i]);
464 if (!SetPathProfile(smoothed_point2d, smoothed_path_points)) {
465 AERROR <<
"Set path profile fails";
469 is_collision_free = CheckCollisionAvoidance(*smoothed_path_points, &colliding_point_index);
471 ADEBUG <<
"loop iteration number is " << counter;
477bool IterativeAnchoringSmoother::CheckCollisionAvoidance(
478 const DiscretizedPath& path_points,
479 std::vector<size_t>* colliding_point_index) {
480 CHECK_NOTNULL(colliding_point_index);
482 colliding_point_index->clear();
483 size_t path_points_size = path_points.size();
484 for (
size_t i = 0; i < path_points_size; ++i) {
486 bool skip_checking =
false;
487 for (
const auto index : input_colliding_point_index_) {
489 skip_checking =
true;
497 const double heading = gear_ ? path_points[i].theta() :
NormalizeAngle(path_points[i].theta() + M_PI);
499 {path_points[i].x() + center_shift_distance_ * std::cos(heading),
500 path_points[i].y() + center_shift_distance_ * std::sin(heading)},
505 bool is_colliding =
false;
506 for (
const auto& obstacle_linesegments : obstacles_linesegments_vec_) {
507 for (
const LineSegment2d& linesegment : obstacle_linesegments) {
508 if (ego_box.HasOverlap(linesegment)) {
509 colliding_point_index->push_back(i);
510 ADEBUG <<
"point at " << i <<
"collied with LineSegment " << linesegment.DebugString();
521 if (!colliding_point_index->empty()) {
527void IterativeAnchoringSmoother::AdjustPathBounds(
528 const std::vector<size_t>& colliding_point_index,
529 std::vector<double>* bounds) {
530 CHECK_NOTNULL(bounds);
534 for (
const auto index : colliding_point_index) {
535 bounds->at(index) *= collision_decrease_ratio;
542 bounds->at(bounds->size() - 1) = 0.0;
543 bounds->at(bounds->size() - 2) = 0.0;
544 if (enforce_initial_kappa_) {
549bool IterativeAnchoringSmoother::SetPathProfile(
550 const std::vector<std::pair<double, double>>& point2d,
551 DiscretizedPath* raw_path_points) {
552 CHECK_NOTNULL(raw_path_points);
553 raw_path_points->clear();
555 std::vector<double> headings;
556 std::vector<double> kappas;
557 std::vector<double> dkappas;
558 std::vector<double> accumulated_s;
562 CHECK_EQ(point2d.size(), headings.size());
563 CHECK_EQ(point2d.size(), kappas.size());
564 CHECK_EQ(point2d.size(), dkappas.size());
565 CHECK_EQ(point2d.size(), accumulated_s.size());
568 size_t points_size = point2d.size();
569 for (
size_t i = 0; i < points_size; ++i) {
570 PathPoint path_point;
571 path_point.set_x(point2d[i].first);
572 path_point.set_y(point2d[i].second);
573 path_point.set_theta(headings[i]);
574 path_point.set_s(accumulated_s[i]);
575 path_point.set_kappa(kappas[i]);
576 path_point.set_dkappa(dkappas[i]);
577 raw_path_points->push_back(std::move(path_point));
582bool IterativeAnchoringSmoother::CheckGear(
const Eigen::MatrixXd& xWS) {
583 CHECK_GT(xWS.size(), 1);
584 double init_heading_angle = xWS(2, 0);
585 const Vec2d init_tracking_vector(xWS(0, 1) - xWS(0, 0), xWS(1, 1) - xWS(1, 0));
586 double init_tracking_angle = init_tracking_vector.Angle();
587 return std::abs(
NormalizeAngle(init_tracking_angle - init_heading_angle)) < M_PI_2;
590bool IterativeAnchoringSmoother::SmoothSpeed(
593 const double path_length,
594 SpeedData* smoothed_speeds) {
595 const double max_forward_v = FLAGS_open_space_max_forward_v;
596 const double max_reverse_v = FLAGS_open_space_max_reverse_v;
597 const double max_forward_acc = FLAGS_open_space_max_forward_acc;
598 const double max_reverse_acc = FLAGS_open_space_max_reverse_acc;
599 const double max_acc_jerk = FLAGS_open_space_max_jerk;
600 const double delta_t = FLAGS_open_space_delta_t;
602 const double total_t = 2 * path_length / max_reverse_acc * 10;
603 ADEBUG <<
"total_t is : " << total_t <<
"path_length" << path_length;
604 const size_t num_of_knots =
static_cast<size_t>(total_t / delta_t) + 1;
606 PiecewiseJerkSpeedProblem piecewise_jerk_problem(num_of_knots, delta_t, {0.0, std::abs(init_v), 0.0});
609 std::vector<std::pair<double, double>> x_bounds(num_of_knots, {0.0, path_length});
611 const double max_v = gear_ ? max_forward_v : max_reverse_v;
612 const double max_acc = gear_ ? max_forward_acc : max_reverse_acc;
614 const auto upper_dx = std::fmax(max_v, std::abs(init_v));
615 std::vector<std::pair<double, double>> dx_bounds(num_of_knots, {0.0, upper_dx});
616 std::vector<std::pair<double, double>> ddx_bounds(num_of_knots, {-max_acc, max_acc});
618 x_bounds[num_of_knots - 1] = std::make_pair(path_length, path_length);
619 dx_bounds[num_of_knots - 1] = std::make_pair(0.0, 0.0);
620 ddx_bounds[num_of_knots - 1] = std::make_pair(0.0, 0.0);
622 std::vector<double> x_ref(num_of_knots, path_length);
623 piecewise_jerk_problem.set_x_ref(FLAGS_open_space_reference_s_weight, std::move(x_ref));
624 piecewise_jerk_problem.set_weight_ddx(FLAGS_open_space_acc_weight);
625 piecewise_jerk_problem.set_weight_dddx(FLAGS_open_space_jerk_weight);
626 piecewise_jerk_problem.set_x_bounds(x_bounds);
627 piecewise_jerk_problem.set_dx_bounds(dx_bounds);
628 piecewise_jerk_problem.set_ddx_bounds(ddx_bounds);
629 piecewise_jerk_problem.set_dddx_bound(max_acc_jerk);
632 if (!piecewise_jerk_problem.Optimize()) {
633 AERROR <<
"Piecewise jerk speed optimizer failed!";
634 AERROR <<
"init v" << init_v <<
",a" << init_a <<
"jerk bound" << max_acc_jerk;
635 AERROR <<
"xbounds; dxbounds;ddxbounds";
636 for (
size_t i = 0; i < num_of_knots; i++) {
637 AERROR << x_bounds[i].first <<
", " << x_bounds[i].second <<
";" << dx_bounds[i].first <<
","
638 << dx_bounds[i].second <<
";" << ddx_bounds[i].first <<
"," << ddx_bounds[i].second;
644 const std::vector<double>& s = piecewise_jerk_problem.opt_x();
645 const std::vector<double>& ds = piecewise_jerk_problem.opt_dx();
646 const std::vector<double>& dds = piecewise_jerk_problem.opt_ddx();
649 smoothed_speeds->AppendSpeedPoint(s[0], 0.0, ds[0], dds[0], 0.0);
650 const double kEpislon = 1.0e-1;
651 const double sEpislon = 1.0e-1;
652 for (
size_t i = 1; i < num_of_knots; ++i) {
653 if (s[i - 1] - s[i] > kEpislon) {
654 AERROR <<
"unexpected decreasing s in speed smoothing at time " <<
static_cast<double>(i) * delta_t
655 <<
"with total time " << total_t;
658 smoothed_speeds->AppendSpeedPoint(
659 s[i], delta_t *
static_cast<double>(i), ds[i], dds[i], (dds[i] - dds[i - 1]) / delta_t);
661 if (path_length - s[i] < sEpislon) {
668bool IterativeAnchoringSmoother::CombinePathAndSpeed(
669 const DiscretizedPath& path_points,
670 const SpeedData& speed_points,
671 DiscretizedTrajectory* discretized_trajectory) {
672 CHECK_NOTNULL(discretized_trajectory);
673 discretized_trajectory->clear();
675 const double kDenseTimeResolution = 0.1;
676 const double time_horizon = speed_points.TotalTime() + kDenseTimeResolution * 1.0e-6;
677 if (path_points.empty()) {
678 AERROR <<
"path data is empty";
681 ADEBUG <<
"speed_points.TotalTime() " << speed_points.TotalTime();
682 for (
double cur_rel_time = 0.0; cur_rel_time < time_horizon; cur_rel_time += kDenseTimeResolution) {
683 common::SpeedPoint speed_point;
684 if (!speed_points.EvaluateByTime(cur_rel_time, &speed_point)) {
685 AERROR <<
"Fail to get speed point with relative time " << cur_rel_time;
689 if (speed_point.s() > path_points.Length()) {
693 common::PathPoint path_point = path_points.Evaluate(speed_point.s());
695 common::TrajectoryPoint trajectory_point;
696 trajectory_point.mutable_path_point()->CopyFrom(path_point);
697 trajectory_point.set_v(speed_point.v());
698 trajectory_point.set_a(speed_point.a());
699 trajectory_point.set_relative_time(speed_point.t());
700 discretized_trajectory->AppendTrajectoryPoint(trajectory_point);
703 common::PathPoint path_point = path_points.Evaluate(path_points.Length());
704 common::TrajectoryPoint trajectory_point;
705 trajectory_point.mutable_path_point()->CopyFrom(path_point);
706 trajectory_point.set_v(0.0);
707 trajectory_point.set_a(0.0);
708 trajectory_point.set_relative_time(speed_points.TotalTime() + kDenseTimeResolution);
709 discretized_trajectory->AppendTrajectoryPoint(trajectory_point);
711 ADEBUG <<
"path length before combine " << path_points.Length();
712 ADEBUG <<
"trajectory length after combine " << discretized_trajectory->GetSpatialLength();
716void IterativeAnchoringSmoother::AdjustPathAndSpeedByGear(DiscretizedTrajectory* discretized_trajectory) {
721 discretized_trajectory->begin(), discretized_trajectory->end(), [](TrajectoryPoint& trajectory_point) {
722 trajectory_point.mutable_path_point()->set_theta(
723 NormalizeAngle(trajectory_point.path_point().theta() + M_PI));
724 trajectory_point.mutable_path_point()->set_s(-1.0 * trajectory_point.path_point().s());
725 trajectory_point.mutable_path_point()->set_kappa(-1.0 * trajectory_point.path_point().kappa());
727 trajectory_point.set_v(-1.0 * trajectory_point.v());
728 trajectory_point.set_a(-1.0 * trajectory_point.a());
732bool IterativeAnchoringSmoother::GenerateStopProfileFromPolynomial(
733 const double init_acc,
734 const double init_speed,
735 const double stop_distance,
736 SpeedData* smoothed_speeds) {
737 static constexpr double kMaxT = 8.0;
738 static constexpr double kUnitT = 0.2;
739 for (
double t = 2.0; t <= kMaxT; t += kUnitT) {
740 QuinticPolynomialCurve1d curve(0.0, init_speed, init_acc, stop_distance, 0.0, 0.0, t);
741 if (!IsValidPolynomialProfile(curve)) {
744 for (
double curve_t = 0.0; curve_t <= t; curve_t += kUnitT) {
745 const double curve_s = curve.Evaluate(0, curve_t);
746 const double curve_v = curve.Evaluate(1, curve_t);
747 const double curve_a = curve.Evaluate(2, curve_t);
748 const double curve_da = curve.Evaluate(3, curve_t);
749 smoothed_speeds->AppendSpeedPoint(curve_s, curve_t, curve_v, curve_a, curve_da);
753 AERROR <<
"GenerateStopProfileFromPolynomial fails.";
757bool IterativeAnchoringSmoother::IsValidPolynomialProfile(
const QuinticPolynomialCurve1d& curve) {
758 for (
double evaluate_t = 0.1; evaluate_t <= curve.ParamLength(); evaluate_t += 0.2) {
759 const double v = curve.Evaluate(1, evaluate_t);
760 const double a = curve.Evaluate(2, evaluate_t);
761 static constexpr double kEpsilon = 1e-3;
762 if (v < -kEpsilon || a > 1.0) {
769double IterativeAnchoringSmoother::CalcHeadings(
const DiscretizedPath& path_points,
const size_t index) {
770 CHECK_GT(path_points.size(), 2U);
774 dx = path_points[index + 1].x() - path_points[index].x();
775 dy = path_points[index + 1].y() - path_points[index].y();
776 }
else if (index == path_points.size() - 1) {
777 dx = path_points[index].x() - path_points[index - 1].x();
778 dy = path_points[index].y() - path_points[index - 1].y();
780 dx = 0.5 * (path_points[index + 1].x() - path_points[index - 1].x());
781 dy = 0.5 * (path_points[index + 1].y() - path_points[index - 1].y());
783 return std::atan2(dy, dx);
Rectangular (undirected) bounding box in 2-D.
Implements a class of 2-dimensional vectors.
double DistanceTo(const Vec2d &other) const
Returns the distance to the given vector
static bool ComputePathProfile(const std::vector< std::pair< double, double > > &xy_points, std::vector< double > *headings, std::vector< double > *accumulated_s, std::vector< double > *kappas, std::vector< double > *dkappas)
common::PathPoint Evaluate(const double path_s) const
bool Smooth(const Eigen::MatrixXd &xWS, const double init_a, const double init_v, const std::vector< std::vector< common::math::Vec2d > > &obstacles_vertices_vec, DiscretizedTrajectory *discretized_trajectory)
IterativeAnchoringSmoother(const PlannerOpenSpaceConfig &planner_open_space_config)
Planning module main class.
Math-related util functions.
T Clamp(const T value, T bound1, T bound2)
Clamp a value between two bounds.
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
optional bool estimate_bound
optional double interpolated_delta_s
optional FemPosDeviationSmootherConfig fem_pos_deviation_smoother_config
optional int32 reanchoring_trails_num
optional double vehicle_shortest_dimension
optional double default_bound
optional double reanchoring_pos_stddev
optional double reanchoring_length_stddev
optional double collision_decrease_ratio
optional IterativeAnchoringConfig iterative_anchoring_smoother_config