20 namespace std_ph = std::placeholders;
29 case carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING:
30 return mvr.lane_following_maneuver.end_speed;
31 case carma_planning_msgs::msg::Maneuver::LANE_CHANGE:
32 return mvr.lane_change_maneuver.end_speed;
33 case carma_planning_msgs::msg::Maneuver::STOP_AND_WAIT:
77 auto error_1 = update_params<double>({
99 auto error_2 = update_params<int>({
103 auto error_3 = update_params<std::string>({
110 rcl_interfaces::msg::SetParametersResult result;
112 result.successful = !error_1 && !error_2 && !error_3;
119 RCLCPP_INFO_STREAM(rclcpp::get_logger(
logger_name),
"ApproachingEmergencyVehiclePlugin trying to configure");
149 RCLCPP_INFO_STREAM(rclcpp::get_logger(
logger_name),
"ApproachingEmergencyVehiclePlugin Config: " <<
config_);
155 incoming_bsm_sub_ = create_subscription<carma_v2x_msgs::msg::BSM>(
"incoming_bsm", 1,
158 georeference_sub_ = create_subscription<std_msgs::msg::String>(
"georeference", 10,
161 route_state_sub_ = create_subscription<carma_planning_msgs::msg::RouteState>(
"route_state", 10,
164 twist_sub_ = create_subscription<geometry_msgs::msg::TwistStamped>(
"current_velocity", 10,
170 guidance_state_sub_ = create_subscription<carma_planning_msgs::msg::GuidanceState>(
"state", 1,
173 route_sub_ = create_subscription<carma_planning_msgs::msg::Route>(
"route", 1,
186 return CallbackReturn::SUCCESS;
194 std::chrono::milliseconds(erv_timeout_check_period_ms),
200 std::chrono::milliseconds(emergency_vehicle_response_period_ms),
206 std::chrono::milliseconds(approaching_erv_status_period_ms),
210 int hazard_light_status_ms = (1 / 30) * 1000;
212 std::chrono::milliseconds(hazard_light_status_ms),
215 return CallbackReturn::SUCCESS;
230 std_msgs::msg::Bool msg;
253 carma_v2x_msgs::msg::EmergencyVehicleResponse msg;
257 msg.can_change_lanes =
false;
258 msg.reason_exists =
true;
282 carma_msgs::msg::UIInstructions status_msg;
283 status_msg.type = carma_msgs::msg::UIInstructions::INFO;
317 fmter %
"Approaching ERV is in our lane. Attempting to change lanes to the right.";
320 fmter %
"Approaching ERV is in our lane. Attempting to change lanes to the left.";
335 fmter %(
"Approaching ERV is in our lane and a lane change is not possible. Remaining in the current lane at a reduced speed of " +
std::to_string(target_speed_mph) +
" mph.");
338 fmter %(
"Approaching ERV is in our lane and a lane change is not possible. Remaining in the current lane and slowing down to a reduced speed of " +
std::to_string(target_speed_mph) +
" mph.");
343 fmter %(
"Approaching ERV is in our lane and a lane change is not possible. Remaining in the current lane and maintaining a speed of " +
std::to_string(non_reduced_speed_to_maintain_mph) +
" mph.");
348 fmter %(
"Approaching ERV is in adjacent lane. Remaining in the current lane at a reduced speed of " +
std::to_string(target_speed_mph) +
" mph.");
351 fmter %(
"Approaching ERV is in adjacent lane. Remaining in the current lane and slowing down to a reduced speed of " +
std::to_string(target_speed_mph) +
" mph.");
356 throw std::invalid_argument(
"State is SLOWING_DOWN_FOR_ERV but latest maneuver plan is empty!");
361 throw std::invalid_argument(
"Transition table in unsupported state");
365 std::string str = fmter.str();
366 status_msg.msg = str;
374 throw std::invalid_argument(
"Attempting to get ERV's current position in map before map projection was set");
378 lanelet::projection::LocalFrameProjector projector(
map_projector_.get().c_str());
381 std::vector<lanelet::BasicPoint3d> erv_current_position_projected_vec;
384 lanelet::GPSPoint current_erv_location;
385 current_erv_location.lat = current_latitude;
386 current_erv_location.lon = current_longitude;
389 erv_current_position_projected_vec.emplace_back(projector.forward(current_erv_location));
390 auto erv_current_position_in_map_vec = lanelet::utils::transform(erv_current_position_projected_vec, [](
auto a) {
return lanelet::traits::to2D(a); });
393 if(!erv_current_position_in_map_vec.empty()){
394 return erv_current_position_in_map_vec[0];
397 return boost::optional<lanelet::BasicPoint2d>();
406 std::stringstream ss;
407 for(
size_t i = 0;
i < msg->core_data.id.size(); ++
i){
408 ss << std::setfill(
'0') << std::setw(2) << std::hex << (unsigned)msg->core_data.id.at(
i);
413 bool has_active_lights_and_sirens =
false;
414 if(msg->presence_vector & carma_v2x_msgs::msg::BSM::HAS_PART_II){
417 if(msg->part_ii.size() > 0){
418 for(
size_t i = 0;
i < msg->part_ii.size(); ++
i){
421 if(msg->part_ii[
i].part_ii_id == carma_v2x_msgs::msg::BSMPartIIExtension::SPECIAL_VEHICLE_EXT){
422 carma_v2x_msgs::msg::SpecialVehicleExtensions special_vehicle_ext = msg->part_ii[
i].special_vehicle_extensions;
424 if(special_vehicle_ext.presence_vector & carma_v2x_msgs::msg::SpecialVehicleExtensions::HAS_VEHICLE_ALERTS){
425 if(special_vehicle_ext.vehicle_alerts.siren_use.siren_in_use == j2735_v2x_msgs::msg::SirenInUse::IN_USE
426 && special_vehicle_ext.vehicle_alerts.lights_use.lightbar_in_use == j2735_v2x_msgs::msg::LightbarInUse::IN_USE){
427 has_active_lights_and_sirens =
true;
435 if(!has_active_lights_and_sirens){
437 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"BSM is not a valid ERV BSM since the lights and sirens are not both active; return an empty object");
439 return boost::optional<ErvInformation>();
443 if(msg->core_data.presence_vector & carma_v2x_msgs::msg::BSMCoreData::SPEED_AVAILABLE){
448 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"BSM is not a valid ERV BSM since current speed is not included; return an empty object");
450 return boost::optional<ErvInformation>();
455 return boost::optional<ErvInformation>();
459 if(msg->core_data.presence_vector & carma_v2x_msgs::msg::BSMCoreData::LATITUDE_AVAILABLE){
463 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"No latitude available");
466 return boost::optional<ErvInformation>();
470 if(msg->core_data.presence_vector & carma_v2x_msgs::msg::BSMCoreData::LONGITUDE_AVAILABLE){
476 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"No longitude available");
478 return boost::optional<ErvInformation>();
484 if(erv_position_in_map){
489 std::vector<carma_v2x_msgs::msg::Position3D> erv_destination_points;
490 if(msg->presence_vector & carma_v2x_msgs::msg::BSM::HAS_REGIONAL){
493 if(msg->regional.size() > 0){
494 for(
size_t i = 0;
i < msg->regional.size(); ++
i){
495 if(msg->regional[
i].regional_extension_id == carma_v2x_msgs::msg::BSMRegionalExtension::ROUTE_DESTINATIONS){
496 erv_destination_points = msg->regional[
i].route_destination_points;
503 if(erv_destination_points.empty()){
504 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"ERV's BSM does not contain any future destination points");
507 return boost::optional<ErvInformation>();
516 if(!erv_future_route){
518 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"The ERV's route could not be generated");
520 return boost::optional<ErvInformation>();
525 if(!erv_future_route.get().shortestPath().empty()){
526 lanelet::ConstLanelet erv_current_lanelet = erv_future_route.get().shortestPath()[0];
533 for (
auto llt: erv_future_route.get().shortestPath())
535 if (
wm_->getRoute()->contains(llt))
539 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Detected that ERV: " << erv_information.
vehicle_id <<
" and CMV are travelling in the SAME direction");
547 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Detected that ERV and CMV are travelling in DIFFERENT directions");
548 return boost::optional<ErvInformation>();
552 int lane_index =
wm_->getMapRoutingGraph()->rights(erv_current_lanelet).size();
567 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"First time detecting this ERV, it's lane index will be " << lane_index);
573 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"ERV's lane index is " << erv_information.
lane_index);
577 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"ERV's shortest path is empty!");
581 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Calling getRouteIntersectingLanelet");
583 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Done calling getRouteIntersectingLanelet");
585 if(intersecting_lanelet){
590 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"No intersecting lanelet between the ERV's future route and the ego vehicle's future route was found.");
592 return boost::optional<ErvInformation>();
596 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Calling getSecondsUntilPassing()");
598 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Done calling getSecondsUntilPassing()");
600 if(seconds_until_passing){
602 RCLCPP_INFO_STREAM(rclcpp::get_logger(
logger_name),
"Detected approaching ERV that is passing ego vehicle in " << seconds_until_passing.get() <<
" seconds");
605 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"Detected ERV is not approaching the ego vehicle");
608 return boost::optional<ErvInformation>();
611 return erv_information;
634 std::vector<carma_v2x_msgs::msg::Position3D> erv_destination_points){
637 throw std::invalid_argument(
"Attempting to generate an ERV's route before map projection was set");
641 lanelet::projection::LocalFrameProjector projector(
map_projector_.get().c_str());
644 std::vector<lanelet::BasicPoint3d> erv_destination_points_projected;
647 lanelet::GPSPoint current_erv_location;
649 current_erv_location.lat = current_latitude;
650 current_erv_location.lon = current_longitude;
655 if(erv_destination_points.size() > 0){
656 for(
size_t i = 0;
i < erv_destination_points.size(); ++
i){
657 carma_v2x_msgs::msg::Position3D position_3d_point = erv_destination_points[
i];
659 lanelet::GPSPoint erv_destination_point;
660 erv_destination_point.lon = position_3d_point.longitude;
661 erv_destination_point.lat = position_3d_point.latitude;
663 if(position_3d_point.elevation_exists){
664 erv_destination_point.ele = position_3d_point.elevation;
667 erv_destination_points_projected.emplace_back(projector.forward(erv_destination_point));
672 auto erv_destination_points_in_map = lanelet::utils::transform(erv_destination_points_projected, [](
auto a) {
return lanelet::traits::to2D(a); });
674 auto cmv_location = lanelet::traits::to2D(projector.forward(current_erv_location));
675 auto shortened_erv_destination_points_in_map =
filter_points_ahead(cmv_location, erv_destination_points_in_map);
677 if(shortened_erv_destination_points_in_map.empty())
679 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"ERV has passed all the destination points!");
682 return lanelet::Optional<lanelet::routing::Route>();
686 for(
size_t i = 0;
i < shortened_erv_destination_points_in_map.size(); ++
i){
687 auto pt = shortened_erv_destination_points_in_map[
i];
690 if((
wm_->getLaneletsFromPoint(shortened_erv_destination_points_in_map[
i])).empty()){
691 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"ERV destination point " <<
i
692 <<
" is not contained in a lanelet map; x: " << pt.x() <<
" y: " << pt.y());
694 return lanelet::Optional<lanelet::routing::Route>();
699 auto starting_lanelet_vector = lanelet::geometry::findNearest(
wm_->getMap()->laneletLayer, cmv_location, 1);
700 if(starting_lanelet_vector.empty())
702 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"Found no lanelets in the map. ERV routing cannot be completed.");
705 return lanelet::Optional<lanelet::routing::Route>();
707 auto starting_lanelet = lanelet::ConstLanelet(starting_lanelet_vector[0].second.constData());
710 auto ending_lanelet_vector = lanelet::geometry::findNearest(
wm_->getMap()->laneletLayer, shortened_erv_destination_points_in_map.back(), 1);
711 auto ending_lanelet = lanelet::ConstLanelet(ending_lanelet_vector[0].second.constData());
712 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"ending_lanelet: " << ending_lanelet.id());
713 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"starting_lanelet: " << starting_lanelet.id());
716 std::vector<lanelet::BasicPoint2d> via = std::vector<lanelet::BasicPoint2d>(shortened_erv_destination_points_in_map.begin(), shortened_erv_destination_points_in_map.end() - 1);
717 lanelet::ConstLanelets via_lanelets_vector;
718 for(
const auto&
point : via){
719 auto lanelet_vector = lanelet::geometry::findNearest(
wm_->getMap()->laneletLayer,
point, 1);
720 auto chosen_lanelet_to_emplace = lanelet::ConstLanelet(lanelet_vector[0].second.constData());
721 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"chosen_lanelet_to_emplace: " << chosen_lanelet_to_emplace.id());
723 if (chosen_lanelet_to_emplace.id() != starting_lanelet.id())
724 via_lanelets_vector.emplace_back(chosen_lanelet_to_emplace);
727 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"======> id was found same: " << chosen_lanelet_to_emplace.id());
732 auto erv_route =
wm_->getMapRoutingGraph()->getRouteVia(starting_lanelet, via_lanelets_vector, ending_lanelet);
739 if (original_points.size() <= 1)
741 return original_points;
745 auto extended_points = original_points;
746 double last_dx = (original_points.end() - 1 ) ->
x() - (original_points.end() - 2 ) ->
x();
747 double last_dy = (original_points.end() - 1 ) ->
y() - (original_points.end() - 2 ) ->
y();
748 lanelet::BasicPoint2d extended_point = {(original_points.end() - 1 ) ->
x() + last_dx, (original_points.end() - 1 ) ->
y() + last_dy};
749 extended_points.push_back(extended_point);
753 double closest_dist = DBL_MAX;
754 while (
i < extended_points.size() - 1)
757 double v1x = reference_point.x() - extended_points[
i].x();
759 double v1y = reference_point.y() - extended_points[
i].y();
760 double v2x = extended_points[
i+1].x() - extended_points[
i].x();
761 double v2y = extended_points[
i+1].y() - extended_points[
i].y();
763 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"reference_point x: " << reference_point.x() <<
", y: " << reference_point.y());
764 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"extended_points x: " << extended_points[
i].
x() <<
", y: " << extended_points[
i].
y());
768 double dotProduct = v1x * v2x + v1y * v2y;
771 double v1Mag = sqrt(v1x * v1x + v1y * v1y);
772 double v2Mag = sqrt(v2x * v2x + v2y * v2y);
775 double angleRad = acos(dotProduct / (v1Mag * v2Mag));
778 if (angleRad >= M_PI / 2)
780 double dx = reference_point.x() - extended_points[
i].x();
781 double dy = reference_point.y() - extended_points[
i].y();
782 double distance = sqrt (dx * dx + dy * dy);
783 if (distance < closest_dist)
785 closest_dist = distance;
787 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"closest_dist: " << closest_dist <<
", closest_idx" << closest_idx);
794 double dx = reference_point.x() - original_points.back().x();
795 double dy = reference_point.y() - original_points.back().y();
796 double distance = sqrt (dx * dx + dy * dy);
800 if (distance < closest_dist)
802 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"Returning empty here");
807 return std::vector<lanelet::BasicPoint2d>(original_points.begin() + closest_idx, original_points.end());
817 std::stringstream ss;
818 for(
size_t i = 0;
i < msg->core_data.id.size(); ++
i){
819 ss << std::setfill(
'0') << std::setw(2) << std::hex << (unsigned)msg->core_data.id.at(
i);
821 std::string erv_vehicle_id = ss.str();
822 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Received a BSM from " << erv_vehicle_id);
832 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Ignoring BSM from tracked ERV " << erv_vehicle_id <<
" since a BSM from it was processed " << seconds_since_prev_processed_bsm <<
" seconds ago");
849 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Ignoring BSM from non tracked ERV " << erv_vehicle_id <<
" since a BSM from it was processed " << seconds_since_prev_processed_bsm <<
" seconds ago");
857 if(!erv_information){
858 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"BSM is not from an active ERV that is approaching the ego vehicle.");
861 RCLCPP_INFO_STREAM(rclcpp::get_logger(
logger_name),
"BSM was from the currently tracked approaching ERV! ERV is no longer approaching.");
884 const double& erv_current_speed, lanelet::ConstLanelet& intersecting_lanelet){
887 lanelet::ConstLineString2d intersecting_centerline = lanelet::utils::to2D(intersecting_lanelet.centerline());
888 lanelet::BasicPoint2d intersecting_end_point = intersecting_centerline.back();
894 lanelet::routing::Route
route = std::move(*erv_future_route);
899 double erv_dist_to_lanelet =
erv_world_model_->routeTrackPos(intersecting_end_point).downtrack -
erv_world_model_->routeTrackPos(erv_position_in_map).downtrack;
901 if(erv_dist_to_lanelet < ego_dist_to_lanelet){
905 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Detected ERV is in front of the ego vehicle");
906 return boost::optional<double>();
915 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"ERV has passed the ego vehicle");
919 return boost::optional<double>();
927 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Detected ERV is travelling slower than the ego vehicle, and will not pass the ego vehicle");
928 return boost::optional<double>();
934 if(delta_speed == 0.0){
937 double seconds_until_passing = (erv_dist_to_lanelet - ego_dist_to_lanelet) / delta_speed;
939 return seconds_until_passing;
947 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"Remaining route lanelets for the ego vehicle not found; plugin cannot compute the intersecting lanelet.");
948 return boost::optional<lanelet::ConstLanelet>();
958 lanelet::Id ego_route_lanelet_id = *it;
959 lanelet::ConstLanelet ego_route_lanelet =
wm_->getMap()->laneletLayer.get(ego_route_lanelet_id);
962 lanelet::BasicPoint2d ego_route_lanelet_centerline_end = lanelet::utils::to2D(ego_route_lanelet.centerline()).back();
963 double ego_route_lanelet_centerline_end_downtrack =
wm_->routeTrackPos(ego_route_lanelet_centerline_end).downtrack;
965 if(current_downtrack > ego_route_lanelet_centerline_end_downtrack){
968 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Removing passed lanelet " << ego_route_lanelet_id);
973 if(erv_future_route.contains(ego_route_lanelet)){
974 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Found intersecting lanelet " << ego_route_lanelet_id);
975 return boost::optional<lanelet::ConstLanelet>(ego_route_lanelet);
1004 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Received route callback");
1005 std::vector<int> new_future_route_lanelet_ids;
1007 for(
size_t i = 0;
i < msg->route_path_lanelet_ids.size(); ++
i){
1008 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"New route lanelet: " << msg->route_path_lanelet_ids[
i]);
1009 new_future_route_lanelet_ids.push_back(msg->route_path_lanelet_ids[
i]);
1019 lanelet::Optional<carma_wm::TrafficRulesConstPtr> traffic_rules =
wm_->getTrafficRules();
1022 speed_limit =(*traffic_rules)->speedLimit(
lanelet).speedLimit.value();
1026 throw std::invalid_argument(
"No speed limit could be found since valid traffic rules object could not be built");
1036 double sum_start_and_end_speed = maneuver_start_speed + maneuver_end_speed;
1038 if(sum_start_and_end_speed < epsilon){
1039 throw std::invalid_argument(
"Maneuver start and ending speed is zero");
1042 rclcpp::Duration maneuver_duration{0,0};
1046 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
logger_name),
"maneuver_end_dist: " << maneuver_end_dist <<
", maneuver_start_dist: " << maneuver_start_dist <<
", sum_start_and_end_speed: " << sum_start_and_end_speed);
1048 maneuver_duration = rclcpp::Duration((maneuver_end_dist - maneuver_start_dist) / (0.5 * sum_start_and_end_speed) * 1e9);
1050 return maneuver_duration;
1054 double start_speed,
double target_speed,
int lanelet_id, rclcpp::Time& start_time)
const
1056 carma_planning_msgs::msg::Maneuver maneuver_msg;
1058 maneuver_msg.type = carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING;
1059 maneuver_msg.lane_following_maneuver.parameters.negotiation_type = carma_planning_msgs::msg::ManeuverParameters::NO_NEGOTIATION;
1060 maneuver_msg.lane_following_maneuver.parameters.presence_vector = carma_planning_msgs::msg::ManeuverParameters::HAS_TACTICAL_PLUGIN;
1063 maneuver_msg.lane_following_maneuver.start_dist = start_dist;
1064 maneuver_msg.lane_following_maneuver.start_speed = start_speed;
1065 maneuver_msg.lane_following_maneuver.start_time = start_time;
1066 maneuver_msg.lane_following_maneuver.end_dist = end_dist;
1067 maneuver_msg.lane_following_maneuver.end_speed = target_speed;
1068 maneuver_msg.lane_following_maneuver.lane_ids = {
std::to_string(lanelet_id) };
1071 maneuver_msg.lane_following_maneuver.end_time = start_time + maneuver_duration;
1073 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Composed lane follow maneuver for lanelet ID:" << lanelet_id <<
" with duration " << maneuver_duration.seconds());
1074 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"start speed: " << start_speed <<
", end speed: " << target_speed);
1075 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"start dist: " << start_dist <<
", end dist: " << end_dist);
1077 return maneuver_msg;
1081 double start_speed,
double target_speed, lanelet::Id starting_lane_id, lanelet::Id ending_lane_id, rclcpp::Time& start_time)
const
1083 carma_planning_msgs::msg::Maneuver maneuver_msg;
1084 maneuver_msg.type = carma_planning_msgs::msg::Maneuver::LANE_CHANGE;
1085 maneuver_msg.lane_change_maneuver.parameters.negotiation_type = carma_planning_msgs::msg::ManeuverParameters::NO_NEGOTIATION;
1086 maneuver_msg.lane_change_maneuver.parameters.presence_vector = carma_planning_msgs::msg::ManeuverParameters::HAS_TACTICAL_PLUGIN;
1089 maneuver_msg.lane_change_maneuver.start_dist = start_dist;
1090 maneuver_msg.lane_change_maneuver.start_speed = start_speed;
1091 maneuver_msg.lane_change_maneuver.start_time = start_time;
1092 maneuver_msg.lane_change_maneuver.end_dist = end_dist;
1093 maneuver_msg.lane_change_maneuver.end_speed = target_speed;
1094 maneuver_msg.lane_change_maneuver.starting_lane_id =
std::to_string(starting_lane_id);
1095 maneuver_msg.lane_change_maneuver.ending_lane_id =
std::to_string(ending_lane_id);
1098 maneuver_msg.lane_change_maneuver.end_time = start_time + maneuver_duration;
1105 static auto gen = boost::uuids::random_generator();
1106 maneuver_msg.lane_change_maneuver.parameters.maneuver_id = boost::lexical_cast<std::string>(gen());
1109 RCLCPP_DEBUG_STREAM(get_logger(),
"Creating lane change id: " << maneuver_msg.lane_change_maneuver.parameters.maneuver_id <<
"start dist: " << start_dist <<
" end dist: " << end_dist <<
" Starting llt: " << starting_lane_id <<
" Ending llt: " << ending_lane_id);
1110 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"start speed: " << start_speed <<
", end speed: " << target_speed <<
", duration: " << maneuver_duration.seconds());
1111 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"start dist: " << start_dist <<
", end dist: " << end_dist);
1113 return maneuver_msg;
1117 lanelet::Id starting_lane_id, lanelet::Id ending_lane_id,
double stopping_deceleration, rclcpp::Time& start_time)
const
1119 carma_planning_msgs::msg::Maneuver maneuver_msg;
1120 maneuver_msg.type = carma_planning_msgs::msg::Maneuver::STOP_AND_WAIT;
1121 maneuver_msg.stop_and_wait_maneuver.parameters.negotiation_type = carma_planning_msgs::msg::ManeuverParameters::NO_NEGOTIATION;
1122 maneuver_msg.stop_and_wait_maneuver.parameters.presence_vector = carma_planning_msgs::msg::ManeuverParameters::HAS_TACTICAL_PLUGIN
1123 | carma_planning_msgs::msg::ManeuverParameters::HAS_FLOAT_META_DATA;
1126 maneuver_msg.stop_and_wait_maneuver.start_time = start_time;
1127 maneuver_msg.stop_and_wait_maneuver.start_dist = start_dist;
1128 maneuver_msg.stop_and_wait_maneuver.start_speed = start_speed;
1129 maneuver_msg.stop_and_wait_maneuver.end_dist = end_dist;
1130 maneuver_msg.stop_and_wait_maneuver.starting_lane_id =
std::to_string(starting_lane_id);
1131 maneuver_msg.stop_and_wait_maneuver.ending_lane_id =
std::to_string(ending_lane_id);
1134 maneuver_msg.stop_and_wait_maneuver.end_time = start_time + maneuver_duration;
1138 maneuver_msg.stop_and_wait_maneuver.parameters.float_valued_meta_data.push_back(stopping_deceleration);
1140 static auto gen = boost::uuids::random_generator();
1141 maneuver_msg.stop_and_wait_maneuver.parameters.maneuver_id = boost::lexical_cast<std::string>(gen());
1143 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Composed stop and wait maneuver for with start lanelet:" << starting_lane_id <<
", end lanelet: " << ending_lane_id <<
" with duration " << maneuver_duration.seconds());
1144 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"start speed: " << start_speed);
1145 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"start dist: " << start_dist <<
", end dist: " << end_dist);
1147 return maneuver_msg;
1151 double downtrack_progress,
double stop_maneuver_beginning_downtrack,
double end_of_route_downtrack,
1152 double stopping_entry_speed,
double stopping_deceleration,
double current_lanelet_ending_downtrack,
1153 lanelet::ConstLanelet current_lanelet, rclcpp::Time time_progress)
1155 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Maneuver plan is reaching the end of the route");
1161 stopping_entry_speed, stopping_entry_speed, current_lanelet.id(), time_progress));
1163 downtrack_progress = stop_maneuver_beginning_downtrack;
1168 lanelet::Id start_lane_id = current_lanelet.id();
1171 while(current_lanelet_ending_downtrack < end_of_route_downtrack){
1173 if(!
wm_->getMapRoutingGraph()->following(current_lanelet,
false).empty()){
1174 current_lanelet =
wm_->getMapRoutingGraph()->following(current_lanelet,
false).front();
1177 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"A following lanelet in the current lane could not be found; returning empty plan");
1178 resp->new_plan.maneuvers = {};
1183 if(!
wm_->getRoute()->contains(current_lanelet)){
1184 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"The next lanelet in the current lane is not on the route; returning empty plan");
1185 resp->new_plan.maneuvers = {};
1190 current_lanelet_ending_downtrack =
wm_->routeTrackPos(current_lanelet.centerline2d().back()).downtrack;
1191 if(current_lanelet_ending_downtrack >= end_of_route_downtrack){
1198 stopping_entry_speed, start_lane_id, current_lanelet.id(), stopping_deceleration, time_progress));
1202 carma_planning_msgs::srv::PlanManeuvers::Response::SharedPtr resp,
1203 lanelet::ConstLanelet current_lanelet,
double downtrack_progress,
double current_lanelet_ending_downtrack,
1204 double speed_progress,
double target_speed, rclcpp::Time time_progress,
bool is_maintaining_non_reduced_speed)
1206 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Generating remain-in-lane maneuver plan");
1212 if(is_maintaining_non_reduced_speed){
1219 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Maneuver target speed reduced to " << target_speed);
1223 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Ending downtrack based on plan duration: " << maneuver_plan_ending_downtrack);
1225 maneuver_plan_ending_downtrack = std::min(maneuver_plan_ending_downtrack,
wm_->getRouteEndTrackPos().downtrack);
1226 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Ending downtrack based on end of route: " <<
wm_->getRouteEndTrackPos().downtrack);
1227 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Selected ending downtrack: " << maneuver_plan_ending_downtrack);
1234 double stopping_distance = (target_speed * target_speed) / (2.0 * stopping_deceleration);
1235 double begin_stopping_downtrack =
wm_->getRouteEndTrackPos().downtrack - stopping_distance;
1236 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Stop and wait maneuver must begin by downtrack " << begin_stopping_downtrack);
1239 while(downtrack_progress < maneuver_plan_ending_downtrack){
1241 if(begin_stopping_downtrack <= current_lanelet_ending_downtrack){
1244 speed_progress, stopping_deceleration, current_lanelet_ending_downtrack, current_lanelet, time_progress);
1250 speed_progress, target_speed, current_lanelet.id(), time_progress));
1253 if(!
wm_->getMapRoutingGraph()->following(current_lanelet,
false).empty())
1255 current_lanelet =
wm_->getMapRoutingGraph()->following(current_lanelet,
false).front();
1259 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"A following lanelet in the current lane could not be found; returning empty plan");
1260 resp->new_plan.maneuvers = {};
1265 if(!
wm_->getRoute()->contains(current_lanelet)){
1266 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"The next lanelet in the current lane is not on the route; returning empty plan");
1267 resp->new_plan.maneuvers = {};
1272 downtrack_progress =
wm_->routeTrackPos(current_lanelet.centerline2d().front()).downtrack;
1273 current_lanelet_ending_downtrack =
wm_->routeTrackPos(current_lanelet.centerline2d().back()).downtrack;
1278 if(is_maintaining_non_reduced_speed){
1285 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Maneuver target speed reduced to " << target_speed);
1290 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Next maneuver starting downtrack is " << downtrack_progress <<
", end of plan is at " << maneuver_plan_ending_downtrack);
1296 carma_planning_msgs::srv::PlanManeuvers::Response::SharedPtr resp,
1297 lanelet::ConstLanelet current_lanelet,
double downtrack_progress,
double current_lanelet_ending_downtrack,
1298 double speed_progress,
double target_speed, rclcpp::Time time_progress,
int ego_lane_index,
int erv_lane_index)
1300 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Generating move-over maneuver plan");
1303 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Ending downtrack based on plan duration: " << maneuver_plan_ending_downtrack);
1305 maneuver_plan_ending_downtrack = std::min(maneuver_plan_ending_downtrack,
wm_->getRouteEndTrackPos().downtrack);
1306 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Ending downtrack based on end of route: " <<
wm_->getRouteEndTrackPos().downtrack);
1307 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Selected ending downtrack: " << maneuver_plan_ending_downtrack);
1314 double stopping_distance = (target_speed * target_speed) / (2.0 * stopping_deceleration);
1315 double begin_stopping_downtrack =
wm_->getRouteEndTrackPos().downtrack - stopping_distance;
1316 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Stop and wait maneuver must begin by downtrack " << begin_stopping_downtrack);
1320 while(downtrack_progress < maneuver_plan_ending_downtrack){
1321 if(begin_stopping_downtrack <= current_lanelet_ending_downtrack){
1324 speed_progress, stopping_deceleration, current_lanelet_ending_downtrack, current_lanelet, time_progress);
1337 speed_progress, target_speed, current_lanelet.id(), time_progress));
1341 if(!
wm_->getMapRoutingGraph()->following(current_lanelet,
false).empty())
1343 current_lanelet =
wm_->getMapRoutingGraph()->following(current_lanelet,
false).front();
1347 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"A following lanelet in the current lane could not be found; returning empty plan");
1348 resp->new_plan.maneuvers = {};
1353 if(!
wm_->getRoute()->contains(current_lanelet)){
1354 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"The next lanelet in the current lane is not on the route; returning empty plan");
1355 resp->new_plan.maneuvers = {};
1360 downtrack_progress =
wm_->routeTrackPos(current_lanelet.centerline2d().front()).downtrack;
1361 current_lanelet_ending_downtrack =
wm_->routeTrackPos(current_lanelet.centerline2d().back()).downtrack;
1366 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Next maneuver starting downtrack is " << downtrack_progress <<
", end of plan is at " << maneuver_plan_ending_downtrack);
1371 bool completed_initial_lane_following =
false;
1372 double initial_lane_following_duration = 0.0;
1374 while(downtrack_progress < maneuver_plan_ending_downtrack){
1376 if(begin_stopping_downtrack <= current_lanelet_ending_downtrack){
1379 speed_progress, stopping_deceleration, current_lanelet_ending_downtrack, current_lanelet, time_progress);
1384 if(!completed_initial_lane_following){
1386 speed_progress, target_speed, current_lanelet.id(), time_progress));
1389 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Seconds of lane following before lane change: " << initial_lane_following_duration);
1392 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Minimum lane following duration before lane change satisfied.");
1393 completed_initial_lane_following =
true;
1403 lanelet::Optional<lanelet::ConstLanelet> target_lanelet;
1404 if(ego_lane_index != erv_lane_index){
1405 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"Planning a move-over maneuver plan when the ego vehicle is not in the ERV's path! Returning an empty maneuver plan");
1406 resp->new_plan.maneuvers = {};
1409 else if((ego_lane_index == 0) && (erv_lane_index == 0)){
1412 target_lanelet =
wm_->getMapRoutingGraph()->left(current_lanelet);
1413 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Composing a left lane change maneuver from lanelet " << current_lanelet.id());
1418 target_lanelet =
wm_->getMapRoutingGraph()->right(current_lanelet);
1419 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Composing a right lane change maneuver from lanelet " << current_lanelet.id());
1425 speed_progress, target_speed, current_lanelet.id(), target_lanelet.get().id(), time_progress));
1431 new_lc_params.
start_dist = downtrack_progress;
1432 new_lc_params.
end_dist = current_lanelet_ending_downtrack;
1435 new_lc_params.
maneuver_id = resp->new_plan.maneuvers.back().lane_change_maneuver.parameters.maneuver_id;
1438 current_lanelet = *target_lanelet;
1441 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"A lane change maneuver from " << current_lanelet.id() <<
" could not be composed since no target lanelet was found!");
1443 speed_progress, target_speed, current_lanelet.id(), time_progress));
1448 speed_progress, target_speed, current_lanelet.id(), time_progress));
1453 if(!
wm_->getMapRoutingGraph()->following(current_lanelet,
false).empty())
1455 current_lanelet =
wm_->getMapRoutingGraph()->following(current_lanelet,
false).front();
1459 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"A following lanelet in the current lane could not be found; returning empty plan");
1460 resp->new_plan.maneuvers = {};
1465 if(!
wm_->getRoute()->contains(current_lanelet)){
1466 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"The next lanelet in the current lane is not on the route; returning empty plan");
1467 resp->new_plan.maneuvers = {};
1472 downtrack_progress =
wm_->routeTrackPos(current_lanelet.centerline2d().front()).downtrack;
1473 current_lanelet_ending_downtrack =
wm_->routeTrackPos(current_lanelet.centerline2d().back()).downtrack;
1478 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Next maneuver starting downtrack is " << downtrack_progress <<
", end of plan is at " << maneuver_plan_ending_downtrack);
1487 std::vector<lanelet::ConstLanelet> ego_route_lanelets =
wm_->getLaneletsFromPoint({x_position, y_position});
1488 boost::optional<lanelet::ConstLanelet> ego_route_lanelet;
1490 if (ego_route_lanelets.empty())
1492 RCLCPP_WARN_STREAM(rclcpp::get_logger(
logger_name),
"Given vehicle position is not on the road.");
1493 return boost::optional<lanelet::ConstLanelet>();
1497 for(
const auto&
lanelet : ego_route_lanelets)
1505 return ego_route_lanelet;
1509 std::shared_ptr<rmw_request_id_t>,
1510 carma_planning_msgs::srv::PlanManeuvers::Request::SharedPtr req,
1511 carma_planning_msgs::srv::PlanManeuvers::Response::SharedPtr resp)
1513 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Received request to plan maneuvers");
1516 bool is_currently_lane_changing =
false;
1519 is_currently_lane_changing =
true;
1529 if(ego_current_lanelet_optional){
1530 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"starting lanelet for maneuver plan is " << ego_current_lanelet_optional.get().id());
1533 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Given vehicle position is not within a lanelet on the route. Returning empty maneuver plan");
1539 ego_lane_index_ =
wm_->getMapRoutingGraph()->rights(ego_current_lanelet_optional.get()).size();
1576 resp->new_plan.maneuvers = {};
1582 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"Ego vehicle is not in ERV's path");
1593 resp->new_plan.maneuvers = {};
1600 double downtrack_progress = req->veh_downtrack;
1601 double current_lanelet_ending_downtrack =
wm_->routeTrackPos(ego_current_lanelet_optional.get().centerline2d().back()).downtrack;
1602 double speed_progress = req->veh_logitudinal_velocity;
1604 rclcpp::Time time_progress = rclcpp::Time(req->header.stamp);
1610 resp->new_plan.maneuvers = {};
1611 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
logger_name),
"No approaching ERV. Returning empty maneuver plan");
1618 generateMoveOverManeuverPlan(resp, ego_current_lanelet_optional.get(), downtrack_progress, current_lanelet_ending_downtrack, speed_progress,
1629 throw std::invalid_argument(
"Transition table in unsupported state");
1645#include "rclcpp_components/register_node_macro.hpp"
#define GET_MANEUVER_PROPERTY(mvr, property)
Macro definition to enable easier access to fields shared across the maneuver types.
Class that implements the Approaching Emergency Vehicle Plugin (ERV) strategic plugin....
carma_ros2_utils::SubPtr< geometry_msgs::msg::TwistStamped > twist_sub_
bool has_broadcasted_warning_messages_
boost::optional< lanelet::ConstLanelet > getRouteIntersectingLanelet(const lanelet::routing::Route &erv_future_route)
Helper function to obtain the earliest lanelet that exists on both an ERV's future route and the ego ...
rcl_interfaces::msg::SetParametersResult parameter_update_callback(const std::vector< rclcpp::Parameter > ¶meters)
Callback for dynamic parameter updates.
carma_ros2_utils::SubPtr< carma_planning_msgs::msg::Route > route_sub_
void publishApproachingErvStatus()
This is a callback function for the approaching_emergency_vehicle_status_timer_. It makes a call to g...
rclcpp::Duration getManeuverDuration(const carma_planning_msgs::msg::Maneuver &maneuver, double epsilon) const
Helper function to obtain the (seconds) of a provided maneuver.
carma_ros2_utils::SubPtr< carma_v2x_msgs::msg::EmergencyVehicleAck > incoming_emergency_vehicle_ack_sub_
carma_ros2_utils::PubPtr< std_msgs::msg::Bool > hazard_light_cmd_pub_
carma_ros2_utils::CallbackReturn on_activate_plugin()
This method is used to create a timer and will be called on the activate transition.
void generateMoveOverManeuverPlan(carma_planning_msgs::srv::PlanManeuvers::Response::SharedPtr resp, lanelet::ConstLanelet current_lanelet, double downtrack_progress, double current_lanelet_ending_downtrack, double speed_progress, double target_speed, rclcpp::Time time_progress, int ego_lane_index, int erv_lane_index)
Function to generate a maneuver plan when the ego vehicle must change lanes due to being in the MOVIN...
bool is_guidance_engaged_
boost::optional< std::string > map_projector_
lanelet::Optional< lanelet::routing::Route > generateErvRoute(double current_latitude, double current_longitude, std::vector< carma_v2x_msgs::msg::Position3D > erv_destination_points)
Helper function to generate an ERV's route based on its current position and its future route destina...
UpcomingLaneChangeParameters upcoming_lc_params_
carma_ros2_utils::SubPtr< carma_v2x_msgs::msg::BSM > incoming_bsm_sub_
void broadcastWarningToErv()
This is a callback function for the warning_broadcast_timer_, and is called to broadcast an Emergency...
std::shared_ptr< carma_wm::CARMAWorldModel > erv_world_model_
carma_planning_msgs::msg::Maneuver composeLaneFollowingManeuverMessage(double start_dist, double end_dist, double start_speed, double target_speed, int lanelet_id, rclcpp::Time &start_time) const
Function to compose a lane following maneuver message based on the provided maneuver parameters.
ApproachingEmergencyVehicleTransitionTable transition_table_
carma_ros2_utils::PubPtr< carma_msgs::msg::UIInstructions > approaching_erv_status_pub_
void checkForErvTimeout()
This is a callback function for the erv_timeout_timer_ timer, and is called to determine whether a ti...
boost::optional< lanelet::ConstLanelet > getLaneletOnEgoRouteFromMapPosition(const double &x_position, const double &y_position)
Helper function to convert a map x,y coordinate pair to a lanelet on the ego vehicle's route.
const double MAINTAIN_SPEED_THRESHOLD
bool has_planned_upcoming_lc_
carma_ros2_utils::SubPtr< std_msgs::msg::String > georeference_sub_
void addStopAndWaitToEndOfPlan(carma_planning_msgs::srv::PlanManeuvers::Response::SharedPtr resp, double downtrack_progress, double stop_maneuver_beginning_downtrack, double end_of_route_downtrack, double stopping_entry_speed, double stopping_deceleration, double current_lanelet_ending_downtrack, lanelet::ConstLanelet current_lanelet, rclcpp::Time time_progress)
Function to add a stop and wait maneuver to the end of the maneuver plan contained in the provided 'r...
carma_wm::WorldModelConstPtr wm_
ApproachingEmergencyVehiclePlugin(const rclcpp::NodeOptions &)
ApproachingEmergencyVehiclePlugin constructor.
bool get_availability() override
Get the availability status of this plugin based on the current operating environment....
carma_ros2_utils::CallbackReturn on_configure_plugin()
This method is used to load parameters and will be called on the configure state transition.
ErvInformation tracked_erv_
double non_reduced_speed_to_maintain_
carma_ros2_utils::PubPtr< carma_v2x_msgs::msg::EmergencyVehicleResponse > outgoing_emergency_vehicle_response_pub_
void routeStateCallback(carma_planning_msgs::msg::RouteState::UniquePtr msg)
Route State subscription callback, with is used to update this plugin's latest_route_state_ object.
void guidanceStateCallback(const carma_planning_msgs::msg::GuidanceState::UniquePtr msg)
Subscription callback to process the latest guidance state and update the is_guidance_engaged_ flag a...
void incomingEmergencyVehicleAckCallback(const carma_v2x_msgs::msg::EmergencyVehicleAck::UniquePtr msg)
Subscription callback for incoming EmergencyVehicleAck messages. If the message is from the currently...
carma_planning_msgs::msg::Maneuver composeStopAndWaitManeuverMessage(double start_dist, double end_dist, double start_speed, lanelet::Id starting_lane_id, lanelet::Id ending_lane_id, double stopping_deceleration, rclcpp::Time &start_time) const
Function to compose a stop and wait maneuver message based on the provided maneuver parameters.
boost::optional< double > getSecondsUntilPassing(lanelet::Optional< lanelet::routing::Route > &erv_future_route, const lanelet::BasicPoint2d &erv_position_in_map, const double &erv_current_speed, lanelet::ConstLanelet &intersecting_lanelet)
Helper function to calculate the estimated seconds until an ERV will pass the ego vehicle....
int num_warnings_broadcasted_
void generateReducedSpeedLaneFollowingeManeuverPlan(carma_planning_msgs::srv::PlanManeuvers::Response::SharedPtr resp, lanelet::ConstLanelet current_lanelet, double downtrack_progress, double current_lanelet_ending_downtrack, double speed_progress, double target_speed, rclcpp::Time time_progress, bool is_maintaining_non_reduced_speed)
Function to generate a maneuver plan when the ego vehicle must remain in its lane due to being in the...
std::unordered_map< std::string, bool > is_same_direction_
void publishHazardLightStatus()
This is a callback function for publishing turn ON/OFF (true/false) hazard light command to the ssc d...
carma_planning_msgs::msg::Maneuver composeLaneChangeManeuverMessage(double start_dist, double end_dist, double start_speed, double target_speed, lanelet::Id starting_lane_id, lanelet::Id ending_lane_id, rclcpp::Time &start_time) const
Function to compose a lane change maneuver message based on the provided maneuver parameters.
rclcpp::TimerBase::SharedPtr erv_timeout_timer_
std::unordered_map< std::string, rclcpp::Time > latest_erv_update_times_
carma_planning_msgs::msg::ManeuverPlan latest_maneuver_plan_
boost::optional< lanelet::BasicPoint2d > getErvPositionInMap(const double ¤t_latitude, const double ¤t_longitude)
Helper function to obtain an ERV's position in the map frame from its current latitude and longitude.
rclcpp::TimerBase::SharedPtr hazard_light_timer_
void incomingBsmCallback(carma_v2x_msgs::msg::BSM::UniquePtr msg)
Incoming BSM subscription callback, which determines whether a BSM should be processed,...
carma_planning_msgs::msg::RouteState latest_route_state_
void plan_maneuvers_callback(std::shared_ptr< rmw_request_id_t >, carma_planning_msgs::srv::PlanManeuvers::Request::SharedPtr req, carma_planning_msgs::srv::PlanManeuvers::Response::SharedPtr resp) override
Extending class provided callback which should return a planned trajectory based on the provided traj...
carma_ros2_utils::SubPtr< carma_planning_msgs::msg::RouteState > route_state_sub_
double getLaneletSpeedLimit(const lanelet::ConstLanelet &lanelet)
Helper function to extract the speed limit (m/s) from a provided lanelet.
std::vector< lanelet::BasicPoint2d > filter_points_ahead(const lanelet::BasicPoint2d &reference_point, const std::vector< lanelet::BasicPoint2d > &original_points) const
Helper function that return points ahead of the given reference point accounting for the list of poin...
boost::optional< ErvInformation > getErvInformationFromBsm(carma_v2x_msgs::msg::BSM::UniquePtr msg)
Through internal logic and calls to separate helper functions, this function processes a received BSM...
std::string strategic_plugin_name_
void routeCallback(carma_planning_msgs::msg::Route::UniquePtr msg)
Route subscription callback, with is used to update this plugin's future_route_lanelet_ids_ object.
void twistCallback(geometry_msgs::msg::TwistStamped::UniquePtr msg)
Subscription callback for the twist subscriber, which will store latest current velocity of the ego v...
bool should_broadcast_warnings_
carma_ros2_utils::SubPtr< carma_planning_msgs::msg::GuidanceState > guidance_state_sub_
void georeferenceCallback(const std_msgs::msg::String::UniquePtr msg)
Subscription callback for the georeference.
rclcpp::TimerBase::SharedPtr approaching_emergency_vehicle_status_timer_
const std::string APPROACHING_ERV_STATUS_PARAMS
std::string get_version_id() override
Returns the version id of this plugin.
rclcpp::TimerBase::SharedPtr warning_broadcast_timer_
carma_msgs::msg::UIInstructions generateApproachingErvStatusMessage()
Function to generate a carma_msgs::msg::UIInstructions message that describes whether there is curren...
std::vector< int > future_route_lanelet_ids_
bool is_maintaining_non_reduced_speed_
ApproachingEmergencyVehicleState getState() const
Returns the current state.
void event(ApproachingEmergencyVehicleEvent event)
Trigger event for the transition table.
virtual carma_wm::WorldModelConstPtr get_world_model() final
Method to return the default world model provided as a convience by this base class If this method or...
Class which implements the WorldModel interface. In addition this class provides write access to the ...
double getManeuverEndSpeed(const carma_planning_msgs::msg::Maneuver &mvr)
Anonymous function to extract maneuver end speed which cannot be obtained with GET_MANEUVER_PROPERY c...
constexpr double METERS_PER_SEC_TO_MILES_PER_HOUR
@ APPROACHING_ERV_IN_PATH
@ APPROACHING_ERV_NOT_IN_PATH
@ MOVING_OVER_FOR_APPROACHING_ERV
auto to_string(const UtmZone &zone) -> std::string
std::shared_ptr< lanelet::routing::Route > LaneletRoutePtr
Stuct containing the algorithm configuration values for approaching_emergency_vehicle_plugin.
double warning_broadcast_frequency
double vehicle_acceleration_limit
double min_lane_following_duration_before_lane_change
std::string lane_following_plugin
double bsm_processing_frequency
int max_warning_broadcasts
double default_speed_limit
std::string lane_change_plugin
double buffer_distance_before_stopping
double finished_passing_threshold
double approaching_threshold
double stopping_accel_limit_multiplier
double minimum_reduced_speed_limit
double minimal_plan_duration
std::string stop_and_wait_plugin
double approaching_erv_status_publication_frequency
double speed_limit_reduction_during_passing
double reduced_speed_buffer
double route_end_point_buffer
double timeout_check_frequency
Convenience struct for storing the parameters of an upcoming lane change to ensure that the same para...
bool is_right_lane_change
lanelet::ConstLanelet starting_lanelet
lanelet::ConstLanelet ending_lanelet