+
+
+
+
+ Red Car - Top Viewimage/svg+xmlOpenclipartRed Car - Top View
+ 2010-05-19T15:02:12
+
+ I was thinking of Trophy ( http://trophy.sourceforge.net/index.php?body=screenshots ) when remixing this one :)
+ http://openclipart.org/detail/61201/red-racing-car-top-view-by-qubodupqubodup
+ car
+ clip artclipartgame
+ game sprite
+ racingracing carred
+ red car
+ simplesimple carsprite
+ transport
+ transportationtravelvideo game
+ video game art
+ video game sprite
+
+
diff --git a/planning/behavior_path_goal_planner_module/images/goal_planner-safety_check.drawio.svg b/planning/behavior_path_goal_planner_module/images/goal_planner-safety_check.drawio.svg
new file mode 100644
index 0000000000000..4fe6313a8da45
--- /dev/null
+++ b/planning/behavior_path_goal_planner_module/images/goal_planner-safety_check.drawio.svg
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/planning/behavior_path_goal_planner_module/images/goal_planner-threads.drawio.svg b/planning/behavior_path_goal_planner_module/images/goal_planner-threads.drawio.svg
new file mode 100644
index 0000000000000..aff3293e5a279
--- /dev/null
+++ b/planning/behavior_path_goal_planner_module/images/goal_planner-threads.drawio.svg
@@ -0,0 +1,651 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pull over path candidates
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sort paths by priority
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generate goal candidates
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ select highest priority collision free path
+
+
+
+
+
+
+
+
+
+
+
+
+
+
run()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ main thread
+
+
+
+
+
+
+
+
+
+
+
+
+
+
get
+
+
+
+
+
+
+
+
+
+
+
+
+
get
+
+
+
+
+
+
+
+
+
+
+
+
+
+ collsion-free path
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ collision-free paths
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ collision-free
+
+ path is found
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Yes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lane path generation thread
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generate path candidates
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ onTimer()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Trigger: previous module output path is changed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
goal candidates
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
previous module path
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ freespace path generation thead
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Trigger: ego vehicle is stuck
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generate freespace paths
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ onTimer()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
freespace path
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if collision-fee path is found...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
No
+
+
+
+
+
+
+
+
+
+
diff --git a/planning/behavior_path_goal_planner_module/images/goal_priority_object_to_avoid_rviz.png b/planning/behavior_path_goal_planner_module/images/goal_priority_object_to_avoid_rviz.png
new file mode 100644
index 0000000000000..5067e0efc90a8
Binary files /dev/null and b/planning/behavior_path_goal_planner_module/images/goal_priority_object_to_avoid_rviz.png differ
diff --git a/planning/behavior_path_goal_planner_module/images/goal_priority_rviz.png b/planning/behavior_path_goal_planner_module/images/goal_priority_rviz.png
new file mode 100644
index 0000000000000..dbcd3e1055497
Binary files /dev/null and b/planning/behavior_path_goal_planner_module/images/goal_priority_rviz.png differ
diff --git a/planning/behavior_path_goal_planner_module/images/goal_priority_with_goal.png b/planning/behavior_path_goal_planner_module/images/goal_priority_with_goal.png
new file mode 100644
index 0000000000000..4094734cb8996
Binary files /dev/null and b/planning/behavior_path_goal_planner_module/images/goal_priority_with_goal.png differ
diff --git a/planning/behavior_path_goal_planner_module/include/behavior_path_goal_planner_module/goal_planner_module.hpp b/planning/behavior_path_goal_planner_module/include/behavior_path_goal_planner_module/goal_planner_module.hpp
index 71c309581f251..7350a7767fe01 100644
--- a/planning/behavior_path_goal_planner_module/include/behavior_path_goal_planner_module/goal_planner_module.hpp
+++ b/planning/behavior_path_goal_planner_module/include/behavior_path_goal_planner_module/goal_planner_module.hpp
@@ -356,7 +356,6 @@ class GoalPlannerModule : public SceneModuleInterface
// If terminating it, it may switch to lane following and could generate an inappropriate path.
bool canTransitSuccessState() override { return false; }
bool canTransitFailureState() override { return false; }
- bool canTransitIdleToRunningState() override { return true; }
mutable StartGoalPlannerData goal_planner_data_;
diff --git a/planning/behavior_path_goal_planner_module/src/goal_planner_module.cpp b/planning/behavior_path_goal_planner_module/src/goal_planner_module.cpp
index 3eb973dc9841e..c3404bf838a2c 100644
--- a/planning/behavior_path_goal_planner_module/src/goal_planner_module.cpp
+++ b/planning/behavior_path_goal_planner_module/src/goal_planner_module.cpp
@@ -1863,6 +1863,9 @@ void GoalPlannerModule::updateSafetyCheckTargetObjectsData(
std::pair GoalPlannerModule::isSafePath() const
{
+ if (!thread_safe_data_.get_pull_over_path()) {
+ return {false, false};
+ }
const auto pull_over_path = thread_safe_data_.get_pull_over_path()->getCurrentPath();
const auto & current_pose = planner_data_->self_odometry->pose.pose;
const double current_velocity = std::hypot(
diff --git a/planning/behavior_path_lane_change_module/include/behavior_path_lane_change_module/interface.hpp b/planning/behavior_path_lane_change_module/include/behavior_path_lane_change_module/interface.hpp
index 6a9a8c40c01d1..757ccd3a3116d 100644
--- a/planning/behavior_path_lane_change_module/include/behavior_path_lane_change_module/interface.hpp
+++ b/planning/behavior_path_lane_change_module/include/behavior_path_lane_change_module/interface.hpp
@@ -126,7 +126,7 @@ class LaneChangeInterface : public SceneModuleInterface
bool canTransitFailureState() override;
- bool canTransitIdleToRunningState() override;
+ ModuleStatus setInitState() const override { return ModuleStatus::WAITING_APPROVAL; };
void updateDebugMarker() const;
diff --git a/planning/behavior_path_lane_change_module/src/interface.cpp b/planning/behavior_path_lane_change_module/src/interface.cpp
index c8d53d8756cf3..e3763720c2d8a 100644
--- a/planning/behavior_path_lane_change_module/src/interface.cpp
+++ b/planning/behavior_path_lane_change_module/src/interface.cpp
@@ -297,29 +297,6 @@ bool LaneChangeInterface::canTransitFailureState()
return false;
}
-bool LaneChangeInterface::canTransitIdleToRunningState()
-{
- updateDebugMarker();
-
- auto log_debug_throttled = [&](std::string_view message) -> void {
- RCLCPP_DEBUG(getLogger(), "%s", message.data());
- };
-
- log_debug_throttled(__func__);
-
- if (!isActivated() || isWaitingApproval()) {
- if (module_type_->specialRequiredCheck()) {
- return true;
- }
- log_debug_throttled("Module is idling.");
- return false;
- }
-
- log_debug_throttled("Can lane change safely. Executing lane change.");
- module_type_->toNormalState();
- return true;
-}
-
void LaneChangeInterface::updateDebugMarker() const
{
if (!parameters_->publish_debug_marker) {
diff --git a/planning/behavior_path_planner_common/include/behavior_path_planner_common/interface/scene_module_interface.hpp b/planning/behavior_path_planner_common/include/behavior_path_planner_common/interface/scene_module_interface.hpp
index 1a8c8241abe1a..73f7448133ee7 100644
--- a/planning/behavior_path_planner_common/include/behavior_path_planner_common/interface/scene_module_interface.hpp
+++ b/planning/behavior_path_planner_common/include/behavior_path_planner_common/interface/scene_module_interface.hpp
@@ -373,13 +373,10 @@ class SceneModuleInterface
RCLCPP_DEBUG(getLogger(), "%s", message.data());
};
if (current_state_ == ModuleStatus::IDLE) {
- if (canTransitIdleToRunningState()) {
- log_debug_throttled("transiting from IDLE to RUNNING");
- return ModuleStatus::RUNNING;
- }
-
- log_debug_throttled("transiting from IDLE to IDLE");
- return ModuleStatus::IDLE;
+ auto init_state = setInitState();
+ RCLCPP_DEBUG(
+ getLogger(), "transiting from IDLE to %s", magic_enum::enum_name(init_state).data());
+ return init_state;
}
if (current_state_ == ModuleStatus::RUNNING) {
@@ -460,9 +457,9 @@ class SceneModuleInterface
virtual bool canTransitFailureState() = 0;
/**
- * @brief State transition condition IDLE -> RUNNING
+ * @brief Explicitly set the initial state
*/
- virtual bool canTransitIdleToRunningState() = 0;
+ virtual ModuleStatus setInitState() const { return ModuleStatus::RUNNING; }
/**
* @brief Get candidate path. This information is used for external judgement.
diff --git a/planning/behavior_path_side_shift_module/include/behavior_path_side_shift_module/scene.hpp b/planning/behavior_path_side_shift_module/include/behavior_path_side_shift_module/scene.hpp
index 7d72afebfb359..1748f57a61bec 100644
--- a/planning/behavior_path_side_shift_module/include/behavior_path_side_shift_module/scene.hpp
+++ b/planning/behavior_path_side_shift_module/include/behavior_path_side_shift_module/scene.hpp
@@ -75,8 +75,6 @@ class SideShiftModule : public SceneModuleInterface
bool canTransitFailureState() override { return false; }
- bool canTransitIdleToRunningState() override { return true; }
-
void initVariables();
// non-const methods
diff --git a/planning/behavior_path_start_planner_module/README.md b/planning/behavior_path_start_planner_module/README.md
index b26864eb450d5..5280f9c2ad020 100644
--- a/planning/behavior_path_start_planner_module/README.md
+++ b/planning/behavior_path_start_planner_module/README.md
@@ -2,24 +2,77 @@
## Purpose / Role
-The Start Planner module is designed to generate a path from the current ego position to the driving lane, avoiding static obstacles and stopping in response to dynamic obstacles when a collision is detected.
+This module generates and plans a path for safely merging from the shoulder lane or side of road lane into the center of the road lane.
-Use cases include:
+Specifically, it includes the following features:
-- pull out from the side of the road lane to centerline.
+- Plan the path to automatically start from the shoulder lane or side of road lane to center of road lane.
+- When parked vehicles are present on the shoulder lane, the module generates a path that allows for starting with a gap of a specified margin.
+- If a collision with other traffic participants is detected while traveling on the generated path, it will stop as much as possible.
-- pull out from the shoulder lane to the road lane centerline.
+## Use Cases
+
+Give an typical example of how path generation is executed. Showing example of path generation starts from shoulder lane, but also from side of road lane can be generated.
+
+
+
+### **Use Case 1: Shift pull out**
+
+In the shoulder lane, when there are no parked vehicles ahead and the shoulder lane is sufficiently long, a forward shift pull out path (a clothoid curve with consistent jerk) is generated.
+
+
+
+### **Use Case 2: Geometric pull out**
+
+In the shoulder lane, when there are objects in front and the lane is not sufficiently long behind, a geometric pull out path is generated.
+
+
+
+### **Use Case 3: Backward and shift pull out**
+
+In the shoulder lane, when there are parked vehicles ahead and the lane is sufficiently long behind, a path that involves reversing before generating a forward shift pull out path is created.
+
+
+
+### **Use Case 4: Backward and geometric pull out**
+
+In the shoulder lane, when there is an object ahead and not enough space to reverse sufficiently, a path that involves reversing before making an geometric pull out is generated.
+### **Use Case 5: Freespace pull out**
+
+If the map is annotated with the information that a free space path can be generated in situations where both shift and geometric pull out paths are impossible to create, a path based on the free space algorithm will be generated.
+
+
+
+**As a note, the patterns for generating these paths are based on default parameters, but as will be explained in the following sections, it is possible to control aspects such as making paths that involve reversing more likely to be generated, or making geometric paths more likely to be generated, by changing the path generation policy or adjusting the margin around static objects.**
+
+## Limitations
+
+Here are some notable limitations:
+
+- If parked vehicles exist in front of, behind, or on both sides of the shoulder, and it's not possible to maintain a specified distance from them, a stopping path will be generated, leading to a potential deadlock.
+- In the default settings of the behavior_path_planner, an avoidance module operates in a later stage and attempts to avoid objects. However, it is not guaranteed that the start_planner module will output a path that can successfully navigate around obstacles. This means that if an unavoidable path is generated, it could result in a deadlock.
+- The performance of safety check relies on the accuracy of the predicted paths generated by the map_based_prediction node. It's important to note that, currently, predicted paths that consider acceleration are not generated, and paths for low-speed objects may not be accurately produced, which requires caution.
+- Given the current specifications of the rule-based algorithms, there is a trade-off between the safety of a path and its naturalness to humans. While it's possible to adjust parameters to manage this trade-off, improvements are necessary to better reconcile these aspects.
+
## Design
```plantuml
diff --git a/planning/behavior_path_start_planner_module/config/start_planner.param.yaml b/planning/behavior_path_start_planner_module/config/start_planner.param.yaml
index 9e5a05a2d60cd..df89427e90fa6 100644
--- a/planning/behavior_path_start_planner_module/config/start_planner.param.yaml
+++ b/planning/behavior_path_start_planner_module/config/start_planner.param.yaml
@@ -12,6 +12,7 @@
center_line_path_interval: 1.0
# shift pull out
enable_shift_pull_out: true
+ check_shift_path_lane_departure: true
shift_collision_check_distance_from_end: -10.0
minimum_shift_pull_out_distance: 0.0
deceleration_interval: 15.0
diff --git a/planning/behavior_path_start_planner_module/images/freespace_pull_out.png b/planning/behavior_path_start_planner_module/images/freespace_pull_out.png
new file mode 100644
index 0000000000000..86b95379f9bc1
Binary files /dev/null and b/planning/behavior_path_start_planner_module/images/freespace_pull_out.png differ
diff --git a/planning/behavior_path_start_planner_module/images/geometric_pull_out_path.drawio.svg b/planning/behavior_path_start_planner_module/images/geometric_pull_out_path.drawio.svg
new file mode 100644
index 0000000000000..295b5f97c1cf0
--- /dev/null
+++ b/planning/behavior_path_start_planner_module/images/geometric_pull_out_path.drawio.svg
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/planning/behavior_path_start_planner_module/images/geometric_pull_out_path_with_back.drawio.svg b/planning/behavior_path_start_planner_module/images/geometric_pull_out_path_with_back.drawio.svg
new file mode 100644
index 0000000000000..37465f8b60cc7
--- /dev/null
+++ b/planning/behavior_path_start_planner_module/images/geometric_pull_out_path_with_back.drawio.svg
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/planning/behavior_path_start_planner_module/images/shift_pull_out_path.drawio.svg b/planning/behavior_path_start_planner_module/images/shift_pull_out_path.drawio.svg
new file mode 100644
index 0000000000000..a8f16716e6b07
--- /dev/null
+++ b/planning/behavior_path_start_planner_module/images/shift_pull_out_path.drawio.svg
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/planning/behavior_path_start_planner_module/images/shift_pull_out_path_from_road_lane.drawio.svg b/planning/behavior_path_start_planner_module/images/shift_pull_out_path_from_road_lane.drawio.svg
new file mode 100644
index 0000000000000..24fe0ccc5f672
--- /dev/null
+++ b/planning/behavior_path_start_planner_module/images/shift_pull_out_path_from_road_lane.drawio.svg
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/planning/behavior_path_start_planner_module/images/shift_pull_out_path_with_back.drawio.svg b/planning/behavior_path_start_planner_module/images/shift_pull_out_path_with_back.drawio.svg
new file mode 100644
index 0000000000000..cc7223786833a
--- /dev/null
+++ b/planning/behavior_path_start_planner_module/images/shift_pull_out_path_with_back.drawio.svg
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/planning/behavior_path_start_planner_module/images/start_from_road_shoulder.drawio.svg b/planning/behavior_path_start_planner_module/images/start_from_road_shoulder.drawio.svg
deleted file mode 100644
index 4a70534d42d2e..0000000000000
--- a/planning/behavior_path_start_planner_module/images/start_from_road_shoulder.drawio.svg
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/planning/behavior_path_start_planner_module/images/start_from_road_side.drawio.svg b/planning/behavior_path_start_planner_module/images/start_from_road_side.drawio.svg
deleted file mode 100644
index 46cdb07150c3a..0000000000000
--- a/planning/behavior_path_start_planner_module/images/start_from_road_side.drawio.svg
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/planning/behavior_path_start_planner_module/images/start_planner_example.png b/planning/behavior_path_start_planner_module/images/start_planner_example.png
new file mode 100644
index 0000000000000..598367c1a6e84
Binary files /dev/null and b/planning/behavior_path_start_planner_module/images/start_planner_example.png differ
diff --git a/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/data_structs.hpp b/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/data_structs.hpp
index f42aef4075777..ecd99393eae2b 100644
--- a/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/data_structs.hpp
+++ b/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/data_structs.hpp
@@ -46,6 +46,7 @@ struct StartPlannerDebugData
std::vector ego_predicted_path;
// collision check debug map
CollisionCheckDebugMap collision_check;
+ lanelet::ConstLanelets departure_check_lanes;
Pose refined_start_pose;
std::vector start_pose_candidates;
diff --git a/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/shift_pull_out.hpp b/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/shift_pull_out.hpp
index fef9a4aa8ebfc..6bf85a4679dfd 100644
--- a/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/shift_pull_out.hpp
+++ b/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/shift_pull_out.hpp
@@ -50,9 +50,9 @@ class ShiftPullOut : public PullOutPlannerBase
ShiftedPath & shifted_path, const Pose & start_pose, const Pose & end_pose,
const double longitudinal_acc, const double lateral_acc);
- void setDrivableLanes(const lanelet::ConstLanelets & drivable_lanes)
+ void setDepartureCheckLanes(const lanelet::ConstLanelets & departure_check_lanes)
{
- drivable_lanes_ = drivable_lanes;
+ departure_check_lanes_ = departure_check_lanes;
}
std::shared_ptr lane_departure_checker_;
@@ -64,7 +64,7 @@ class ShiftPullOut : public PullOutPlannerBase
const double lon_acc, const double shift_time, const double shift_length,
const double max_curvature, const double min_distance) const;
- lanelet::ConstLanelets drivable_lanes_;
+ lanelet::ConstLanelets departure_check_lanes_;
};
} // namespace behavior_path_planner
diff --git a/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/start_planner_module.hpp b/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/start_planner_module.hpp
index 90ce99692e57a..e6f5d78a6eb71 100644
--- a/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/start_planner_module.hpp
+++ b/planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/start_planner_module.hpp
@@ -139,8 +139,6 @@ class StartPlannerModule : public SceneModuleInterface
bool canTransitFailureState() override { return false; }
- bool canTransitIdleToRunningState() override { return true; }
-
/**
* @brief init member variables.
*/
@@ -244,8 +242,8 @@ class StartPlannerModule : public SceneModuleInterface
const std::vector & ego_predicted_path) const;
bool isSafePath() const;
void setDrivableAreaInfo(BehaviorModuleOutput & output) const;
- void updateDrivableLanes();
- lanelet::ConstLanelets createDrivableLanes() const;
+ void updateDepartureCheckLanes();
+ lanelet::ConstLanelets createDepartureCheckLanes() const;
// check if the goal is located behind the ego in the same route segment.
bool isGoalBehindOfEgoInSameRouteSegment() const;
diff --git a/planning/behavior_path_start_planner_module/src/shift_pull_out.cpp b/planning/behavior_path_start_planner_module/src/shift_pull_out.cpp
index 3b4d08b65923c..8eca8479fbd44 100644
--- a/planning/behavior_path_start_planner_module/src/shift_pull_out.cpp
+++ b/planning/behavior_path_start_planner_module/src/shift_pull_out.cpp
@@ -88,7 +88,7 @@ std::optional ShiftPullOut::plan(const Pose & start_pose, const Pos
const auto transformed_vehicle_footprint =
transformVector(vehicle_footprint_, tier4_autoware_utils::pose2transform(pose));
const bool is_out_of_lane =
- LaneDepartureChecker::isOutOfLane(drivable_lanes_, transformed_vehicle_footprint);
+ LaneDepartureChecker::isOutOfLane(departure_check_lanes_, transformed_vehicle_footprint);
if (i <= start_segment_idx) {
if (!is_out_of_lane) {
cropped_path.points.push_back(shift_path.points.at(i));
@@ -100,9 +100,16 @@ std::optional ShiftPullOut::plan(const Pose & start_pose, const Pos
shift_path.points = cropped_path.points;
// check lane departure
+ // The method for lane departure checking verifies if the footprint of each point on the path is
+ // contained within a lanelet using `boost::geometry::within`, which incurs a high computational
+ // cost.
+ // TODO(someone): improve the method for detecting lane departures without using
+ // lanelet::ConstLanelets, making it unnecessary to retain departure_check_lanes_ as a member
+ // variable.
if (
parameters_.check_shift_path_lane_departure &&
- lane_departure_checker_->checkPathWillLeaveLane(drivable_lanes_, path_shift_start_to_end)) {
+ lane_departure_checker_->checkPathWillLeaveLane(
+ departure_check_lanes_, path_shift_start_to_end)) {
continue;
}
diff --git a/planning/behavior_path_start_planner_module/src/start_planner_module.cpp b/planning/behavior_path_start_planner_module/src/start_planner_module.cpp
index f5f0e514ce8bc..9e42a02b95219 100644
--- a/planning/behavior_path_start_planner_module/src/start_planner_module.cpp
+++ b/planning/behavior_path_start_planner_module/src/start_planner_module.cpp
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include
#include
@@ -137,7 +138,7 @@ void StartPlannerModule::initVariables()
debug_marker_.markers.clear();
initializeSafetyCheckParameters();
initializeCollisionCheckDebugMap(debug_data_.collision_check);
- updateDrivableLanes();
+ updateDepartureCheckLanes();
}
void StartPlannerModule::updateEgoPredictedPathParams(
@@ -597,7 +598,7 @@ BehaviorModuleOutput StartPlannerModule::planWaitingApproval()
void StartPlannerModule::resetStatus()
{
status_ = PullOutStatus{};
- updateDrivableLanes();
+ updateDepartureCheckLanes();
}
void StartPlannerModule::incrementPathIndex()
@@ -1244,8 +1245,12 @@ bool StartPlannerModule::isSafePath() const
const double hysteresis_factor =
status_.is_safe_dynamic_objects ? 1.0 : safety_check_params_->hysteresis_factor_expand_rate;
- behavior_path_planner::updateSafetyCheckDebugData(
- debug_data_, filtered_objects, target_objects_on_lane, ego_predicted_path);
+ // debug
+ {
+ debug_data_.filtered_objects = filtered_objects;
+ debug_data_.target_objects_on_lane = target_objects_on_lane;
+ debug_data_.ego_predicted_path = ego_predicted_path;
+ }
return behavior_path_planner::utils::path_safety_checker::checkSafetyWithRSS(
pull_out_path, ego_predicted_path, target_objects_on_lane.on_current_lane,
@@ -1373,19 +1378,23 @@ void StartPlannerModule::setDrivableAreaInfo(BehaviorModuleOutput & output) cons
}
}
-void StartPlannerModule::updateDrivableLanes()
+void StartPlannerModule::updateDepartureCheckLanes()
{
- const auto drivable_lanes = createDrivableLanes();
+ const auto departure_check_lanes = createDepartureCheckLanes();
for (auto & planner : start_planners_) {
auto shift_pull_out = std::dynamic_pointer_cast(planner);
if (shift_pull_out) {
- shift_pull_out->setDrivableLanes(drivable_lanes);
+ shift_pull_out->setDepartureCheckLanes(departure_check_lanes);
}
}
+ // debug
+ {
+ debug_data_.departure_check_lanes = departure_check_lanes;
+ }
}
-lanelet::ConstLanelets StartPlannerModule::createDrivableLanes() const
+lanelet::ConstLanelets StartPlannerModule::createDepartureCheckLanes() const
{
const double backward_path_length =
planner_data_->parameters.backward_path_length + parameters_->max_back_distance;
@@ -1404,13 +1413,14 @@ lanelet::ConstLanelets StartPlannerModule::createDrivableLanes() const
[this](const auto & pull_out_lane) {
return planner_data_->route_handler->isShoulderLanelet(pull_out_lane);
});
- const auto drivable_lanes = utils::transformToLanelets(
+ const auto departure_check_lanes = utils::transformToLanelets(
utils::generateDrivableLanesWithShoulderLanes(road_lanes, shoulder_lanes));
- return drivable_lanes;
+ return departure_check_lanes;
}
void StartPlannerModule::setDebugData()
{
+ using lanelet::visualization::laneletsAsTriangleMarkerArray;
using marker_utils::addFootprintMarker;
using marker_utils::createFootprintMarkerArray;
using marker_utils::createObjectsMarkerArray;
@@ -1425,6 +1435,12 @@ void StartPlannerModule::setDebugData()
using tier4_autoware_utils::createMarkerScale;
using visualization_msgs::msg::Marker;
+ const auto red_color = createMarkerColor(1.0, 0.0, 0.0, 0.999);
+ const auto cyan_color = createMarkerColor(0.0, 1.0, 1.0, 0.2);
+ const auto pink_color = createMarkerColor(1.0, 0.5, 0.5, 0.35);
+ const auto purple_color = createMarkerColor(1.0, 0.0, 1.0, 0.99);
+ const auto white_color = createMarkerColor(1.0, 1.0, 1.0, 0.99);
+
const auto life_time = rclcpp::Duration::from_seconds(1.5);
auto add = [&](MarkerArray added) {
for (auto & marker : added.markers) {
@@ -1456,10 +1472,9 @@ void StartPlannerModule::setDebugData()
if (collision_check_end_pose) {
add(createPoseMarkerArray(
*collision_check_end_pose, "static_collision_check_end_pose", 0, 1.0, 0.0, 0.0));
- auto marker = tier4_autoware_utils::createDefaultMarker(
+ auto marker = createDefaultMarker(
"map", rclcpp::Clock{RCL_ROS_TIME}.now(), "static_collision_check_end_polygon", 0,
- Marker::LINE_LIST, tier4_autoware_utils::createMarkerScale(0.1, 0.1, 0.1),
- tier4_autoware_utils::createMarkerColor(1.0, 0.0, 0.0, 0.999));
+ Marker::LINE_LIST, createMarkerScale(0.1, 0.1, 0.1), red_color);
const auto footprint = transformVector(
local_footprint, tier4_autoware_utils::pose2transform(*collision_check_end_pose));
const double ego_z = planner_data_->self_odometry->pose.pose.position.z;
@@ -1479,13 +1494,13 @@ void StartPlannerModule::setDebugData()
{
MarkerArray start_pose_footprint_marker_array{};
MarkerArray start_pose_text_marker_array{};
- const auto purple = createMarkerColor(1.0, 0.0, 1.0, 0.99);
Marker footprint_marker = createDefaultMarker(
"map", rclcpp::Clock{RCL_ROS_TIME}.now(), "start_pose_candidates", 0, Marker::LINE_STRIP,
- createMarkerScale(0.2, 0.2, 0.2), purple);
+ createMarkerScale(0.2, 0.2, 0.2), purple_color);
Marker text_marker = createDefaultMarker(
"map", rclcpp::Clock{RCL_ROS_TIME}.now(), "start_pose_candidates_idx", 0,
- visualization_msgs::msg::Marker::TEXT_VIEW_FACING, createMarkerScale(0.3, 0.3, 0.3), purple);
+ visualization_msgs::msg::Marker::TEXT_VIEW_FACING, createMarkerScale(0.3, 0.3, 0.3),
+ purple_color);
footprint_marker.lifetime = rclcpp::Duration::from_seconds(1.5);
text_marker.lifetime = rclcpp::Duration::from_seconds(1.5);
for (size_t i = 0; i < debug_data_.start_pose_candidates.size(); ++i) {
@@ -1506,10 +1521,9 @@ void StartPlannerModule::setDebugData()
// visualize the footprint from pull_out_start pose to pull_out_end pose along the path
{
MarkerArray pull_out_path_footprint_marker_array{};
- const auto pink = createMarkerColor(1.0, 0.0, 1.0, 0.99);
Marker pull_out_path_footprint_marker = createDefaultMarker(
"map", rclcpp::Clock{RCL_ROS_TIME}.now(), "shift_path_footprint", 0, Marker::LINE_STRIP,
- createMarkerScale(0.2, 0.2, 0.2), pink);
+ createMarkerScale(0.2, 0.2, 0.2), pink_color);
pull_out_path_footprint_marker.lifetime = rclcpp::Duration::from_seconds(1.5);
PathWithLaneId path_shift_start_to_end{};
const auto shift_path = status_.pull_out_path.partial_paths.front();
@@ -1567,8 +1581,7 @@ void StartPlannerModule::setDebugData()
const auto header = planner_data_->route_handler->getRouteHeader();
{
visualization_msgs::msg::MarkerArray planner_type_marker_array{};
- const auto color = status_.found_pull_out_path ? createMarkerColor(1.0, 1.0, 1.0, 0.99)
- : createMarkerColor(1.0, 0.0, 0.0, 0.99);
+ const auto color = status_.found_pull_out_path ? white_color : red_color;
auto marker = createDefaultMarker(
header.frame_id, header.stamp, "planner_type", 0,
visualization_msgs::msg::Marker::TEXT_VIEW_FACING, createMarkerScale(0.0, 0.0, 1.0), color);
@@ -1583,6 +1596,15 @@ void StartPlannerModule::setDebugData()
planner_type_marker_array.markers.push_back(marker);
add(planner_type_marker_array);
}
+
+ add(laneletsAsTriangleMarkerArray(
+ "departure_check_lanes_for_shift_pull_out_path", debug_data_.departure_check_lanes,
+ cyan_color));
+
+ const auto pull_out_lanes = start_planner_utils::getPullOutLanes(
+ planner_data_, planner_data_->parameters.backward_path_length + parameters_->max_back_distance);
+ add(laneletsAsTriangleMarkerArray(
+ "pull_out_lanes_for_static_objects_collision_check", pull_out_lanes, pink_color));
}
void StartPlannerModule::logPullOutStatus(rclcpp::Logger::Level log_level) const
diff --git a/planning/behavior_velocity_intersection_module/src/scene_intersection.cpp b/planning/behavior_velocity_intersection_module/src/scene_intersection.cpp
index 3f6136673a44a..3cf243b7893fc 100644
--- a/planning/behavior_velocity_intersection_module/src/scene_intersection.cpp
+++ b/planning/behavior_velocity_intersection_module/src/scene_intersection.cpp
@@ -735,9 +735,7 @@ void reactRTCApprovalByDecisionResult(
path->points.at(stopline_idx).point.pose, VelocityFactor::UNKNOWN);
}
}
- if (
- !rtc_occlusion_approved && decision_result.occlusion_stopline_idx &&
- planner_param.occlusion.enable) {
+ if (!rtc_occlusion_approved && decision_result.occlusion_stopline_idx) {
const auto occlusion_stopline_idx = decision_result.occlusion_stopline_idx.value();
planning_utils::setVelocityFromIndex(occlusion_stopline_idx, 0.0, path);
debug_data->occlusion_stop_wall_pose =
@@ -814,7 +812,7 @@ void reactRTCApprovalByDecisionResult(
path->points.at(stopline_idx).point.pose, VelocityFactor::UNKNOWN);
}
}
- if (!rtc_occlusion_approved && planner_param.occlusion.enable) {
+ if (!rtc_occlusion_approved) {
const auto stopline_idx = decision_result.occlusion_stopline_idx;
planning_utils::setVelocityFromIndex(stopline_idx, 0.0, path);
debug_data->occlusion_stop_wall_pose =
@@ -857,7 +855,7 @@ void reactRTCApprovalByDecisionResult(
path->points.at(stopline_idx).point.pose, VelocityFactor::UNKNOWN);
}
}
- if (!rtc_occlusion_approved && planner_param.occlusion.enable) {
+ if (!rtc_occlusion_approved) {
if (planner_param.occlusion.creep_during_peeking.enable) {
const size_t occlusion_peeking_stopline = decision_result.occlusion_stopline_idx;
const size_t closest_idx = decision_result.closest_idx;
@@ -895,7 +893,7 @@ void reactRTCApprovalByDecisionResult(
"PeekingTowardOcclusion, approval = (default: %d, occlusion: %d)", rtc_default_approved,
rtc_occlusion_approved);
// NOTE: creep_velocity should be inserted first at closest_idx if !rtc_default_approved
- if (!rtc_occlusion_approved && planner_param.occlusion.enable) {
+ if (!rtc_occlusion_approved) {
const size_t occlusion_peeking_stopline =
decision_result.temporal_stop_before_attention_required
? decision_result.first_attention_stopline_idx
@@ -965,7 +963,7 @@ void reactRTCApprovalByDecisionResult(
path->points.at(stopline_idx).point.pose, VelocityFactor::UNKNOWN);
}
}
- if (!rtc_occlusion_approved && planner_param.occlusion.enable) {
+ if (!rtc_occlusion_approved) {
const auto stopline_idx = decision_result.temporal_stop_before_attention_required
? decision_result.first_attention_stopline_idx
: decision_result.occlusion_stopline_idx;
@@ -1066,7 +1064,7 @@ void reactRTCApprovalByDecisionResult(
path->points.at(stopline_idx).point.pose, VelocityFactor::UNKNOWN);
}
}
- if (!rtc_occlusion_approved && planner_param.occlusion.enable) {
+ if (!rtc_occlusion_approved) {
const auto stopline_idx = decision_result.occlusion_stopline_idx;
planning_utils::setVelocityFromIndex(stopline_idx, 0.0, path);
debug_data->occlusion_stop_wall_pose =
@@ -1110,7 +1108,7 @@ void reactRTCApprovalByDecisionResult(
path->points.at(stopline_idx).point.pose, VelocityFactor::UNKNOWN);
}
}
- if (!rtc_occlusion_approved && planner_param.occlusion.enable) {
+ if (!rtc_occlusion_approved) {
const auto stopline_idx = decision_result.occlusion_stopline_idx;
planning_utils::setVelocityFromIndex(stopline_idx, 0.0, path);
debug_data->occlusion_stop_wall_pose =
diff --git a/sensing/pointcloud_preprocessor/README.md b/sensing/pointcloud_preprocessor/README.md
index 91ef34f4cae72..5c6402efdf23d 100644
--- a/sensing/pointcloud_preprocessor/README.md
+++ b/sensing/pointcloud_preprocessor/README.md
@@ -56,7 +56,45 @@ Detail description of each filter's algorithm is in the following links.
## Assumptions / Known limits
-`pointcloud_preprocessor::Filter` is implemented based on pcl_perception [1] because of [this issue](https://github.com/ros-perception/perception_pcl/issues/9).
+`pointcloud_preprocessor::Filter` is implemented based on pcl_perception [1] because
+of [this issue](https://github.com/ros-perception/perception_pcl/issues/9).
+
+## Measuring the performance
+
+In Autoware, point cloud data from each LiDAR sensor undergoes preprocessing in the sensing pipeline before being input
+into the perception pipeline. The preprocessing stages are illustrated in the diagram below:
+
+![pointcloud_preprocess_pipeline.drawio.png](docs%2Fimage%2Fpointcloud_preprocess_pipeline.drawio.png)
+
+Each stage in the pipeline incurs a processing delay. Mostly, we've used `ros2 topic delay /topic_name` to measure
+the time between the message header and the current time. This approach works well for small-sized messages. However,
+when dealing with large point cloud messages, this method introduces an additional delay. This is primarily because
+accessing these large point cloud messages externally impacts the pipeline's performance.
+
+Our sensing/perception nodes are designed to run within composable node containers, leveraging intra-process
+communication. External subscriptions to these messages (like using ros2 topic delay or rviz2) impose extra delays and
+can even slow down the pipeline by subscribing externally. Therefore, these measurements will not be accurate.
+
+To mitigate this issue, we've adopted a method where each node in the pipeline reports its pipeline latency time.
+This approach ensures the integrity of intra-process communication and provides a more accurate measure of delays in the
+pipeline.
+
+### Benchmarking The Pipeline
+
+The nodes within the pipeline report the pipeline latency time, indicating the duration from the sensor driver's pointcloud
+output to the node's output. This data is crucial for assessing the pipeline's health and efficiency.
+
+When running Autoware, you can monitor the pipeline latency times for each node in the pipeline by subscribing to the
+following ROS 2 topics:
+
+- `/sensing/lidar/LidarX/crop_box_filter_self/debug/pipeline_latency_ms`
+- `/sensing/lidar/LidarX/crop_box_filter_mirror/debug/pipeline_latency_ms`
+- `/sensing/lidar/LidarX/distortion_corrector/debug/pipeline_latency_ms`
+- `/sensing/lidar/LidarX/ring_outlier_filter/debug/pipeline_latency_ms`
+- `/sensing/lidar/concatenate_data_synchronizer/debug/sensing/lidar/LidarX/pointcloud/pipeline_latency_ms`
+
+These topics provide the pipeline latency times, giving insights into the delays at various stages of the pipeline
+from the sensor output of LidarX to each subsequent node.
## (Optional) Error detection and handling
diff --git a/sensing/pointcloud_preprocessor/docs/image/pointcloud_preprocess_pipeline.drawio.png b/sensing/pointcloud_preprocessor/docs/image/pointcloud_preprocess_pipeline.drawio.png
new file mode 100644
index 0000000000000..e690d0179afa6
Binary files /dev/null and b/sensing/pointcloud_preprocessor/docs/image/pointcloud_preprocess_pipeline.drawio.png differ
diff --git a/sensing/pointcloud_preprocessor/src/concatenate_data/concatenate_and_time_sync_nodelet.cpp b/sensing/pointcloud_preprocessor/src/concatenate_data/concatenate_and_time_sync_nodelet.cpp
index ff72e433e9602..635e0d1103f89 100644
--- a/sensing/pointcloud_preprocessor/src/concatenate_data/concatenate_and_time_sync_nodelet.cpp
+++ b/sensing/pointcloud_preprocessor/src/concatenate_data/concatenate_and_time_sync_nodelet.cpp
@@ -380,6 +380,20 @@ void PointCloudConcatenateDataSynchronizerComponent::publish()
const auto & transformed_raw_points =
PointCloudConcatenateDataSynchronizerComponent::combineClouds(concat_cloud_ptr);
+ for (const auto & e : cloud_stdmap_) {
+ if (e.second != nullptr) {
+ if (debug_publisher_) {
+ const auto pipeline_latency_ms =
+ std::chrono::duration(
+ std::chrono::nanoseconds(
+ (this->get_clock()->now() - e.second->header.stamp).nanoseconds()))
+ .count();
+ debug_publisher_->publish(
+ "debug" + e.first + "/pipeline_latency_ms", pipeline_latency_ms);
+ }
+ }
+ }
+
// publish concatenated pointcloud
if (concat_cloud_ptr) {
auto output = std::make_unique(*concat_cloud_ptr);
diff --git a/sensing/pointcloud_preprocessor/src/crop_box_filter/crop_box_filter_nodelet.cpp b/sensing/pointcloud_preprocessor/src/crop_box_filter/crop_box_filter_nodelet.cpp
index 20d1f5c8b3d6d..cfbeffee9982c 100644
--- a/sensing/pointcloud_preprocessor/src/crop_box_filter/crop_box_filter_nodelet.cpp
+++ b/sensing/pointcloud_preprocessor/src/crop_box_filter/crop_box_filter_nodelet.cpp
@@ -65,7 +65,7 @@ CropBoxFilterComponent::CropBoxFilterComponent(const rclcpp::NodeOptions & optio
using tier4_autoware_utils::DebugPublisher;
using tier4_autoware_utils::StopWatch;
stop_watch_ptr_ = std::make_unique>();
- debug_publisher_ = std::make_unique(this, "crop_box_filter");
+ debug_publisher_ = std::make_unique(this, this->get_name());
stop_watch_ptr_->tic("cyclic_time");
stop_watch_ptr_->tic("processing_time");
}
@@ -195,6 +195,14 @@ void CropBoxFilterComponent::faster_filter(
"debug/cyclic_time_ms", cyclic_time_ms);
debug_publisher_->publish(
"debug/processing_time_ms", processing_time_ms);
+
+ auto pipeline_latency_ms =
+ std::chrono::duration(
+ std::chrono::nanoseconds((this->get_clock()->now() - input->header.stamp).nanoseconds()))
+ .count();
+
+ debug_publisher_->publish(
+ "debug/pipeline_latency_ms", pipeline_latency_ms);
}
}
diff --git a/sensing/pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp b/sensing/pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp
index dd38b85a2b56d..d1d91ed7ec439 100644
--- a/sensing/pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp
+++ b/sensing/pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp
@@ -128,6 +128,16 @@ void DistortionCorrectorComponent::onPointCloud(PointCloud2::UniquePtr points_ms
undistortPointCloud(tf2_base_link_to_sensor, *points_msg);
+ if (debug_publisher_) {
+ auto pipeline_latency_ms =
+ std::chrono::duration(
+ std::chrono::nanoseconds(
+ (this->get_clock()->now() - points_msg->header.stamp).nanoseconds()))
+ .count();
+ debug_publisher_->publish(
+ "debug/pipeline_latency_ms", pipeline_latency_ms);
+ }
+
undistorted_points_pub_->publish(std::move(points_msg));
// add processing time for debug
diff --git a/sensing/pointcloud_preprocessor/src/outlier_filter/ring_outlier_filter_nodelet.cpp b/sensing/pointcloud_preprocessor/src/outlier_filter/ring_outlier_filter_nodelet.cpp
index d2570b9c4d786..d968b06a0dc61 100644
--- a/sensing/pointcloud_preprocessor/src/outlier_filter/ring_outlier_filter_nodelet.cpp
+++ b/sensing/pointcloud_preprocessor/src/outlier_filter/ring_outlier_filter_nodelet.cpp
@@ -204,6 +204,14 @@ void RingOutlierFilterComponent::faster_filter(
"debug/cyclic_time_ms", cyclic_time_ms);
debug_publisher_->publish(
"debug/processing_time_ms", processing_time_ms);
+
+ auto pipeline_latency_ms =
+ std::chrono::duration(
+ std::chrono::nanoseconds((this->get_clock()->now() - input->header.stamp).nanoseconds()))
+ .count();
+
+ debug_publisher_->publish(
+ "debug/pipeline_latency_ms", pipeline_latency_ms);
}
}