24#include <unordered_set>
39 planner_open_space_config_.CopyFrom(open_space_conf);
40 reed_shepp_generator_ =
41 std::make_unique<ReedShepp>(vehicle_param_, planner_open_space_config_);
42 grid_a_star_heuristic_generator_ =
43 std::make_unique<GridSearch>(planner_open_space_config_);
56 std::tan(max_steer_angle_ * 2 / (next_node_num_ / 2 - 1));
57 if (arc_length_ < std::sqrt(2) * xy_grid_resolution_) {
58 arc_length_ = std::sqrt(2) * xy_grid_resolution_;
60 AINFO <<
"arc_length" << arc_length_;
61 delta_t_ = planner_open_space_config_.
delta_t();
62 traj_forward_penalty_ =
66 traj_gear_switch_penalty_ =
79 kappa_penalty_weight_ =
108bool HybridAStar::AnalyticExpansion(
109 std::shared_ptr<Node3d> current_node,
110 std::shared_ptr<Node3d>* candidate_final_node) {
111 std::shared_ptr<ReedSheppPath> reeds_shepp_to_check =
112 std::make_shared<ReedSheppPath>();
113 if (!reed_shepp_generator_->ShortestRSP(current_node, end_node_,
114 reeds_shepp_to_check)) {
117 if (!RSPCheck(reeds_shepp_to_check)) {
121 *candidate_final_node = LoadRSPinCS(reeds_shepp_to_check, current_node);
125bool HybridAStar::RSPCheck(
126 const std::shared_ptr<ReedSheppPath> reeds_shepp_to_end) {
127 std::shared_ptr<Node3d> node = std::shared_ptr<Node3d>(
new Node3d(
128 reeds_shepp_to_end->x, reeds_shepp_to_end->y, reeds_shepp_to_end->phi,
129 XYbounds_, planner_open_space_config_));
130 return ValidityCheck(node);
133bool HybridAStar::ValidityCheck(std::shared_ptr<Node3d> node) {
135 CHECK_GT(node->GetStepSize(), 0U);
137 if (obstacles_linesegments_vec_.empty()) {
141 size_t node_step_size = node->GetStepSize();
142 const auto& traversed_x = node->GetXs();
143 const auto& traversed_y = node->GetYs();
144 const auto& traversed_phi = node->GetPhis();
148 size_t check_start_index = 0;
149 if (node_step_size == 1) {
150 check_start_index = 0;
152 check_start_index = 1;
155 for (
size_t i = check_start_index; i < node_step_size; ++i) {
156 if (traversed_x[i] > XYbounds_[1] || traversed_x[i] < XYbounds_[0] ||
157 traversed_y[i] > XYbounds_[3] || traversed_y[i] < XYbounds_[2]) {
161 vehicle_param_, traversed_x[i], traversed_y[i], traversed_phi[i]);
162 for (
const auto& obstacle_linesegments : obstacles_linesegments_vec_) {
163 for (
const common::math::LineSegment2d& linesegment :
164 obstacle_linesegments) {
165 if (bounding_box.HasOverlap(linesegment)) {
166 ADEBUG <<
"collision start at x: " << linesegment.start().x();
167 ADEBUG <<
"collision start at y: " << linesegment.start().y();
168 ADEBUG <<
"collision end at x: " << linesegment.end().x();
169 ADEBUG <<
"collision end at y: " << linesegment.end().y();
178std::shared_ptr<Node3d> HybridAStar::LoadRSPinCS(
179 const std::shared_ptr<ReedSheppPath> reeds_shepp_to_end,
180 std::shared_ptr<Node3d> current_node) {
181 std::shared_ptr<Node3d> end_node = std::shared_ptr<Node3d>(
new Node3d(
182 reeds_shepp_to_end->x, reeds_shepp_to_end->y, reeds_shepp_to_end->phi,
183 XYbounds_, planner_open_space_config_));
184 end_node->SetPre(current_node);
185 end_node->SetTrajCost(current_node->GetTrajCost() + reeds_shepp_to_end->cost);
189std::shared_ptr<Node3d> HybridAStar::Next_node_generator(
190 std::shared_ptr<Node3d> current_node,
size_t next_node_index) {
191 double steering = 0.0;
192 double traveled_distance = 0.0;
193 if (next_node_index <
static_cast<double>(next_node_num_) / 2) {
194 steering = -max_steer_angle_ +
195 (2 * max_steer_angle_ /
196 (
static_cast<double>(next_node_num_) / 2 - 1))
197 *
static_cast<double>(next_node_index);
198 traveled_distance = step_size_;
200 size_t index = next_node_index - next_node_num_ / 2;
201 steering = -max_steer_angle_
202 + (2 * max_steer_angle_
203 / (
static_cast<double>(next_node_num_) / 2 - 1))
204 *
static_cast<double>(index);
205 traveled_distance = -step_size_;
209 std::vector<double> intermediate_x;
210 std::vector<double> intermediate_y;
211 std::vector<double> intermediate_phi;
212 double last_x = current_node->GetX();
213 double last_y = current_node->GetY();
214 double last_phi = current_node->GetPhi();
215 intermediate_x.push_back(last_x);
216 intermediate_y.push_back(last_y);
217 intermediate_phi.push_back(last_phi);
218 for (
size_t i = 0; i < arc_length_ / step_size_; ++i) {
219 const double next_phi = last_phi +
223 const double next_x = last_x +
225 std::cos((last_phi + next_phi) / 2.0);
226 const double next_y = last_y +
228 std::sin((last_phi + next_phi) / 2.0);
229 intermediate_x.push_back(next_x);
230 intermediate_y.push_back(next_y);
237 if (intermediate_x.back() > XYbounds_[1] ||
238 intermediate_x.back() < XYbounds_[0] ||
239 intermediate_y.back() > XYbounds_[3] ||
240 intermediate_y.back() < XYbounds_[2]) {
243 std::shared_ptr<Node3d> next_node = std::shared_ptr<Node3d>(
244 new Node3d(intermediate_x, intermediate_y, intermediate_phi, XYbounds_,
245 planner_open_space_config_));
246 next_node->SetPre(current_node);
247 next_node->SetDirec(traveled_distance > 0.0);
248 next_node->SetSteer(steering);
252void HybridAStar::CalculateNodeCost(
253 std::shared_ptr<Node3d> current_node, std::shared_ptr<Node3d> next_node) {
254 next_node->SetTrajCost(
255 current_node->GetTrajCost() + TrajCost(current_node, next_node));
257 double optimal_path_cost = 0.0;
258 optimal_path_cost += HoloObstacleHeuristic(next_node);
259 next_node->SetHeuCost(optimal_path_cost);
262double HybridAStar::TrajCost(std::shared_ptr<Node3d> current_node,
263 std::shared_ptr<Node3d> next_node) {
265 double piecewise_cost = 0.0;
266 if (next_node->GetDirec()) {
268 static_cast<double>(next_node->GetStepSize() - 1) *
270 traj_forward_penalty_;
273 static_cast<double>(next_node->GetStepSize() - 1) *
277 AINFO <<
"traj cost: " << piecewise_cost;
278 if (current_node->GetDirec() != next_node->GetDirec()) {
279 piecewise_cost += traj_gear_switch_penalty_;
281 piecewise_cost += traj_steer_penalty_ * std::abs(next_node->GetSteer());
282 piecewise_cost += traj_steer_change_penalty_ *
283 std::abs(next_node->GetSteer() - current_node->GetSteer());
284 return piecewise_cost;
287double HybridAStar::HoloObstacleHeuristic(std::shared_ptr<Node3d> next_node) {
288 return grid_a_star_heuristic_generator_->CheckDpMap(
289 next_node->GetX(), next_node->GetY());
292bool HybridAStar::GetResult(HybridAStartResult* result) {
293 std::shared_ptr<Node3d> current_node = final_node_;
294 std::vector<double> hybrid_a_x;
295 std::vector<double> hybrid_a_y;
296 std::vector<double> hybrid_a_phi;
297 AINFO <<
"switch node:" << current_node->GetXs().back()
298 <<
", " << current_node->GetYs().back();
299 AINFO <<
"switch node:" << current_node->GetXs().front()
300 <<
", " << current_node->GetYs().front();
301 AINFO <<
"cost: " << final_node_->GetCost()
302 <<
"," << final_node_->GetTrajCost();
303 while (current_node->GetPreNode() !=
nullptr) {
304 std::vector<double> x = current_node->GetXs();
305 std::vector<double> y = current_node->GetYs();
306 std::vector<double> phi = current_node->GetPhis();
307 if (x.empty() || y.empty() || phi.empty()) {
308 AERROR <<
"result size check failed";
311 if (x.size() != y.size() || x.size() != phi.size()) {
312 AERROR <<
"states sizes are not equal";
315 std::reverse(x.begin(), x.end());
316 std::reverse(y.begin(), y.end());
317 std::reverse(phi.begin(), phi.end());
321 hybrid_a_x.insert(hybrid_a_x.end(), x.begin(), x.end());
322 hybrid_a_y.insert(hybrid_a_y.end(), y.begin(), y.end());
323 hybrid_a_phi.insert(hybrid_a_phi.end(), phi.begin(), phi.end());
324 current_node = current_node->GetPreNode();
326 hybrid_a_x.push_back(current_node->GetX());
327 hybrid_a_y.push_back(current_node->GetY());
328 hybrid_a_phi.push_back(current_node->GetPhi());
329 std::reverse(hybrid_a_x.begin(), hybrid_a_x.end());
330 std::reverse(hybrid_a_y.begin(), hybrid_a_y.end());
331 std::reverse(hybrid_a_phi.begin(), hybrid_a_phi.end());
332 (*result).x = hybrid_a_x;
333 (*result).y = hybrid_a_y;
334 (*result).phi = hybrid_a_phi;
336 if (!GetTemporalProfile(result)) {
337 AERROR <<
"GetSpeedProfile from Hybrid Astar path fails";
341 if (result->x.size() != result->y.size() ||
342 result->x.size() != result->v.size() ||
343 result->x.size() != result->phi.size()) {
344 AERROR <<
"state sizes not equal, "
345 <<
"result->x.size(): " << result->x.size()
346 <<
"result->y.size()" << result->y.size()
347 <<
"result->phi.size()" << result->phi.size()
348 <<
"result->v.size()" << result->v.size();
351 if (result->a.size() != result->steer.size() ||
352 result->x.size() - result->a.size() != 1) {
353 AERROR <<
"control sizes not equal or not right";
354 AERROR <<
" acceleration size: " << result->a.size();
355 AERROR <<
" steer size: " << result->steer.size();
356 AERROR <<
" x size: " << result->x.size();
362bool HybridAStar::GenerateSpeedAcceleration(
363 HybridAStartResult* result) {
364 AINFO <<
"GenerateSpeedAcceleration";
366 if (result->x.size() < 2 || result->y.size() < 2 || result->phi.size() < 2) {
367 AERROR <<
"result size check when generating speed and acceleration fail";
370 const size_t x_size = result->x.size();
374 result->v.push_back(0.0);
375 for (
size_t i = 1; i + 1 < x_size; ++i) {
376 double discrete_v = (((result->x[i + 1] - result->x[i]) / delta_t_) *
377 std::cos(result->phi[i]) +
378 ((result->x[i] - result->x[i - 1]) / delta_t_) *
379 std::cos(result->phi[i])) /
381 (((result->y[i + 1] - result->y[i]) / delta_t_) *
382 std::sin(result->phi[i]) +
383 ((result->y[i] - result->y[i - 1]) / delta_t_) *
384 std::sin(result->phi[i])) /
386 result->v.push_back(discrete_v);
388 result->v.push_back(0.0);
391 for (
size_t i = 0; i + 1 < x_size; ++i) {
392 const double discrete_a = (result->v[i + 1] - result->v[i]) / delta_t_;
393 result->a.push_back(discrete_a);
397 for (
size_t i = 0; i + 1 < x_size; ++i) {
398 double discrete_steer = (result->phi[i + 1] - result->phi[i]) *
400 if (result->v[i] > 0.0) {
401 discrete_steer = std::atan(discrete_steer);
403 discrete_steer = std::atan(-discrete_steer);
405 result->steer.push_back(discrete_steer);
410bool HybridAStar::GenerateSCurveSpeedAcceleration(HybridAStartResult* result) {
411 AINFO <<
"GenerateSCurveSpeedAcceleration";
413 CHECK_NOTNULL(result);
414 if (result->x.size() < 2 || result->y.size() < 2 || result->phi.size() < 2) {
415 AERROR <<
"result size check when generating speed and acceleration fail";
418 if (result->x.size() != result->y.size() ||
419 result->x.size() != result->phi.size()) {
420 AERROR <<
"result sizes not equal";
425 double init_heading = result->phi.front();
426 const Vec2d init_tracking_vector(result->x[1] - result->x[0],
427 result->y[1] - result->y[0]);
430 init_heading - init_tracking_vector.Angle())) < M_PI_2;
433 size_t path_points_size = result->x.size();
435 double accumulated_s = 0.0;
436 result->accumulated_s.clear();
437 auto last_x = result->x.front();
438 auto last_y = result->y.front();
439 for (
size_t i = 0; i < path_points_size; ++i) {
440 double x_diff = result->x[i] - last_x;
441 double y_diff = result->y[i] - last_y;
442 accumulated_s += std::sqrt(x_diff * x_diff + y_diff * y_diff);
443 result->accumulated_s.push_back(accumulated_s);
444 last_x = result->x[i];
445 last_y = result->y[i];
448 const double init_v = 0.0;
449 const double init_a = 0.0;
454 SpeedData speed_data;
457 const double path_length = result->accumulated_s.back();
458 const double total_t =
459 std::max(gear ? 1.5 *
460 (max_forward_v_ * max_forward_v_ +
461 path_length * max_forward_acc_) /
462 (max_forward_acc_ * max_forward_v_)
464 (max_reverse_v_ * max_reverse_v_ +
465 path_length * max_reverse_acc_) /
466 (max_reverse_acc_ * max_reverse_v_),
468 if (total_t + delta_t_ >= delta_t_ * std::numeric_limits<size_t>::max()) {
469 AERROR <<
"Number of knots overflow. total_t: " << total_t
470 <<
", delta_t: " << delta_t_;
473 const size_t num_of_knots =
static_cast<size_t>(total_t / delta_t_) + 1;
475 PiecewiseJerkSpeedProblem piecewise_jerk_problem(
476 num_of_knots, delta_t_, {0.0, std::abs(init_v), std::abs(init_a)});
479 std::vector<std::pair<double, double>> x_bounds(num_of_knots,
482 const double max_v = gear ? max_forward_v_ : max_reverse_v_;
483 const double max_acc = gear ? max_forward_acc_ : max_reverse_acc_;
485 const auto upper_dx = std::fmax(max_v, std::abs(init_v));
486 std::vector<std::pair<double, double>> dx_bounds(num_of_knots,
488 std::vector<std::pair<double, double>> ddx_bounds(num_of_knots,
489 {-max_acc, max_acc});
491 x_bounds[num_of_knots - 1] = std::make_pair(path_length, path_length);
492 dx_bounds[num_of_knots - 1] = std::make_pair(0.0, 0.0);
493 ddx_bounds[num_of_knots - 1] = std::make_pair(0.0, 0.0);
496 std::vector<double> x_ref(num_of_knots, path_length);
497 piecewise_jerk_problem.set_x_ref(ref_s_weight_, std::move(x_ref));
498 piecewise_jerk_problem.set_dx_ref(ref_v_weight_, max_v * 0.8);
499 piecewise_jerk_problem.set_weight_ddx(acc_weight_);
500 piecewise_jerk_problem.set_weight_dddx(jerk_weight_);
501 piecewise_jerk_problem.set_x_bounds(std::move(x_bounds));
502 piecewise_jerk_problem.set_dx_bounds(std::move(dx_bounds));
503 piecewise_jerk_problem.set_ddx_bounds(std::move(ddx_bounds));
504 piecewise_jerk_problem.set_dddx_bound(max_acc_jerk_);
507 if (!piecewise_jerk_problem.Optimize()) {
508 AERROR <<
"Piecewise jerk speed optimizer failed!";
513 const std::vector<double>& s = piecewise_jerk_problem.opt_x();
514 const std::vector<double>& ds = piecewise_jerk_problem.opt_dx();
515 const std::vector<double>& dds = piecewise_jerk_problem.opt_ddx();
518 speed_data.AppendSpeedPoint(s[0], 0.0, ds[0], dds[0], 0.0);
519 const double kEpislon = 1.0e-6;
520 const double sEpislon = 1.0e-6;
521 for (
size_t i = 1; i < num_of_knots; ++i) {
522 if (s[i - 1] - s[i] > kEpislon) {
523 ADEBUG <<
"unexpected decreasing s in speed smoothing at time "
524 <<
static_cast<double>(i) * delta_t_
525 <<
"with total time " << total_t;
528 speed_data.AppendSpeedPoint(
529 s[i], delta_t_ *
static_cast<double>(i), ds[i],
530 dds[i], (dds[i] - dds[i - 1]) / delta_t_);
532 if (path_length - s[i] < sEpislon) {
538 DiscretizedPath path_data;
539 for (
size_t i = 0; i < path_points_size; ++i) {
540 common::PathPoint path_point;
541 path_point.set_x(result->x[i]);
542 path_point.set_y(result->y[i]);
543 path_point.set_theta(result->phi[i]);
544 path_point.set_s(result->accumulated_s[i]);
545 path_data.push_back(std::move(path_point));
548 HybridAStartResult combined_result;
551 const double kDenseTimeResoltuion = 0.5;
552 const double time_horizon = speed_data.TotalTime() +
553 kDenseTimeResoltuion * 1.0e-6;
554 if (path_data.empty()) {
555 AERROR <<
"path data is empty";
558 for (
double cur_rel_time = 0.0; cur_rel_time < time_horizon;
559 cur_rel_time += kDenseTimeResoltuion) {
560 common::SpeedPoint speed_point;
561 if (!speed_data.EvaluateByTime(cur_rel_time, &speed_point)) {
562 AERROR <<
"Fail to get speed point with relative time " << cur_rel_time;
566 if (speed_point.s() > path_data.Length()) {
570 common::PathPoint path_point = path_data.Evaluate(speed_point.s());
572 combined_result.x.push_back(path_point.x());
573 combined_result.y.push_back(path_point.y());
574 combined_result.phi.push_back(path_point.theta());
575 combined_result.accumulated_s.push_back(path_point.s());
577 combined_result.v.push_back(-speed_point.v());
578 combined_result.a.push_back(-speed_point.a());
580 combined_result.v.push_back(speed_point.v());
581 combined_result.a.push_back(speed_point.a());
585 combined_result.a.pop_back();
588 path_points_size = combined_result.x.size();
591 for (
size_t i = 0; i + 1 < path_points_size; ++i) {
592 double discrete_steer =
593 (combined_result.phi[i + 1] - combined_result.phi[i]) *
595 (combined_result.accumulated_s[i + 1] -
596 combined_result.accumulated_s[i]);
598 gear ? std::atan(discrete_steer) :
std::atan(-discrete_steer);
599 combined_result.steer.push_back(discrete_steer);
602 *result = combined_result;
608 std::vector<HybridAStartResult>* partitioned_result) {
609 const auto& x = result.
x;
610 const auto& y = result.
y;
611 const auto& phi = result.
phi;
612 if (x.size() != y.size() || x.size() != phi.size()) {
613 AERROR <<
"states sizes are not equal when do trajectory partitioning of "
614 "Hybrid A Star result";
618 size_t horizon = x.size();
619 partitioned_result->clear();
620 partitioned_result->emplace_back();
621 auto* current_traj = &(partitioned_result->back());
622 double heading_angle = phi.front();
623 const Vec2d init_tracking_vector(x[1] - x[0], y[1] - y[0]);
624 double tracking_angle = init_tracking_vector.
Angle();
629 for (
size_t i = 0; i < horizon - 1; ++i) {
630 heading_angle = phi[i];
631 const Vec2d tracking_vector(x[i + 1] - x[i], y[i + 1] - y[i]);
632 tracking_angle = tracking_vector.
Angle();
636 if (gear != current_gear) {
637 current_traj->x.push_back(x[i]);
638 current_traj->y.push_back(y[i]);
639 current_traj->phi.push_back(phi[i]);
640 partitioned_result->emplace_back();
641 current_traj = &(partitioned_result->back());
644 current_traj->x.push_back(x[i]);
645 current_traj->y.push_back(y[i]);
646 current_traj->phi.push_back(phi[i]);
648 current_traj->x.push_back(x.back());
649 current_traj->y.push_back(y.back());
650 current_traj->phi.push_back(phi.back());
652 const auto start_timestamp = std::chrono::system_clock::now();
655 for (
auto& result : *partitioned_result) {
656 if (FLAGS_use_s_curve_speed_smooth) {
657 if (!GenerateSCurveSpeedAcceleration(&result)) {
658 AERROR <<
"GenerateSCurveSpeedAcceleration fail";
662 if (!GenerateSpeedAcceleration(&result)) {
663 AERROR <<
"GenerateSpeedAcceleration fail";
669 const auto end_timestamp = std::chrono::system_clock::now();
670 std::chrono::duration<double> diff = end_timestamp - start_timestamp;
671 ADEBUG <<
"speed profile total time: " << diff.count() * 1000.0 <<
" ms.";
676 std::vector<HybridAStartResult> partitioned_results;
678 AERROR <<
"TrajectoryPartition fail";
681 ADEBUG <<
"PARTION SIZE " << partitioned_results.size();
682 HybridAStartResult stitched_result;
683 for (
const auto& result : partitioned_results) {
684 std::copy(result.
x.begin(), result.
x.end() - 1,
685 std::back_inserter(stitched_result.x));
686 std::copy(result.
y.begin(), result.
y.end() - 1,
687 std::back_inserter(stitched_result.y));
688 std::copy(result.
phi.begin(), result.
phi.end() - 1,
689 std::back_inserter(stitched_result.phi));
690 std::copy(result.
v.begin(), result.
v.end() - 1,
691 std::back_inserter(stitched_result.v));
692 std::copy(result.
a.begin(), result.
a.end(),
693 std::back_inserter(stitched_result.a));
694 std::copy(result.
steer.begin(), result.
steer.end(),
695 std::back_inserter(stitched_result.steer));
697 stitched_result.x.push_back(partitioned_results.back().x.back());
698 stitched_result.y.push_back(partitioned_results.back().y.back());
699 stitched_result.phi.push_back(partitioned_results.back().phi.back());
700 stitched_result.v.push_back(partitioned_results.back().v.back());
701 *result = stitched_result;
706 double sx,
double sy,
double sphi,
double ex,
double ey,
double ephi,
707 const std::vector<double>& XYbounds,
708 const std::vector<std::vector<common::math::Vec2d>>& obstacles_vertices_vec,
710 const std::vector<std::vector<common::math::Vec2d>>&
711 soft_boundary_vertices_vec,
712 bool reeds_sheep_last_straight) {
713 reed_shepp_generator_->reeds_sheep_last_straight_ = reeds_sheep_last_straight;
717 open_pq_ =
decltype(open_pq_)();
718 final_node_ =
nullptr;
720 std::vector<std::vector<common::math::LineSegment2d>>
721 obstacles_linesegments_vec;
722 for (
const auto& obstacle_vertices : obstacles_vertices_vec) {
723 size_t vertices_num = obstacle_vertices.size();
724 std::vector<common::math::LineSegment2d> obstacle_linesegments;
725 for (
size_t i = 0; i < vertices_num - 1; ++i) {
728 obstacle_vertices[i], obstacle_vertices[i + 1]);
729 obstacle_linesegments.emplace_back(line_segment);
731 obstacles_linesegments_vec.emplace_back(obstacle_linesegments);
733 obstacles_linesegments_vec_ = std::move(obstacles_linesegments_vec);
734 for (
size_t i = 0; i < obstacles_linesegments_vec_.size(); i++) {
735 for (
auto linesg : obstacles_linesegments_vec_[i]) {
736 std::string name = std::to_string(i) +
"roi_boundary";
737 print_curves.
AddPoint(name, linesg.start());
738 print_curves.
AddPoint(name, linesg.end());
741 Vec2d sposition(sx, sy);
742 Vec2d svec_to_center(
747 Vec2d scenter(sposition + svec_to_center.
rotate(sphi));
750 Vec2d eposition(ex, ey);
751 print_curves.
AddPoint(
"end_position", eposition);
752 Vec2d evec_to_center(
757 Vec2d ecenter(eposition + evec_to_center.
rotate(ephi));
760 XYbounds_ = XYbounds;
763 new Node3d({sx}, {sy}, {sphi}, XYbounds_, planner_open_space_config_));
765 new Node3d({ex}, {ey}, {ephi}, XYbounds_, planner_open_space_config_));
766 AINFO <<
"start node" << sx <<
"," << sy <<
"," << sphi;
767 AINFO <<
"end node " << ex <<
"," << ey <<
"," << ephi;
768 if (!ValidityCheck(start_node_)) {
769 AERROR <<
"start_node in collision with obstacles";
770 AERROR << start_node_->GetX()
771 <<
"," << start_node_->GetY()
772 <<
"," << start_node_->GetPhi();
776 if (!ValidityCheck(end_node_)) {
777 AERROR <<
"end_node in collision with obstacles";
782 grid_a_star_heuristic_generator_->GenerateDpMap(
783 ex, ey, XYbounds_, obstacles_linesegments_vec_);
786 open_set_.insert(start_node_->GetIndex());
787 open_pq_.emplace(start_node_, start_node_->GetCost());
789 size_t explored_node_num = 0;
790 size_t available_result_num = 0;
791 auto best_explored_num = explored_node_num;
792 auto best_available_result_num = available_result_num;
794 double heuristic_time = 0.0;
795 double rs_time = 0.0;
796 double node_generator_time = 0.0;
797 double validity_check_time = 0.0;
798 size_t max_explored_num =
800 size_t desired_explored_num = std::min(
803 static constexpr int kMaxNodeNum = 200000;
804 std::vector<std::shared_ptr<Node3d>> candidate_final_nodes;
805 while (!open_pq_.empty() &&
806 open_pq_.size() < kMaxNodeNum &&
807 available_result_num < desired_explored_num &&
808 explored_node_num < max_explored_num) {
809 std::shared_ptr<Node3d> current_node = open_pq_.top().first;
812 std::shared_ptr<Node3d> final_node =
nullptr;
813 if (AnalyticExpansion(current_node, &final_node)) {
814 if (final_node_ ==
nullptr ||
815 final_node_->GetTrajCost() > final_node->GetTrajCost()) {
816 final_node_ = final_node;
817 best_explored_num = explored_node_num + 1;
818 best_available_result_num = available_result_num + 1;
820 available_result_num++;
824 rs_time += rs_end_time - rs_start_time;
825 close_set_.insert(current_node->GetIndex());
830 available_result_num > 0) {
834 size_t begin_index = 0;
835 size_t end_index = next_node_num_;
836 std::unordered_set<std::string> temp_set;
837 for (
size_t i = begin_index; i < end_index; ++i) {
839 std::shared_ptr<Node3d> next_node = Next_node_generator(current_node, i);
843 if (next_node ==
nullptr) {
847 if (close_set_.count(next_node->GetIndex()) > 0) {
852 if (!ValidityCheck(next_node)) {
856 if (open_set_.count(next_node->GetIndex()) == 0) {
858 CalculateNodeCost(current_node, next_node);
860 heuristic_time += end_time - start_time;
861 temp_set.insert(next_node->GetIndex());
862 open_pq_.emplace(next_node, next_node->GetCost());
865 open_set_.insert(temp_set.begin(), temp_set.end());
868 if (final_node_ ==
nullptr) {
869 AERROR <<
"Hybird A* cannot find a valid path";
874 AINFO <<
"open_pq_.empty()" << (open_pq_.empty() ?
"true" :
"false");
875 AINFO <<
"open_pq_.size()" << open_pq_.size();
876 AINFO <<
"desired_explored_num" << desired_explored_num;
877 AINFO <<
"min cost is : " << final_node_->GetTrajCost();
878 AINFO <<
"max_explored_num is " << max_explored_num;
879 AINFO <<
"explored node num is " << explored_node_num
880 <<
"available_result_num " << available_result_num;
881 AINFO <<
"best_explored_num is " << best_explored_num
882 <<
"best_available_result_num is " << best_available_result_num;
883 AINFO <<
"cal node time is " << heuristic_time
884 <<
"validity_check_time " << validity_check_time
885 <<
"node_generator_time " << node_generator_time;
886 AINFO <<
"reed shepp time is " << rs_time;
887 AINFO <<
"hybrid astar total time is "
891 "rs_point", final_node_->GetXs().front(), final_node_->GetYs().front());
892 if (!GetResult(result)) {
893 AERROR <<
"GetResult failed";
897 for (
size_t i = 0; i < result->
x.size(); i++) {
898 print_curves.
AddPoint(
"warm_path", result->
x[i], result->
y[i]);
Rectangular (undirected) bounding box in 2-D.
void GetAllCorners(std::vector< Vec2d > *const corners) const
Getter of the corners of the box
Implements a class of 2-dimensional vectors.
Vec2d rotate(const double angle) const
rotate the vector by angle.
double Angle() const
Gets the angle between the vector and the positive x semi-axis
a singleton clock that can be used to get the current timestamp.
static double NowInSeconds()
gets the current time in second.
HybridAStar(const PlannerOpenSpaceConfig &open_space_conf)
bool TrajectoryPartition(const HybridAStartResult &result, std::vector< HybridAStartResult > *partitioned_result)
bool Plan(double sx, double sy, double sphi, double ex, double ey, double ephi, const std::vector< double > &XYbounds, const std::vector< std::vector< common::math::Vec2d > > &obstacles_vertices_vec, HybridAStartResult *result, const std::vector< std::vector< common::math::Vec2d > > &soft_boundary_vertices_vec={}, bool reeds_sheep_last_straight=false)
static apollo::common::math::Box2d GetBoundingBox(const common::VehicleParam &vehicle_param_, const double x, const double y, const double phi)
void AddPoint(std::string key, double x, double y)
add point to curve key
Planning module main class.
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
optional double max_steer_angle
optional double left_edge_to_center
optional double back_edge_to_center
optional double steer_ratio
optional double front_edge_to_center
optional double wheel_base
optional double right_edge_to_center
std::vector< double > steer
std::vector< double > phi
optional double max_forward_v
optional double max_forward_acc
optional double max_acc_jerk
optional double max_reverse_acc
optional double max_reverse_v
optional SpeedOptimizerConfig s_curve_config
optional WarmStartConfig warm_start_config
optional IterativeAnchoringConfig iterative_anchoring_smoother_config
optional double jerk_weight
optional double ref_v_weight
optional double kappa_penalty_weight
optional double acc_weight
optional double ref_s_weight
optional double traj_back_penalty
optional double phi_grid_resolution
optional int32 max_explored_num
optional double traj_steer_penalty
optional double step_size
optional int32 desired_explored_num
optional double traj_steer_change_penalty
optional double astar_max_search_time
optional double xy_grid_resolution
optional double traj_gear_switch_penalty
optional uint64 next_node_num
optional double traj_kappa_contraint_ratio
optional double traj_forward_penalty