Repository navigation
feat: add safety gate for generator-selector framework - #11404
Conversation
Signed-off-by: Go Sakayori <gsakayori@gmail.com>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
|
Thank you for contributing to the Autoware project! 🚧 If your pull request is in progress, switch it to draft mode. Please ensure:
|
There was a problem hiding this comment.
Pull Request Overview
This PR implements the trajectory safety filter component for the generator-selector framework, providing validation of candidate trajectories before they reach the vehicle control module. The safety filter checks trajectories for out-of-lane conditions and collision risks with predicted objects.
- Adds new trajectory safety filter package with plugin-based architecture
- Implements OutOfLaneFilter and CollisionFilter plugins for trajectory validation
- Integrates with existing planning pipeline through launch configuration updates
Reviewed Changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| trajectory_safety_filter_node.cpp | Main node implementation with plugin loading and trajectory filtering logic |
| out_of_lane_filter.cpp | Plugin that validates trajectories stay within lane boundaries |
| collision_filter.cpp | Plugin that checks time-to-collision with predicted objects |
| plugins.xml | Plugin registration configuration |
| parameter_struct.yaml | Parameter definitions for filter configuration |
| package.xml | Package dependencies and metadata |
| launch/trajectory_safety_filter.launch.xml | Launch file for the safety filter node |
| Header files | Interface definitions and class declarations |
| config/trajectory_safety_filter.param.yaml | Default parameter values |
| README.md | Documentation for the trajectory safety filter |
| CMakeLists.txt | Build configuration |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #11404 +/- ##
==========================================
- Coverage 20.29% 20.18% -0.12%
==========================================
Files 1588 1593 +5
Lines 114260 114596 +336
Branches 39005 38129 -876
==========================================
- Hits 23190 23132 -58
- Misses 73084 73519 +435
+ Partials 17986 17945 -41
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
danielsanchezaran
left a comment
There was a problem hiding this comment.
Thank you for this PR, I believe the general code is solid, however, I worry about the performance when we have big maps and many trajectories and many objects. I would like to get some measurements of time using the time_keeper feature. Likewise, I believe it might be better to pre-compute object trajectories so this task does not need to be repeated ( since TTC is currently calculated using Points, I think the performance cost is not high, but it will increase when we decide to refine the method).
| # if(BUILD_TESTING) | ||
| # ament_add_ros_isolated_gmock(test_${PROJECT_NAME} | ||
| # test/test_util.cpp | ||
| # ) | ||
|
|
||
| # target_link_libraries(test_${PROJECT_NAME} | ||
| # ${PROJECT_NAME} | ||
| # ) | ||
|
|
||
| # ament_target_dependencies(test_${PROJECT_NAME} | ||
| # autoware_test_utils | ||
| # ) | ||
| # endif() | ||
|
|
There was a problem hiding this comment.
Maybe it is better to delete this is there are no tests atm?
| This node performs a feasibility check on each candidate trajectory before it enters the final ranking stage. It drops paths that are physically impossible for the ego vehicle or that create an obvious driving risk. | ||
|
|
There was a problem hiding this comment.
I feel this description is a little bit off, the trajectories are feasible, but dangerous no?
| for (const auto & object : objects.objects) { | ||
| const double ttc = time_to_collision(traj_point, duration, object); | ||
|
|
||
| // Check if TTC is below minimum threshold | ||
| if (ttc < params_.min_ttc && ttc >= 0) { | ||
| return true; // Potential collision detected | ||
| } | ||
| } | ||
| return false; // No collision | ||
| } |
There was a problem hiding this comment.
| for (const auto & object : objects.objects) { | |
| const double ttc = time_to_collision(traj_point, duration, object); | |
| // Check if TTC is below minimum threshold | |
| if (ttc < params_.min_ttc && ttc >= 0) { | |
| return true; // Potential collision detected | |
| } | |
| } | |
| return false; // No collision | |
| } | |
| return std::any_of(objects.begin(),objects.end(),[&](const auto& object){ | |
| const double ttc = time_to_collision(traj_point, duration, object); | |
| return (ttc < params_.min_ttc && ttc >= 0); | |
| } | |
There was a problem hiding this comment.
Fixed in 9d897b1, but eventually removed
| float time_to_collision( | ||
| const TrajectoryPoint & ego_point, const rclcpp::Duration & duration, | ||
| const autoware_perception_msgs::msg::PredictedObject & object, const float max_ttc_value = 100.0f) | ||
| { | ||
| // Find the path with highest confidence | ||
| const auto max_confidence_path = std::max_element( | ||
| object.kinematics.predicted_paths.begin(), object.kinematics.predicted_paths.end(), | ||
| [](const auto & a, const auto & b) { return a.confidence < b.confidence; }); | ||
| if (max_confidence_path == object.kinematics.predicted_paths.end()) return max_ttc_value; | ||
|
|
||
| const auto & object_path = max_confidence_path->path; | ||
| if (object_path.size() < 2) { | ||
| if (duration.seconds() == 0.0f) { | ||
| TrajectoryPoint object_point; | ||
| object_point.pose = object.kinematics.initial_pose_with_covariance.pose; | ||
| object_point.longitudinal_velocity_mps = | ||
| object.kinematics.initial_twist_with_covariance.twist.linear.x; | ||
| object_point.lateral_velocity_mps = | ||
| object.kinematics.initial_twist_with_covariance.twist.linear.y; | ||
| float ttc = time_to_collision(ego_point, object_point); | ||
| return std::min(ttc, max_ttc_value); | ||
| } | ||
| return max_ttc_value; | ||
| } |
There was a problem hiding this comment.
For every trajectory point, we are checking the position of each object at a set interval of "time_from_start" based on the highest confidence trajectory. If there is only one input trajectory, this approach is ok, however, if you have several trajectories to evaluate, we are rapidly increasing the computations required to get the object's position. Since the object position and trajectory are independent, I suggest calculating all the future positions of every object (up to the ttc horizon time with 3 seconds as default) ONCE, and store them in memory, then you can query the position of every object at a given time.
| const float distance = displacement.length(); | ||
| if (distance < eps) return 0.0f; | ||
|
|
||
| const auto dir = displacement.normalized(); | ||
|
|
||
| const auto v1 = get_velocity_in_world_coordinate(point1); | ||
| const auto v2 = get_velocity_in_world_coordinate(point2); | ||
|
|
||
| const float relative_velocity = tf2::tf2Dot(dir, v1) - tf2::tf2Dot(dir, v2); | ||
|
|
||
| if (std::abs(relative_velocity) < eps) return std::numeric_limits<float>::infinity(); | ||
| return distance / relative_velocity; | ||
| } | ||
|
|
There was a problem hiding this comment.
Very nice. Please add somewhere in the description that the TTC is currently calculated using infinitesimal points and its not a full 2D collision check for the sake of simplicity.
| for (const auto & point : traj_points) { | ||
| if (rclcpp::Duration(point.time_from_start).seconds() > params_.max_check_time) { | ||
| break; | ||
| } | ||
| const auto nearest_lanelets = lanelet::geometry::findWithin2d( | ||
| context.lanelet_map->laneletLayer, | ||
| lanelet::BasicPoint2d(point.pose.position.x, point.pose.position.y), 0.0); | ||
| if (nearest_lanelets.empty()) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; |
There was a problem hiding this comment.
I worry about the processing time when we have a big map and several trajectories. I suggest creating a set of polygons for each trajectory and checking if they are leaving the lane using the boundary departure checker
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
|
@danielsanchezaran Thank you for the comment. I will leave the computational time as a future work, and would improve it once we start using the new planning framework. I have added a section in README about the future work. e8501e1 |
| const TrajectoryPoints & traj_points, const FilterContext & context) | ||
| { | ||
| // Check required context data | ||
| if (!context.lanelet_map || !context.odometry || traj_points.empty()) { |
There was a problem hiding this comment.
why not add the !boundary_departure_checker_ check from below to this line?
Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
danielsanchezaran
left a comment
There was a problem hiding this comment.
Built and also tested on Psim, seems to work fine. Unit tests should be added in the future. LGTM
…ation#11404) * copy packages from new planning framework Signed-off-by: Go Sakayori <gsakayori@gmail.com> * introduce plugin Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add/remove plugins Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix readme Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix include guard Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * remove test section in CMakeList Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * change definition in README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add comment for ttc calculation Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use lambda function for check_collison function Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * calculate obstacle position only once Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use boundary departure checker Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add future work section to README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * small fix for if condition Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> --------- Signed-off-by: Go Sakayori <gsakayori@gmail.com> Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> Signed-off-by: emuemuJP <k.matsumoto.0807@gmail.com>
…ation#11404) * copy packages from new planning framework Signed-off-by: Go Sakayori <gsakayori@gmail.com> * introduce plugin Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add/remove plugins Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix readme Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix include guard Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * remove test section in CMakeList Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * change definition in README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add comment for ttc calculation Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use lambda function for check_collison function Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * calculate obstacle position only once Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use boundary departure checker Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add future work section to README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * small fix for if condition Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> --------- Signed-off-by: Go Sakayori <gsakayori@gmail.com> Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
…ation#11404) * copy packages from new planning framework Signed-off-by: Go Sakayori <gsakayori@gmail.com> * introduce plugin Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add/remove plugins Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix readme Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix include guard Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * remove test section in CMakeList Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * change definition in README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add comment for ttc calculation Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use lambda function for check_collison function Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * calculate obstacle position only once Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use boundary departure checker Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add future work section to README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * small fix for if condition Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> --------- Signed-off-by: Go Sakayori <gsakayori@gmail.com> Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
…ation#11404) * copy packages from new planning framework Signed-off-by: Go Sakayori <gsakayori@gmail.com> * introduce plugin Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add/remove plugins Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix readme Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix include guard Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * remove test section in CMakeList Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * change definition in README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add comment for ttc calculation Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use lambda function for check_collison function Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * calculate obstacle position only once Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use boundary departure checker Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add future work section to README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * small fix for if condition Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> --------- Signed-off-by: Go Sakayori <gsakayori@gmail.com> Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
…ation#11404) * copy packages from new planning framework Signed-off-by: Go Sakayori <gsakayori@gmail.com> * introduce plugin Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add/remove plugins Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix readme Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix include guard Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * remove test section in CMakeList Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * change definition in README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add comment for ttc calculation Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use lambda function for check_collison function Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * calculate obstacle position only once Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use boundary departure checker Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add future work section to README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * small fix for if condition Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> --------- Signed-off-by: Go Sakayori <gsakayori@gmail.com> Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
…ation#11404) * copy packages from new planning framework Signed-off-by: Go Sakayori <gsakayori@gmail.com> * introduce plugin Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add/remove plugins Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix readme Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix include guard Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * remove test section in CMakeList Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * change definition in README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add comment for ttc calculation Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use lambda function for check_collison function Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * calculate obstacle position only once Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use boundary departure checker Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add future work section to README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * small fix for if condition Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> --------- Signed-off-by: Go Sakayori <gsakayori@gmail.com> Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
…ation/autoware_universe#11404) * copy packages from new planning framework Signed-off-by: Go Sakayori <gsakayori@gmail.com> * introduce plugin Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add/remove plugins Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix readme Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix include guard Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * fix precommit Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * remove test section in CMakeList Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * change definition in README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add comment for ttc calculation Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use lambda function for check_collison function Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * calculate obstacle position only once Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * use boundary departure checker Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * add future work section to README Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> * small fix for if condition Signed-off-by: Go Sakayori <go.sakayori@tier4.jp> --------- Signed-off-by: Go Sakayori <gsakayori@gmail.com> Signed-off-by: Go Sakayori <go.sakayori@tier4.jp>
Description
This PR completes the implementation of
autoware_trajectory_safety_filterfor the generator-selector framework. It validates candidate trajectories from the trajectory optimizer before they are sent to the vehicle control module. The filter checks for potential safety violations such as out-of-lane conditions and collision risks withpredicted objects, ensuring that only safe trajectories are executed by the autonomous vehicle.
Related links
Parent Issue:
This PR corresponds to Phase 4.
How was this PR tested?
Notes for reviewers
In this update, the nodes in this package will not be launched.
Interface changes
None.
Effects on system behavior
None.