Skip to content

Commit 69348a2

Browse files
authored
Merge pull request #1418 from tier4/fix/start_goal_v0.29.0
fix(star/goal_planner): improve start/goal planner
2 parents 287b69c + e553faa commit 69348a2

File tree

12 files changed

+224
-65
lines changed

12 files changed

+224
-65
lines changed

common/autoware_motion_utils/include/autoware/motion_utils/trajectory/trajectory.hpp

+33-16
Original file line numberDiff line numberDiff line change
@@ -991,34 +991,51 @@ calcCurvature<std::vector<autoware_planning_msgs::msg::TrajectoryPoint>>(
991991
* curvature calculation
992992
*/
993993
template <class T>
994-
std::vector<std::pair<double, double>> calcCurvatureAndArcLength(const T & points)
994+
std::vector<std::pair<double, std::pair<double, double>>> calcCurvatureAndSegmentLength(
995+
const T & points)
995996
{
996-
// Note that arclength is for the segment, not the sum.
997-
std::vector<std::pair<double, double>> curvature_arc_length_vec;
998-
curvature_arc_length_vec.emplace_back(0.0, 0.0);
997+
// segment length is pair of segment length between {p1, p2} and {p2, p3}
998+
std::vector<std::pair<double, std::pair<double, double>>> curvature_and_segment_length_vec;
999+
curvature_and_segment_length_vec.reserve(points.size());
1000+
curvature_and_segment_length_vec.emplace_back(0.0, std::make_pair(0.0, 0.0));
9991001
for (size_t i = 1; i < points.size() - 1; ++i) {
10001002
const auto p1 = autoware::universe_utils::getPoint(points.at(i - 1));
10011003
const auto p2 = autoware::universe_utils::getPoint(points.at(i));
10021004
const auto p3 = autoware::universe_utils::getPoint(points.at(i + 1));
10031005
const double curvature = autoware::universe_utils::calcCurvature(p1, p2, p3);
1004-
const double arc_length =
1005-
autoware::universe_utils::calcDistance2d(points.at(i - 1), points.at(i)) +
1006-
autoware::universe_utils::calcDistance2d(points.at(i), points.at(i + 1));
1007-
curvature_arc_length_vec.emplace_back(curvature, arc_length);
1006+
1007+
// The first point has only the next point, so put the distance to that point.
1008+
// In other words, assign the first segment length at the second point to the
1009+
// second_segment_length at the first point.
1010+
if (i == 1) {
1011+
curvature_and_segment_length_vec.at(0).second.second =
1012+
autoware::universe_utils::calcDistance2d(p1, p2);
1013+
}
1014+
1015+
// The second_segment_length of the previous point and the first segment length of the current
1016+
// point are equal.
1017+
const std::pair<double, double> arc_length{
1018+
curvature_and_segment_length_vec.back().second.second,
1019+
autoware::universe_utils::calcDistance2d(p2, p3)};
1020+
1021+
curvature_and_segment_length_vec.emplace_back(curvature, arc_length);
10081022
}
1009-
curvature_arc_length_vec.emplace_back(0.0, 0.0);
10101023

1011-
return curvature_arc_length_vec;
1024+
// set to the last point
1025+
curvature_and_segment_length_vec.emplace_back(
1026+
0.0, std::make_pair(curvature_and_segment_length_vec.back().second.second, 0.0));
1027+
1028+
return curvature_and_segment_length_vec;
10121029
}
10131030

1014-
extern template std::vector<std::pair<double, double>>
1015-
calcCurvatureAndArcLength<std::vector<autoware_planning_msgs::msg::PathPoint>>(
1031+
extern template std::vector<std::pair<double, std::pair<double, double>>>
1032+
calcCurvatureAndSegmentLength<std::vector<autoware_planning_msgs::msg::PathPoint>>(
10161033
const std::vector<autoware_planning_msgs::msg::PathPoint> & points);
1017-
extern template std::vector<std::pair<double, double>>
1018-
calcCurvatureAndArcLength<std::vector<tier4_planning_msgs::msg::PathPointWithLaneId>>(
1034+
extern template std::vector<std::pair<double, std::pair<double, double>>>
1035+
calcCurvatureAndSegmentLength<std::vector<tier4_planning_msgs::msg::PathPointWithLaneId>>(
10191036
const std::vector<tier4_planning_msgs::msg::PathPointWithLaneId> & points);
1020-
extern template std::vector<std::pair<double, double>>
1021-
calcCurvatureAndArcLength<std::vector<autoware_planning_msgs::msg::TrajectoryPoint>>(
1037+
extern template std::vector<std::pair<double, std::pair<double, double>>>
1038+
calcCurvatureAndSegmentLength<std::vector<autoware_planning_msgs::msg::TrajectoryPoint>>(
10221039
const std::vector<autoware_planning_msgs::msg::TrajectoryPoint> & points);
10231040

10241041
/**

common/autoware_motion_utils/src/trajectory/trajectory.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,14 @@ calcCurvature<std::vector<autoware_planning_msgs::msg::TrajectoryPoint>>(
238238
const std::vector<autoware_planning_msgs::msg::TrajectoryPoint> & points);
239239

240240
//
241-
template std::vector<std::pair<double, double>>
242-
calcCurvatureAndArcLength<std::vector<autoware_planning_msgs::msg::PathPoint>>(
241+
template std::vector<std::pair<double, std::pair<double, double>>>
242+
calcCurvatureAndSegmentLength<std::vector<autoware_planning_msgs::msg::PathPoint>>(
243243
const std::vector<autoware_planning_msgs::msg::PathPoint> & points);
244-
template std::vector<std::pair<double, double>>
245-
calcCurvatureAndArcLength<std::vector<tier4_planning_msgs::msg::PathPointWithLaneId>>(
244+
template std::vector<std::pair<double, std::pair<double, double>>>
245+
calcCurvatureAndSegmentLength<std::vector<tier4_planning_msgs::msg::PathPointWithLaneId>>(
246246
const std::vector<tier4_planning_msgs::msg::PathPointWithLaneId> & points);
247-
template std::vector<std::pair<double, double>>
248-
calcCurvatureAndArcLength<std::vector<autoware_planning_msgs::msg::TrajectoryPoint>>(
247+
template std::vector<std::pair<double, std::pair<double, double>>>
248+
calcCurvatureAndSegmentLength<std::vector<autoware_planning_msgs::msg::TrajectoryPoint>>(
249249
const std::vector<autoware_planning_msgs::msg::TrajectoryPoint> & points);
250250

251251
//

planning/behavior_path_planner/autoware_behavior_path_goal_planner_module/config/goal_planner.param.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
lateral_offset_interval: 0.25
2323
ignore_distance_from_lane_start: 0.0
2424
margin_from_boundary: 0.5
25+
high_curvature_threshold: 0.1
2526

2627
# occupancy grid map
2728
occupancy_grid:

planning/behavior_path_planner/autoware_behavior_path_goal_planner_module/include/autoware/behavior_path_goal_planner_module/goal_planner_parameters.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct GoalPlannerParameters
6060
double lateral_offset_interval{0.0};
6161
double ignore_distance_from_lane_start{0.0};
6262
double margin_from_boundary{0.0};
63+
double high_curvature_threshold{0.0};
6364

6465
// occupancy grid map
6566
bool use_occupancy_grid_for_goal_search{false};

planning/behavior_path_planner/autoware_behavior_path_goal_planner_module/include/autoware/behavior_path_goal_planner_module/pull_over_planner_base.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct PullOverPath
5252
size_t goal_id{};
5353
size_t id{};
5454
bool decided_velocity{false};
55+
double max_curvature{0.0}; // max curvature of the parking path
5556

5657
PathWithLaneId getFullPath() const
5758
{
@@ -72,6 +73,7 @@ struct PullOverPath
7273
return path;
7374
}
7475

76+
// path from the pull over start pose to the end pose
7577
PathWithLaneId getParkingPath() const
7678
{
7779
const PathWithLaneId full_path = getFullPath();

planning/behavior_path_planner/autoware_behavior_path_goal_planner_module/src/goal_planner_module.cpp

+87-34
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,18 @@ void GoalPlannerModule::onTimer()
293293
planner->setPlannerData(local_planner_data);
294294
planner->setPreviousModuleOutput(previous_module_output);
295295
auto pull_over_path = planner->plan(goal_candidate.goal_pose);
296-
if (pull_over_path) {
296+
if (pull_over_path && pull_over_path->getParkingPath().points.size() >= 3) {
297297
pull_over_path->goal_id = goal_candidate.id;
298298
pull_over_path->id = path_candidates.size();
299+
300+
// calculate absolute maximum curvature of parking path(start pose to end pose) for path
301+
// priority
302+
const std::vector<double> curvatures =
303+
autoware::motion_utils::calcCurvature(pull_over_path->getParkingPath().points);
304+
pull_over_path->max_curvature = std::abs(*std::max_element(
305+
curvatures.begin(), curvatures.end(),
306+
[](const double & a, const double & b) { return std::abs(a) < std::abs(b); }));
307+
299308
path_candidates.push_back(*pull_over_path);
300309
// calculate closest pull over start pose for stop path
301310
const double start_arc_length =
@@ -817,23 +826,37 @@ std::vector<PullOverPath> GoalPlannerModule::sortPullOverPathCandidatesByGoalPri
817826
const auto debugPrintPathPriority =
818827
[this](
819828
const std::vector<PullOverPath> & sorted_pull_over_path_candidates,
820-
const std::map<size_t, size_t> & goal_id_to_index,
821-
const std::optional<std::map<size_t, double>> & path_id_to_margin_map_opt = std::nullopt,
822-
const std::optional<std::function<bool(const PullOverPath &)>> & isSoftMarginOpt =
823-
std::nullopt) {
829+
const std::map<size_t, size_t> & goal_id_to_index, const GoalCandidates & goal_candidates,
830+
const std::map<size_t, double> & path_id_to_margin_map,
831+
const std::function<bool(const PullOverPath &)> & isSoftMargin,
832+
const std::function<bool(const PullOverPath &)> & isHighCurvature) {
824833
std::stringstream ss;
825-
ss << "\n---------------------- path priority ----------------------\n";
826-
for (const auto & path : sorted_pull_over_path_candidates) {
827-
// clang-format off
828-
ss << "path_type: " << magic_enum::enum_name(path.type)
829-
<< ", path_id: " << path.id
830-
<< ", goal_id: " << path.goal_id
831-
<< ", goal_priority:" << goal_id_to_index.at(path.goal_id);
832-
// clang-format on
833-
if (path_id_to_margin_map_opt && isSoftMarginOpt) {
834-
ss << ", margin: " << path_id_to_margin_map_opt->at(path.id)
835-
<< ((*isSoftMarginOpt)(path) ? " (soft)" : " (hard)");
834+
835+
// unsafe goal and it's priority are not visible as debug marker in rviz,
836+
// so exclude unsafe goal from goal_priority
837+
std::map<size_t, int> goal_id_and_priority;
838+
{
839+
int priority = 0;
840+
for (const auto & goal_candidate : goal_candidates) {
841+
goal_id_and_priority[goal_candidate.id] = goal_candidate.is_safe ? priority++ : -1;
836842
}
843+
}
844+
845+
ss << "\n---------------------- path priority ----------------------\n";
846+
for (size_t i = 0; i < sorted_pull_over_path_candidates.size(); ++i) {
847+
const auto & path = sorted_pull_over_path_candidates[i];
848+
849+
// goal_index is same to goal priority including unsafe goal
850+
const int goal_index = static_cast<int>(goal_id_to_index.at(path.goal_id));
851+
const bool is_safe_goal = goal_candidates[goal_index].is_safe;
852+
const int goal_priority = goal_id_and_priority[path.goal_id];
853+
854+
ss << "path_priority: " << i << ", path_type: " << magic_enum::enum_name(path.type)
855+
<< ", path_id: " << path.id << ", goal_id: " << path.goal_id
856+
<< ", goal_priority: " << (is_safe_goal ? std::to_string(goal_priority) : "unsafe")
857+
<< ", margin: " << path_id_to_margin_map.at(path.id)
858+
<< (isSoftMargin(path) ? " (soft)" : " (hard)") << ", curvature: " << path.max_curvature
859+
<< (isHighCurvature(path) ? " (high)" : " (low)");
837860
ss << "\n";
838861
}
839862
ss << "-----------------------------------------------------------\n";
@@ -844,6 +867,7 @@ std::vector<PullOverPath> GoalPlannerModule::sortPullOverPathCandidatesByGoalPri
844867
const auto & soft_margins = parameters_->object_recognition_collision_check_soft_margins;
845868
const auto & hard_margins = parameters_->object_recognition_collision_check_hard_margins;
846869

870+
// (1) Sort pull_over_path_candidates based on the order in goal_candidates
847871
// Create a map of goal_id to its index in goal_candidates
848872
std::map<size_t, size_t> goal_id_to_index;
849873
for (size_t i = 0; i < goal_candidates.size(); ++i) {
@@ -868,6 +892,7 @@ std::vector<PullOverPath> GoalPlannerModule::sortPullOverPathCandidatesByGoalPri
868892

869893
// if object recognition is enabled, sort by collision check margin
870894
if (parameters_->use_object_recognition) {
895+
// (2) Sort by collision check margins
871896
const std::vector<double> margins = std::invoke([&]() {
872897
std::vector<double> combined_margins = soft_margins;
873898
combined_margins.insert(combined_margins.end(), hard_margins.begin(), hard_margins.end());
@@ -914,42 +939,70 @@ std::vector<PullOverPath> GoalPlannerModule::sortPullOverPathCandidatesByGoalPri
914939
return path_id_to_margin_map[a.id] > path_id_to_margin_map[b.id];
915940
});
916941

917-
// Sort pull_over_path_candidates based on the order in efficient_path_order
918-
if (parameters_->path_priority == "efficient_path") {
919-
const auto isSoftMargin = [&](const PullOverPath & path) -> bool {
920-
const double margin = path_id_to_margin_map[path.id];
921-
return std::any_of(
922-
soft_margins.begin(), soft_margins.end(),
923-
[margin](const double soft_margin) { return std::abs(margin - soft_margin) < 0.01; });
924-
};
925-
const auto isSameHardMargin = [&](const PullOverPath & a, const PullOverPath & b) -> bool {
926-
return !isSoftMargin(a) && !isSoftMargin(b) &&
927-
std::abs(path_id_to_margin_map[a.id] - path_id_to_margin_map[b.id]) < 0.01;
928-
};
942+
// (3) Sort by curvature
943+
// If the curvature is less than the threshold, prioritize the path.
944+
const auto isHighCurvature = [&](const PullOverPath & path) -> bool {
945+
return path.max_curvature >= parameters_->high_curvature_threshold;
946+
};
929947

948+
const auto isSoftMargin = [&](const PullOverPath & path) -> bool {
949+
const double margin = path_id_to_margin_map[path.id];
950+
return std::any_of(
951+
soft_margins.begin(), soft_margins.end(),
952+
[margin](const double soft_margin) { return std::abs(margin - soft_margin) < 0.01; });
953+
};
954+
const auto isSameHardMargin = [&](const PullOverPath & a, const PullOverPath & b) -> bool {
955+
return !isSoftMargin(a) && !isSoftMargin(b) &&
956+
std::abs(path_id_to_margin_map[a.id] - path_id_to_margin_map[b.id]) < 0.01;
957+
};
958+
959+
// NOTE: this is just partition sort based on curvature threshold within each sub partitions
960+
std::stable_sort(
961+
sorted_pull_over_path_candidates.begin(), sorted_pull_over_path_candidates.end(),
962+
[&](const PullOverPath & a, const PullOverPath & b) {
963+
// if both are soft margin or both are same hard margin, prioritize the path with lower
964+
// curvature.
965+
if ((isSoftMargin(a) && isSoftMargin(b)) || isSameHardMargin(a, b)) {
966+
return !isHighCurvature(a) && isHighCurvature(b);
967+
}
968+
// otherwise, keep the order based on the margin.
969+
return false;
970+
});
971+
972+
// (4) Sort pull_over_path_candidates based on the order in efficient_path_order keeping the
973+
// collision check margin and curvature priority.
974+
if (parameters_->path_priority == "efficient_path") {
930975
std::stable_sort(
931976
sorted_pull_over_path_candidates.begin(), sorted_pull_over_path_candidates.end(),
932977
[&](const auto & a, const auto & b) {
933-
// if both are soft margin or both are same hard margin, sort by planner priority
978+
// if any of following conditions are met, sort by path type priority
979+
// - both are soft margin
980+
// - both are same hard margin
934981
if ((isSoftMargin(a) && isSoftMargin(b)) || isSameHardMargin(a, b)) {
935982
return comparePathTypePriority(a, b);
936983
}
937984
// otherwise, keep the order.
938985
return false;
939986
});
940987

941-
// debug print path priority: sorted by efficient_path_order and collision check margin
988+
// debug print path priority sorted by
989+
// - efficient_path_order
990+
// - collision check margin
991+
// - curvature
942992
debugPrintPathPriority(
943-
sorted_pull_over_path_candidates, goal_id_to_index, path_id_to_margin_map, isSoftMargin);
993+
sorted_pull_over_path_candidates, goal_id_to_index, goal_candidates, path_id_to_margin_map,
994+
isSoftMargin, isHighCurvature);
944995
}
945996
} else {
946-
// Sort pull_over_path_candidates based on the order in efficient_path_order
997+
/**
998+
* NOTE: use_object_recognition=false is not recommended. This option will be deprecated in the
999+
* future. sort by curvature is not implemented yet.
1000+
* Sort pull_over_path_candidates based on the order in efficient_path_order
1001+
*/
9471002
if (parameters_->path_priority == "efficient_path") {
9481003
std::stable_sort(
9491004
sorted_pull_over_path_candidates.begin(), sorted_pull_over_path_candidates.end(),
9501005
[&](const auto & a, const auto & b) { return comparePathTypePriority(a, b); });
951-
// debug print path priority: sorted by efficient_path_order and collision check margin
952-
debugPrintPathPriority(sorted_pull_over_path_candidates, goal_id_to_index);
9531006
}
9541007
}
9551008

planning/behavior_path_planner/autoware_behavior_path_goal_planner_module/src/manager.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ void GoalPlannerModuleManager::init(rclcpp::Node * node)
6161
p.ignore_distance_from_lane_start =
6262
node->declare_parameter<double>(ns + "ignore_distance_from_lane_start");
6363
p.margin_from_boundary = node->declare_parameter<double>(ns + "margin_from_boundary");
64+
p.high_curvature_threshold = node->declare_parameter<double>(ns + "high_curvature_threshold");
6465

6566
const std::string parking_policy_name =
6667
node->declare_parameter<std::string>(ns + "parking_policy");

planning/behavior_path_planner/autoware_behavior_path_goal_planner_module/src/shift_pull_over.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,19 @@ double ShiftPullOver::calcBeforeShiftedArcLength(
308308

309309
double before_arc_length{0.0};
310310
double after_arc_length{0.0};
311-
for (const auto & [k, segment_length] :
312-
autoware::motion_utils::calcCurvatureAndArcLength(reversed_path.points)) {
311+
312+
const auto curvature_and_segment_length =
313+
autoware::motion_utils::calcCurvatureAndSegmentLength(reversed_path.points);
314+
315+
for (size_t i = 0; i < curvature_and_segment_length.size(); ++i) {
316+
const auto & [k, segment_length_pair] = curvature_and_segment_length[i];
317+
318+
// If it is the last point, add the lengths of the previous and next segments.
319+
// For other points, only add the length of the previous segment.
320+
const double segment_length = i == curvature_and_segment_length.size() - 1
321+
? segment_length_pair.first
322+
: segment_length_pair.first + segment_length_pair.second;
323+
313324
// after shifted segment length
314325
const double after_segment_length =
315326
k > 0 ? segment_length * (1 + k * dr) : segment_length / (1 - k * dr);

planning/behavior_path_planner/autoware_behavior_path_start_planner_module/include/autoware/behavior_path_start_planner_module/data_structs.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ struct StartPlannerDebugData
9090
std::vector<Pose> start_pose_candidates;
9191
size_t selected_start_pose_candidate_index;
9292
double margin_for_start_pose_candidate;
93+
94+
// for isPreventingRearVehicleFromPassingThrough
95+
std::optional<Pose> estimated_stop_pose;
9396
};
9497

9598
struct StartPlannerParameters

planning/behavior_path_planner/autoware_behavior_path_start_planner_module/include/autoware/behavior_path_start_planner_module/start_planner_module.hpp

+23
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,31 @@ class StartPlannerModule : public SceneModuleInterface
229229

230230
bool isModuleRunning() const;
231231
bool isCurrentPoseOnMiddleOfTheRoad() const;
232+
233+
/**
234+
* @brief Check if the ego vehicle is preventing the rear vehicle from passing through.
235+
*
236+
* This function just call isPreventingRearVehicleFromPassingThrough(const Pose & ego_pose) with
237+
* two poses. If rear vehicle is obstructed by ego vehicle at either of the two poses, it returns
238+
* true.
239+
*
240+
* @return true if the ego vehicle is preventing the rear vehicle from passing through with the
241+
* current pose or the pose if it stops.
242+
*/
232243
bool isPreventingRearVehicleFromPassingThrough() const;
233244

245+
/**
246+
* @brief Check if the ego vehicle is preventing the rear vehicle from passing through.
247+
*
248+
* This function measures the distance to the lane boundary from the current pose and the pose if
249+
it stops, and determines whether there is enough space for the rear vehicle to pass through. If
250+
* it is obstructing at either of the two poses, it returns true.
251+
*
252+
* @return true if the ego vehicle is preventing the rear vehicle from passing through with given
253+
ego pose.
254+
*/
255+
bool isPreventingRearVehicleFromPassingThrough(const Pose & ego_pose) const;
256+
234257
bool isCloseToOriginalStartPose() const;
235258
bool hasArrivedAtGoal() const;
236259
bool isMoving() const;

planning/behavior_path_planner/autoware_behavior_path_start_planner_module/src/shift_pull_out.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,17 @@ double ShiftPullOut::calcBeforeShiftedArcLength(
423423
double before_arc_length{0.0};
424424
double after_arc_length{0.0};
425425

426-
for (const auto & [k, segment_length] :
427-
autoware::motion_utils::calcCurvatureAndArcLength(path.points)) {
426+
const auto curvatures_and_segment_lengths =
427+
autoware::motion_utils::calcCurvatureAndSegmentLength(path.points);
428+
for (size_t i = 0; i < curvatures_and_segment_lengths.size(); ++i) {
429+
const auto & [k, segment_length_pair] = curvatures_and_segment_lengths.at(i);
430+
431+
// If it is the last point, add the lengths of the previous and next segments.
432+
// For other points, only add the length of the previous segment.
433+
const double segment_length = i == curvatures_and_segment_lengths.size() - 1
434+
? segment_length_pair.first + segment_length_pair.second
435+
: segment_length_pair.first;
436+
428437
// after shifted segment length
429438
const double after_segment_length =
430439
k < 0 ? segment_length * (1 - k * dr) : segment_length / (1 + k * dr);

0 commit comments

Comments
 (0)