Carma-platform v4.11.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
yield_plugin.hpp
Go to the documentation of this file.
1#pragma once
2
3/*
4 * Copyright (C) 2022-2026 LEIDOS.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7 * use this file except in compliance with the License. You may obtain a copy of
8 * the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 * License for the specific language governing permissions and limitations under
16 * the License.
17 */
18
19#include <vector>
20#include <carma_planning_msgs/msg/trajectory_plan.hpp>
21#include <carma_planning_msgs/msg/trajectory_plan_point.hpp>
22#include <carma_planning_msgs/msg/plugin.hpp>
23#include <carma_v2x_msgs/msg/mobility_request.hpp>
24#include <carma_v2x_msgs/msg/mobility_response.hpp>
25#include <carma_v2x_msgs/msg/bsm.hpp>
26#include <carma_planning_msgs/msg/lane_change_status.hpp>
27#include <boost/shared_ptr.hpp>
28#include <carma_ros2_utils/carma_lifecycle_node.hpp>
29#include <boost/geometry.hpp>
31#include <functional>
32#include "yield_config.hpp"
33#include <unordered_set>
34#include <carma_planning_msgs/srv/plan_trajectory.hpp>
35#include <std_msgs/msg/string.hpp>
36#include <geometry_msgs/msg/pose_stamped.hpp>
37#include <trajectory_utils/quintic_coefficient_calculator.hpp>
38#include <boost/property_tree/json_parser.hpp>
39#include <lanelet2_extension/projection/local_frame_projector.h>
40#include <carma_v2x_msgs/msg/location_ecef.hpp>
41#include <carma_v2x_msgs/msg/trajectory.hpp>
42#include <carma_v2x_msgs/msg/plan_type.hpp>
43#include <carma_wm/Geometry.hpp>
47
48
49namespace yield_plugin
50{
51using MobilityResponseCB = std::function<void(const carma_v2x_msgs::msg::MobilityResponse&)>;
52using LaneChangeStatusCB = std::function<void(const carma_planning_msgs::msg::LaneChangeStatus&)>;
53
58{
59 lanelet::BasicPoint2d point;
60 double speed = 0;
61};
62
67{
68 rclcpp::Time collision_time;
69 lanelet::BasicPoint2d ego_point;
70 lanelet::BasicPoint2d object_point;
71};
72
78{
79public:
88 YieldPlugin(std::shared_ptr<carma_ros2_utils::CarmaLifecycleNode> nh, carma_wm::WorldModelConstPtr wm, YieldPluginConfig config,
89 MobilityResponseCB mobility_response_publisher,
90 LaneChangeStatusCB lc_status_publisher);
91
100 carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req,
101 carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp);
102
110 carma_planning_msgs::msg::TrajectoryPlan update_traj_for_object(const carma_planning_msgs::msg::TrajectoryPlan& original_tp, const std::vector<carma_perception_msgs::msg::ExternalObject>& external_objects, double initial_velocity);
111
118 double polynomial_calc(std::vector<double> coeff, double x) const;
119
126 double polynomial_calc_d(std::vector<double> coeff, double x) const;
127
134 double max_trajectory_speed(const std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint>& trajectory_points, double timestamp_in_sec_to_search_until) const;
135
141 std::vector<double> get_relative_downtracks(const carma_planning_msgs::msg::TrajectoryPlan& trajectory_plan) const;
142
147 void mobilityrequest_cb(const carma_v2x_msgs::msg::MobilityRequest::UniquePtr msg);
148
153 void bsm_cb(const carma_v2x_msgs::msg::BSM::UniquePtr msg);
154
161 std::vector<lanelet::BasicPoint2d> convert_eceftrajectory_to_mappoints(const carma_v2x_msgs::msg::Trajectory& ecef_trajectory) const;
162
169 lanelet::BasicPoint2d ecef_to_map_point(const carma_v2x_msgs::msg::LocationECEF& ecef_point) const;
170
178 carma_v2x_msgs::msg::MobilityResponse compose_mobility_response(const std::string& resp_recipient_id, const std::string& req_plan_id, bool response) const;
179
193 carma_planning_msgs::msg::TrajectoryPlan generate_JMT_trajectory(const carma_planning_msgs::msg::TrajectoryPlan& original_tp, double initial_pos, double goal_pos,
194 double initial_velocity, double goal_velocity, double planning_time, double original_max_speed);
195
202 carma_planning_msgs::msg::TrajectoryPlan update_traj_for_cooperative_behavior(const carma_planning_msgs::msg::TrajectoryPlan& original_tp, double current_speed);
203
210 std::vector<std::pair<int, lanelet::BasicPoint2d>> detect_trajectories_intersection(std::vector<lanelet::BasicPoint2d> self_trajectory, std::vector<lanelet::BasicPoint2d> incoming_trajectory) const;
211
212
220 void set_incoming_request_info(std::vector <lanelet::BasicPoint2d> req_trajectory, double req_speed, double req_planning_time, double req_timestamp);
221
226
232 double check_traj_for_digital_min_gap(const carma_planning_msgs::msg::TrajectoryPlan& original_tp) const;
233
238 void set_georeference_string(const std::string& georeference);
239
244 void set_external_objects(const std::vector<carma_perception_msgs::msg::ExternalObject>& object_list);
245
251
262 std::optional<GetCollisionResult> get_collision(const carma_planning_msgs::msg::TrajectoryPlan& ego_trajectory, const std::vector<carma_perception_msgs::msg::PredictedState>& object_predictions, double collision_radius, double ego_max_speed);
263
272 std::optional<rclcpp::Time> get_collision_time(const carma_planning_msgs::msg::TrajectoryPlan& original_tp, const carma_perception_msgs::msg::ExternalObject& curr_obstacle, double original_tp_max_speed);
273
284 bool is_object_behind_vehicle(uint32_t object_id, const rclcpp::Time& collision_time, double vehicle_point, double object_downtrack);
285
293 std::optional<std::pair<carma_perception_msgs::msg::ExternalObject, double>> get_earliest_collision_object_and_time(const carma_planning_msgs::msg::TrajectoryPlan& original_tp, const std::vector<carma_perception_msgs::msg::ExternalObject>& external_objects);
294
302 std::unordered_map<uint32_t, rclcpp::Time> get_collision_times_concurrently(const carma_planning_msgs::msg::TrajectoryPlan& original_tp, const std::vector<carma_perception_msgs::msg::ExternalObject>& external_objects, double original_tp_max_speed);
303
304private:
313 std::unordered_map<uint32_t, rclcpp::Time> get_collision_times_concurrently_cpu(
314 const carma_planning_msgs::msg::TrajectoryPlan& original_tp,
315 const std::vector<carma_perception_msgs::msg::ExternalObject>& external_objects,
316 double original_tp_max_speed);
317
327 std::unordered_map<uint32_t, rclcpp::Time> get_collision_times_concurrently_cuda(
328 const carma_planning_msgs::msg::TrajectoryPlan& original_tp,
329 const std::vector<carma_perception_msgs::msg::ExternalObject>& external_objects,
330 double original_tp_max_speed);
331
339 std::pair<bool, int> find_on_route_in_predictions(
340 const std::vector<carma_perception_msgs::msg::PredictedState>& predictions,
341 int stride, bool zero_speed) const;
342
343public:
352 double get_predicted_velocity_at_time(const geometry_msgs::msg::Twist& object_velocity_in_map_frame, const carma_planning_msgs::msg::TrajectoryPlan& original_tp, double timestamp_in_sec_to_predict);
353
354
355private:
356
361 std::shared_ptr<carma_ros2_utils::CarmaLifecycleNode> nh_;
362 std::set<lanelet::Id> route_llt_ids_;
363 // Store lanelet polygons for precise geometric containment checking instead of just bounding boxes
364 std::vector<lanelet::ConstLanelet> route_llt_polygons_;
365 lanelet::Id previous_llt_id_;
366 std::vector<carma_perception_msgs::msg::ExternalObject> external_objects_;
367 std::unordered_map<uint32_t, int> consecutive_clearance_count_for_obstacles_;
368 // flag to show if it is possible for the vehicle to accept the cooperative request
370
371 // incoming request trajectory information:
372 std::vector <lanelet::BasicPoint2d> req_trajectory_points_;
374 double req_timestamp_ = 0;
378 std::optional<double> last_speed_ = std::nullopt;
379 std::optional<rclcpp::Time> last_speed_time_ = std::nullopt;
380 std::optional<rclcpp::Time> first_time_stopped_to_prevent_collision_ = std::nullopt;
381 std::optional<
382 carma_planning_msgs::msg::TrajectoryPlan> last_traj_plan_committed_to_stopping_ = std::nullopt;
383 // time between ecef trajectory points
385
386 geometry_msgs::msg::Vector3 host_vehicle_size;
388 // BSM Message
389 std::string host_bsm_id_;
390
391 std::string georeference_{""};
392 std::shared_ptr<lanelet::projection::LocalFrameProjector> map_projector_;
393
394 std::string bsmIDtoString(carma_v2x_msgs::msg::BSMCoreData bsm_core)
395 {
396 std::string res = "";
397 for (size_t i=0; i<bsm_core.id.size(); i++)
398 {
399 res+=std::to_string(bsm_core.id[i]);
400 }
401 return res;
402 }
403
404};
405} // namespace yield_plugin
Class containing primary business logic for the In-Lane Cruising Plugin.
std::set< lanelet::Id > route_llt_ids_
void plan_trajectory_callback(carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req, carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp)
Service callback for trajectory planning.
std::vector< double > get_relative_downtracks(const carma_planning_msgs::msg::TrajectoryPlan &trajectory_plan) const
calculates distance between trajectory points in a plan
geometry_msgs::msg::Vector3 host_vehicle_size
LaneChangeStatusCB lc_status_publisher_
void set_incoming_request_info(std::vector< lanelet::BasicPoint2d > req_trajectory, double req_speed, double req_planning_time, double req_timestamp)
set values for member variables related to cooperative behavior
std::vector< lanelet::BasicPoint2d > req_trajectory_points_
void mobilityrequest_cb(const carma_v2x_msgs::msg::MobilityRequest::UniquePtr msg)
callback for mobility request
double check_traj_for_digital_min_gap(const carma_planning_msgs::msg::TrajectoryPlan &original_tp) const
checks trajectory for minimum gap associated with it from the road
double get_predicted_velocity_at_time(const geometry_msgs::msg::Twist &object_velocity_in_map_frame, const carma_planning_msgs::msg::TrajectoryPlan &original_tp, double timestamp_in_sec_to_predict)
Given the object velocity in map frame with x,y components, this function returns the projected veloc...
std::shared_ptr< lanelet::projection::LocalFrameProjector > map_projector_
std::vector< lanelet::BasicPoint2d > convert_eceftrajectory_to_mappoints(const carma_v2x_msgs::msg::Trajectory &ecef_trajectory) const
convert a carma trajectory from ecef frame to map frame ecef trajectory consists of the point and a s...
std::optional< std::pair< carma_perception_msgs::msg::ExternalObject, double > > get_earliest_collision_object_and_time(const carma_planning_msgs::msg::TrajectoryPlan &original_tp, const std::vector< carma_perception_msgs::msg::ExternalObject > &external_objects)
Return the earliest collision object and time of collision pair from the given trajectory and list of...
std::optional< rclcpp::Time > get_collision_time(const carma_planning_msgs::msg::TrajectoryPlan &original_tp, const carma_perception_msgs::msg::ExternalObject &curr_obstacle, double original_tp_max_speed)
Return collision time given two trajectories with one being external object with predicted steps.
void lookup_ecef_to_map_transform()
Looks up the transform between map and earth frames, and sets the member variable.
std::optional< rclcpp::Time > last_speed_time_
std::unordered_map< uint32_t, rclcpp::Time > get_collision_times_concurrently_cpu(const carma_planning_msgs::msg::TrajectoryPlan &original_tp, const std::vector< carma_perception_msgs::msg::ExternalObject > &external_objects, double original_tp_max_speed)
CPU implementation of get_collision_times_concurrently. Launches one thread per external object and c...
void update_route_llt_cache()
Rebuild the cached route lanelet polygons and IDs from the current route. Should be called once whene...
void bsm_cb(const carma_v2x_msgs::msg::BSM::UniquePtr msg)
callback for bsm message
MobilityResponseCB mobility_response_publisher_
std::string bsmIDtoString(carma_v2x_msgs::msg::BSMCoreData bsm_core)
void set_external_objects(const std::vector< carma_perception_msgs::msg::ExternalObject > &object_list)
Setter for external objects with predictions in the environment.
YieldPlugin(std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > nh, carma_wm::WorldModelConstPtr wm, YieldPluginConfig config, MobilityResponseCB mobility_response_publisher, LaneChangeStatusCB lc_status_publisher)
Constructor.
std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > nh_
void set_georeference_string(const std::string &georeference)
Setter for map projection string to define lat/lon -> map conversion.
std::unordered_map< uint32_t, rclcpp::Time > get_collision_times_concurrently(const carma_planning_msgs::msg::TrajectoryPlan &original_tp, const std::vector< carma_perception_msgs::msg::ExternalObject > &external_objects, double original_tp_max_speed)
Given the list of objects with predicted states, get all collision times concurrently using multi-thr...
YieldPluginConfig config_
std::optional< rclcpp::Time > first_time_stopped_to_prevent_collision_
std::optional< GetCollisionResult > get_collision(const carma_planning_msgs::msg::TrajectoryPlan &ego_trajectory, const std::vector< carma_perception_msgs::msg::PredictedState > &object_predictions, double collision_radius, double ego_max_speed)
Return naive collision time and locations based on collision radius given two trajectories with one b...
std::vector< std::pair< int, lanelet::BasicPoint2d > > detect_trajectories_intersection(std::vector< lanelet::BasicPoint2d > self_trajectory, std::vector< lanelet::BasicPoint2d > incoming_trajectory) const
detect intersection point(s) of two trajectories
std::optional< carma_planning_msgs::msg::TrajectoryPlan > last_traj_plan_committed_to_stopping_
lanelet::BasicPoint2d ecef_to_map_point(const carma_v2x_msgs::msg::LocationECEF &ecef_point) const
convert a point in ecef frame (in cm) into map frame (in meters)
carma_planning_msgs::msg::TrajectoryPlan update_traj_for_object(const carma_planning_msgs::msg::TrajectoryPlan &original_tp, const std::vector< carma_perception_msgs::msg::ExternalObject > &external_objects, double initial_velocity)
trajectory is modified to safely avoid obstacles on the road
carma_planning_msgs::msg::TrajectoryPlan generate_JMT_trajectory(const carma_planning_msgs::msg::TrajectoryPlan &original_tp, double initial_pos, double goal_pos, double initial_velocity, double goal_velocity, double planning_time, double original_max_speed)
generate a Jerk Minimizing Trajectory(JMT) with the provided start and end conditions
carma_v2x_msgs::msg::MobilityResponse compose_mobility_response(const std::string &resp_recipient_id, const std::string &req_plan_id, bool response) const
compose a mobility response message
std::pair< bool, int > find_on_route_in_predictions(const std::vector< carma_perception_msgs::msg::PredictedState > &predictions, int stride, bool zero_speed) const
Check whether any predicted state of an object falls within the route lanelet polygons.
std::vector< lanelet::ConstLanelet > route_llt_polygons_
carma_planning_msgs::msg::TrajectoryPlan update_traj_for_cooperative_behavior(const carma_planning_msgs::msg::TrajectoryPlan &original_tp, double current_speed)
update trajectory for yielding to an incoming cooperative behavior
std::unordered_map< uint32_t, rclcpp::Time > get_collision_times_concurrently_cuda(const carma_planning_msgs::msg::TrajectoryPlan &original_tp, const std::vector< carma_perception_msgs::msg::ExternalObject > &external_objects, double original_tp_max_speed)
CUDA implementation of get_collision_times_concurrently. Filters objects to those with on-route predi...
std::unordered_map< uint32_t, int > consecutive_clearance_count_for_obstacles_
std::vector< carma_perception_msgs::msg::ExternalObject > external_objects_
bool is_object_behind_vehicle(uint32_t object_id, const rclcpp::Time &collision_time, double vehicle_point, double object_downtrack)
Check if object location is behind the vehicle using estimates of the vehicle's length and route down...
double max_trajectory_speed(const std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > &trajectory_points, double timestamp_in_sec_to_search_until) const
calculates the maximum speed in a set of tajectory points
double polynomial_calc(std::vector< double > coeff, double x) const
calculate quintic polynomial equation for a given x
std::optional< double > last_speed_
double polynomial_calc_d(std::vector< double > coeff, double x) const
calculate derivative of quintic polynomial equation for a given x
carma_wm::WorldModelConstPtr wm_
auto to_string(const UtmZone &zone) -> std::string
Definition: utm_zone.cpp:21
std::shared_ptr< const WorldModel > WorldModelConstPtr
Definition: WorldModel.hpp:454
std::function< void(const carma_planning_msgs::msg::LaneChangeStatus &)> LaneChangeStatusCB
std::function< void(const carma_v2x_msgs::msg::MobilityResponse &)> MobilityResponseCB
Stuct containing the algorithm configuration values for the YieldPluginConfig.
Convenience class for saving collision results.
lanelet::BasicPoint2d object_point
lanelet::BasicPoint2d ego_point
Convenience class for pairing 2d points with speeds.
lanelet::BasicPoint2d point