18#include <unordered_set>
24 namespace std_ph = std::placeholders;
34 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Updating maneuver starting_lane_id to " << start_id);
37 case carma_planning_msgs::msg::Maneuver::LANE_CHANGE:
38 mvr.lane_change_maneuver.starting_lane_id =
std::to_string(start_id);
40 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_STRAIGHT:
41 mvr.intersection_transit_straight_maneuver.starting_lane_id =
std::to_string(start_id);
43 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_LEFT_TURN:
44 mvr.intersection_transit_left_turn_maneuver.starting_lane_id =
std::to_string(start_id);
46 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_RIGHT_TURN:
47 mvr.intersection_transit_right_turn_maneuver.starting_lane_id =
std::to_string(start_id);
49 case carma_planning_msgs::msg::Maneuver::STOP_AND_WAIT:
50 mvr.stop_and_wait_maneuver.starting_lane_id =
std::to_string(start_id);
53 throw std::invalid_argument(
"Maneuver type does not have starting and ending lane ids");
63 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Updating maneuver ending_lane_id to " << end_id);
66 case carma_planning_msgs::msg::Maneuver::LANE_CHANGE:
69 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_STRAIGHT:
70 mvr.intersection_transit_straight_maneuver.ending_lane_id =
std::to_string(end_id);
72 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_LEFT_TURN:
73 mvr.intersection_transit_left_turn_maneuver.ending_lane_id =
std::to_string(end_id);
75 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_RIGHT_TURN:
76 mvr.intersection_transit_right_turn_maneuver.ending_lane_id =
std::to_string(end_id);
78 case carma_planning_msgs::msg::Maneuver::STOP_AND_WAIT:
79 mvr.stop_and_wait_maneuver.ending_lane_id =
std::to_string(end_id);
82 throw std::invalid_argument(
"Maneuver type does not have starting and ending lane ids");
93 case carma_planning_msgs::msg::Maneuver::LANE_CHANGE:
94 return mvr.lane_change_maneuver.starting_lane_id;
95 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_STRAIGHT:
96 return mvr.intersection_transit_straight_maneuver.starting_lane_id;
97 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_LEFT_TURN:
98 return mvr.intersection_transit_left_turn_maneuver.starting_lane_id;
99 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_RIGHT_TURN:
100 return mvr.intersection_transit_right_turn_maneuver.starting_lane_id;
101 case carma_planning_msgs::msg::Maneuver::STOP_AND_WAIT:
102 return mvr.stop_and_wait_maneuver.starting_lane_id;
104 throw std::invalid_argument(
"Maneuver type does not have starting and ending lane ids");
115 case carma_planning_msgs::msg::Maneuver::LANE_CHANGE:
116 return mvr.lane_change_maneuver.ending_lane_id;
117 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_STRAIGHT:
118 return mvr.intersection_transit_straight_maneuver.ending_lane_id;
119 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_LEFT_TURN:
120 return mvr.intersection_transit_left_turn_maneuver.ending_lane_id;
121 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_RIGHT_TURN:
122 return mvr.intersection_transit_right_turn_maneuver.ending_lane_id;
123 case carma_planning_msgs::msg::Maneuver::STOP_AND_WAIT:
124 return mvr.stop_and_wait_maneuver.ending_lane_id;
126 throw std::invalid_argument(
"Maneuver type does not have starting and ending lane ids");
133 tf2_buffer_(std::make_shared<tf2_ros::Buffer>(this->get_clock())),
134 wml_(this->get_node_base_interface(), this->get_node_logging_interface(),
135 this->get_node_topics_interface(), this->get_node_parameters_interface())
164 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Done loading parameters: " <<
config_);
167 traj_pub_ = create_publisher<carma_planning_msgs::msg::TrajectoryPlan>(
"plan_trajectory", 5);
173 twist_sub_ = create_subscription<geometry_msgs::msg::TwistStamped>(
"current_velocity", 5,
174 [
this](geometry_msgs::msg::TwistStamped::UniquePtr twist) {this->
latest_twist_ = *twist;});
180 return CallbackReturn::SUCCESS;
189 return CallbackReturn::SUCCESS;
199 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Received request to delegate plan ID " << std::string(plan->maneuver_plan_id));
201 auto copy_plan = *plan;
206 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Received plan with " <<
latest_maneuver_plan_.maneuvers.size() <<
" maneuvers");
214 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Received empty plan, no maneuvers found in plan ID " << std::string(plan->maneuver_plan_id));
221 double current_downtrack =
wm_->routeTrackPos(current_loc).downtrack;
226 if(maneuver.type == carma_planning_msgs::msg::Maneuver::LANE_CHANGE){
227 if(current_downtrack >= maneuver.lane_change_maneuver.start_dist){
262 lane_change_information.
starting_downtrack = lane_change_maneuver.lane_change_maneuver.start_dist;
265 lanelet::ConstLanelet starting_lanelet =
wm_->getMap()->laneletLayer.get(std::stoi(lane_change_maneuver.lane_change_maneuver.starting_lane_id));
266 lanelet::ConstLanelet ending_lanelet =
wm_->getMap()->laneletLayer.get(std::stoi(lane_change_maneuver.lane_change_maneuver.ending_lane_id));
277 boost::optional<bool> is_right_lane_change;
279 if(starting_lanelet.leftBound() == ending_lanelet.rightBound()){
280 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Lanelet " <<
std::to_string(starting_lanelet.id()) <<
" shares left boundary with " <<
std::to_string(ending_lanelet.id()));
281 is_right_lane_change =
false;
283 else if(starting_lanelet.rightBound() == ending_lanelet.leftBound()){
284 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Lanelet " <<
std::to_string(starting_lanelet.id()) <<
" shares right boundary with " <<
std::to_string(ending_lanelet.id()));
285 is_right_lane_change =
true;
289 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Searching for shared boundary with starting lanechange lanelet " <<
std::to_string(starting_lanelet.id()) <<
" and ending lanelet " <<
std::to_string(ending_lanelet.id()));
290 lanelet::ConstLanelet current_lanelet = starting_lanelet;
291 std::unordered_set<lanelet::Id> visited{current_lanelet.id()};
293 while(!is_right_lane_change){
295 auto following_lanelets =
wm_->getMapRoutingGraph()->following(current_lanelet,
false);
296 bool no_successor = following_lanelets.empty();
297 lanelet::ConstLanelet candidate_lanelet = no_successor ? current_lanelet : following_lanelets.front();
298 bool loop_detected = !no_successor && visited.count(candidate_lanelet.id()) > 0;
302 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"No following lanelets from lanelet " << current_lanelet.id()
303 <<
" reachable without a lane change (possibly closed or missing from the map); "
304 <<
"falling back to a geometric left/right estimate for lane change from "
305 << starting_lanelet.id() <<
" to " << ending_lanelet.id());
310 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Detected a routing loop while searching for a shared boundary between lanelet "
311 << starting_lanelet.id() <<
" and " << ending_lanelet.id() <<
"; falling back to a geometric left/right estimate");
314 if(no_successor || loop_detected)
319 current_lanelet = candidate_lanelet;
320 visited.insert(current_lanelet.id());
322 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Now checking for shared lane boundary with lanelet " <<
std::to_string(current_lanelet.id()) <<
" and ending lanelet " <<
std::to_string(ending_lanelet.id()));
323 if(current_lanelet.leftBound() == ending_lanelet.rightBound()){
324 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Lanelet " <<
std::to_string(current_lanelet.id()) <<
" shares left boundary with " <<
std::to_string(ending_lanelet.id()));
325 is_right_lane_change =
false;
327 else if(current_lanelet.rightBound() == ending_lanelet.leftBound()){
328 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Lanelet " <<
std::to_string(current_lanelet.id()) <<
" shares right boundary with " <<
std::to_string(ending_lanelet.id()));
329 is_right_lane_change =
true;
334 if(!is_right_lane_change)
340 lanelet::BasicLineString2d starting_centerline = starting_lanelet.centerline2d().basicLineString();
341 lanelet::BasicPoint2d start_pt = starting_centerline.front();
342 lanelet::BasicPoint2d heading_vec = starting_centerline.back() - start_pt;
343 lanelet::BasicPoint2d to_target = ending_lanelet.centerline2d().basicLineString().front() - start_pt;
344 double cross = heading_vec.x() * to_target.y() - heading_vec.y() * to_target.x();
346 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Could not find a shared lane boundary between starting lanelet "
347 << starting_lanelet.id() <<
" and ending lanelet " << ending_lanelet.id()
348 <<
"; estimating lane change direction geometrically instead.");
350 is_right_lane_change = (cross < 0.0);
354 return lane_change_information;
359 carma_planning_msgs::msg::UpcomingLaneChangeStatus upcoming_lane_change_status;
362 if(upcoming_lane_change_information){
365 double current_downtrack =
wm_->routeTrackPos(current_loc).downtrack;
366 upcoming_lane_change_status.downtrack_until_lanechange = std::max(0.0, upcoming_lane_change_information.get().starting_downtrack - current_downtrack);
369 if(upcoming_lane_change_information.get().is_right_lane_change){
370 upcoming_lane_change_status.lane_change = carma_planning_msgs::msg::UpcomingLaneChangeStatus::RIGHT;
373 upcoming_lane_change_status.lane_change = carma_planning_msgs::msg::UpcomingLaneChangeStatus::LEFT;
377 upcoming_lane_change_status.lane_change = carma_planning_msgs::msg::UpcomingLaneChangeStatus::NONE;
387 void PlanDelegator::publishTurnSignalCommand(
const boost::optional<LaneChangeInformation>& current_lane_change_information,
const carma_planning_msgs::msg::UpcomingLaneChangeStatus& upcoming_lane_change_status)
391 autoware_msgs::msg::LampCmd turn_signal_command;
394 if(current_lane_change_information){
396 if(current_lane_change_information.get().is_right_lane_change){
397 turn_signal_command.r = 1;
400 turn_signal_command.l = 1;
404 else if(upcoming_lane_change_status.lane_change != carma_planning_msgs::msg::UpcomingLaneChangeStatus::NONE){
407 if(upcoming_lane_change_status.lane_change == carma_planning_msgs::msg::UpcomingLaneChangeStatus::RIGHT){
408 turn_signal_command.r = 1;
411 turn_signal_command.l = 1;
427 if(planner_name.size() == 0)
429 throw std::invalid_argument(
"Invalid trajectory planner name because it has zero length!");
433 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Discovered new trajectory planner: " << planner_name);
444 return !maneuver_plan.maneuvers.empty();
450 return !(trajectory_plan.trajectory_points.size() < 2);
457 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"current time:" <<
std::to_string(now().seconds()));
458 bool isexpired = rclcpp::Time(
GET_MANEUVER_PROPERTY(maneuver, end_time), get_clock()->get_clock_type()) <= current_time;
459 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"isexpired:" << isexpired);
464 std::shared_ptr<carma_planning_msgs::srv::PlanTrajectory::Request>
466 const carma_planning_msgs::msg::TrajectoryPlan& latest_trajectory_plan,
467 const carma_planning_msgs::msg::ManeuverPlan& locked_maneuver_plan,
468 const uint16_t& current_maneuver_index)
const
470 auto plan_req = std::make_shared<carma_planning_msgs::srv::PlanTrajectory::Request>();
471 plan_req->maneuver_plan = locked_maneuver_plan;
474 if(latest_trajectory_plan.trajectory_points.empty())
477 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"latest_pose_.header.stamp: " <<
std::to_string(rclcpp::Time(
latest_pose_.header.stamp).seconds()));
478 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"plan_req->header.stamp: " <<
std::to_string(rclcpp::Time(plan_req->header.stamp).seconds()));
480 plan_req->vehicle_state.longitudinal_vel =
latest_twist_.twist.linear.x;
481 plan_req->vehicle_state.x_pos_global =
latest_pose_.pose.position.x;
482 plan_req->vehicle_state.y_pos_global =
latest_pose_.pose.position.y;
483 double roll, pitch, yaw;
485 plan_req->vehicle_state.orientation = yaw;
486 plan_req->maneuver_index_to_plan = current_maneuver_index;
491 carma_planning_msgs::msg::TrajectoryPlanPoint last_point = latest_trajectory_plan.trajectory_points.back();
492 carma_planning_msgs::msg::TrajectoryPlanPoint second_last_point = *(latest_trajectory_plan.trajectory_points.rbegin() + 1);
493 plan_req->vehicle_state.x_pos_global = last_point.x;
494 plan_req->vehicle_state.y_pos_global = last_point.y;
495 auto distance_diff = std::sqrt(std::pow(last_point.x - second_last_point.x, 2) + std::pow(last_point.y - second_last_point.y, 2));
496 rclcpp::Duration time_diff = rclcpp::Time(last_point.target_time) - rclcpp::Time(second_last_point.target_time);
497 auto time_diff_sec = time_diff.seconds();
498 plan_req->maneuver_index_to_plan = current_maneuver_index;
500 plan_req->header.stamp = latest_trajectory_plan.trajectory_points.back().target_time;
501 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"plan_req->header.stamp: " <<
std::to_string(rclcpp::Time(plan_req->header.stamp).seconds()));
503 plan_req->vehicle_state.longitudinal_vel = distance_diff / time_diff_sec;
511 rclcpp::Duration time_diff = rclcpp::Time(plan.trajectory_points.back().target_time) - rclcpp::Time(plan.trajectory_points.front().target_time);
512 return time_diff.seconds() >= config_.max_trajectory_duration;
519 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Map is not set yet");
526 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Changing maneuver distances for planner: " <<
GET_MANEUVER_PROPERTY(maneuver, parameters.planning_tactical_plugin));
528 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"original_start_dist:" << original_start_dist);
529 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"adjusted_start_dist:" << adjusted_start_dist);
531 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"original_end_dist:" << original_end_dist);
532 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"adjusted_end_dist:" << adjusted_end_dist);
538 if(maneuver.type == carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING && !maneuver.lane_following_maneuver.lane_ids.empty()){
542 lanelet::Id original_starting_lanelet_id = std::stoi(maneuver.lane_following_maneuver.lane_ids.front());
543 lanelet::ConstLanelet original_starting_lanelet =
wm_->getMap()->laneletLayer.get(original_starting_lanelet_id);
546 lanelet::BasicPoint2d original_starting_lanelet_centerline_start_point = lanelet::utils::to2D(original_starting_lanelet.centerline()).front();
547 double original_starting_lanelet_centerline_start_point_dt =
wm_->routeTrackPos(original_starting_lanelet_centerline_start_point).downtrack;
549 if(adjusted_start_dist < original_starting_lanelet_centerline_start_point_dt){
551 auto previous_lanelets =
wm_->getMapRoutingGraph()->previous(original_starting_lanelet,
false);
553 if(!previous_lanelets.empty()){
555 auto llt_on_route_optional =
wm_->getFirstLaneletOnShortestPath(previous_lanelets);
557 lanelet::ConstLanelet previous_lanelet_to_add;
559 if (llt_on_route_optional){
560 previous_lanelet_to_add = llt_on_route_optional.value();
563 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"When adjusting maneuver for lane follow, no previous lanelet found on the shortest path for lanelet "
564 << original_starting_lanelet.id() <<
". Picking arbitrary lanelet: " << previous_lanelets[0].id() <<
", instead");
565 previous_lanelet_to_add = previous_lanelets[0];
569 maneuver.lane_following_maneuver.lane_ids.insert(maneuver.lane_following_maneuver.lane_ids.begin(),
std::to_string(previous_lanelet_to_add.id()));
571 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Inserted lanelet " <<
std::to_string(previous_lanelet_to_add.id()) <<
" to beginning of maneuver.");
574 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"No previous lanelet was found for lanelet " << original_starting_lanelet.id());
579 lanelet::Id original_ending_lanelet_id = std::stoi(maneuver.lane_following_maneuver.lane_ids.back());
580 lanelet::ConstLanelet original_ending_lanelet =
wm_->getMap()->laneletLayer.get(original_ending_lanelet_id);
583 lanelet::BasicPoint2d original_ending_lanelet_centerline_start_point = lanelet::utils::to2D(original_ending_lanelet.centerline()).front();
584 double original_ending_lanelet_centerline_start_point_dt =
wm_->routeTrackPos(original_ending_lanelet_centerline_start_point).downtrack;
586 if(adjusted_end_dist < original_ending_lanelet_centerline_start_point_dt){
587 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Original ending lanelet " << original_ending_lanelet.id() <<
" removed from lane_ids since the updated maneuver no longer crosses it");
590 maneuver.lane_following_maneuver.lane_ids.pop_back();
593 else if (maneuver.type != carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING){
598 lanelet::ConstLanelet original_starting_lanelet =
wm_->getMap()->laneletLayer.get(original_starting_lanelet_id);
601 lanelet::BasicPoint2d original_starting_lanelet_centerline_start_point = lanelet::utils::to2D(original_starting_lanelet.centerline()).front();
602 double original_starting_lanelet_centerline_start_point_dt =
wm_->routeTrackPos(original_starting_lanelet_centerline_start_point).downtrack;
604 if(adjusted_start_dist < original_starting_lanelet_centerline_start_point_dt){
605 auto previous_lanelets =
wm_->getMapRoutingGraph()->previous(original_starting_lanelet,
false);
606 if(!previous_lanelets.empty()){
607 auto llt_on_route_optional =
wm_->getFirstLaneletOnShortestPath(previous_lanelets);
608 lanelet::ConstLanelet previous_lanelet_to_add;
610 if (llt_on_route_optional){
611 previous_lanelet_to_add = llt_on_route_optional.value();
614 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"When adjusting non-lane follow maneuver, no previous lanelet found on the shortest path for lanelet "
615 << original_starting_lanelet.id() <<
". Picking arbitrary lanelet: " << previous_lanelets[0].id() <<
", instead");
616 previous_lanelet_to_add = previous_lanelets[0];
621 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"No previous lanelet was found for lanelet " << original_starting_lanelet.id());
627 lanelet::ConstLanelet original_ending_lanelet =
wm_->getMap()->laneletLayer.get(original_ending_lanelet_id);
630 lanelet::BasicPoint2d original_ending_lanelet_centerline_start_point = lanelet::utils::to2D(original_ending_lanelet.centerline()).front();
631 double original_ending_lanelet_centerline_start_point_dt =
wm_->routeTrackPos(original_ending_lanelet_centerline_start_point).downtrack;
633 if(adjusted_end_dist < original_ending_lanelet_centerline_start_point_dt){
634 auto previous_lanelets =
wm_->getMapRoutingGraph()->previous(original_ending_lanelet,
false);
636 if(!previous_lanelets.empty()){
640 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"No previous lanelet was found for lanelet " << original_starting_lanelet.id());
648 carma_planning_msgs::msg::TrajectoryPlan latest_trajectory_plan;
649 bool full_plan_generation_failed =
false;
652 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Guidance is not engaged. Plan delegator will not plan trajectory.");
653 return latest_trajectory_plan;
659 bool first_trajectory_plan =
true;
662 uint16_t current_maneuver_index = 0;
665 while(current_maneuver_index < locked_maneuver_plan.maneuvers.size())
667 auto& maneuver = locked_maneuver_plan.maneuvers[current_maneuver_index];
672 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Dropping expired maneuver: " <<
GET_MANEUVER_PROPERTY(maneuver, parameters.maneuver_id));
674 ++current_maneuver_index;
678 double current_downtrack =
wm_->routeTrackPos(current_loc).downtrack;
679 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"current_downtrack" << current_downtrack);
681 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"maneuver_end_dist" << maneuver_end_dist);
684 if (current_downtrack > maneuver_end_dist)
686 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Dropping passed maneuver: " <<
GET_MANEUVER_PROPERTY(maneuver, parameters.maneuver_id));
688 ++current_maneuver_index;
697 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Current planner: " << maneuver_planner);
701 latest_trajectory_plan, locked_maneuver_plan, current_maneuver_index);
703 auto future_response = client->async_send_request(plan_req);
707 if (future_status != std::future_status::ready)
709 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Unsuccessful service call to trajectory planner:" << maneuver_planner <<
" for plan ID " << std::string(locked_maneuver_plan.maneuver_plan_id));
711 full_plan_generation_failed =
true;
716 auto plan_response = future_response.get();
720 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
721 "Found invalid trajectory with less than 2 trajectory "
722 <<
"points for maneuver_plan_id: "
723 << std::string(locked_maneuver_plan.maneuver_plan_id));
724 full_plan_generation_failed =
true;
728 if(latest_trajectory_plan.trajectory_points.size() != 0 &&
729 latest_trajectory_plan.trajectory_points.back().target_time == plan_response->trajectory_plan.trajectory_points.front().target_time)
731 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Removing duplicate point for planner: " << maneuver_planner);
732 plan_response->trajectory_plan.trajectory_points.erase(plan_response->trajectory_plan.trajectory_points.begin());
733 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"plan_response->trajectory_plan size: " << plan_response->trajectory_plan.trajectory_points.size());
735 latest_trajectory_plan.trajectory_points.insert(latest_trajectory_plan.trajectory_points.end(),
736 plan_response->trajectory_plan.trajectory_points.begin(),
737 plan_response->trajectory_plan.trajectory_points.end());
738 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"new latest_trajectory_plan size: " << latest_trajectory_plan.trajectory_points.size());
741 if(first_trajectory_plan ==
true)
743 latest_trajectory_plan.initial_longitudinal_velocity = plan_response->trajectory_plan.initial_longitudinal_velocity;
744 first_trajectory_plan =
false;
749 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"plan_delegator"),
"Plan Trajectory completed for " << std::string(locked_maneuver_plan.maneuver_plan_id));
755 if(plan_response->related_maneuvers.size() > 0)
757 current_maneuver_index = plan_response->related_maneuvers.back() + 1;
761 if (full_plan_generation_failed)
763 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
764 "Plan_delegator's current run wasn't fully able to generate trajectory!");
766 carma_planning_msgs::msg::TrajectoryPlan empty_plan;
770 return latest_trajectory_plan;
780 carma_planning_msgs::msg::TrajectoryPlan trajectory_plan =
planTrajectory();
785 trajectory_plan.header.stamp = get_clock()->now();
793 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
794 "Guidance is engaged, but new planned trajectory has less than 2 points. " <<
795 "It will not be published! Consecutive failure count: "
803 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
804 "Instead, last available trajectory is published with outdated timestamp of:"
814 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"),
815 "Instead, tried publishing last available trajectory, but it's not available!");
819 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
"plan_delegator"),
820 "No valid trajectory is available to publish! "
821 "Please check the planner plugins and their configurations.");
822 throw std::runtime_error(
"No valid trajectory is available to publish!");
833 geometry_msgs::msg::TransformStamped tf =
tf2_buffer_->lookupTransform(
"base_link",
"vehicle_front", rclcpp::Time(0), rclcpp::Duration(20.0, 0));
835 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"plan_delegator"),
"length_to_front_bumper_: " <<
length_to_front_bumper_);
838 catch (
const tf2::TransformException &ex)
840 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"plan_delegator"), ex.what());
847#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.
WorldModelConstPtr getWorldModel()
Returns a pointer to an intialized world model instance.
void onTrajPlanTick()
Callback function for triggering trajectory planning.
carma_ros2_utils::SubPtr< carma_planning_msgs::msg::GuidanceState > guidance_state_sub_
bool received_maneuver_plan_
carma_planning_msgs::msg::TrajectoryPlan planTrajectory()
Plan trajectory based on latest maneuver plan via ROS service call to plugins.
LaneChangeInformation getLaneChangeInformation(const carma_planning_msgs::msg::Maneuver &lane_change_maneuver)
Function for generating a LaneChangeInformation object from a provided lane change maneuver.
carma_ros2_utils::ClientPtr< carma_planning_msgs::srv::PlanTrajectory > getPlannerClientByName(const std::string &planner_name)
Get PlanTrajectory service client by plugin name and create new PlanTrajectory service client if spec...
void poseCallback(geometry_msgs::msg::PoseStamped::UniquePtr pose_msg)
Callback function for vehicle pose subscriber. Updates latest_pose_ and makes calls to publishUpcomin...
int consecutive_traj_gen_failure_num_
carma_wm::WorldModelConstPtr wm_
carma_ros2_utils::SubPtr< geometry_msgs::msg::TwistStamped > twist_sub_
std::shared_ptr< carma_planning_msgs::srv::PlanTrajectory::Request > composePlanTrajectoryRequest(const carma_planning_msgs::msg::TrajectoryPlan &latest_trajectory_plan, const carma_planning_msgs::msg::ManeuverPlan &locked_maneuver_plan, const uint16_t ¤t_maneuver_index) const
Generate new PlanTrajecory service request based on current planning progress.
carma_ros2_utils::CallbackReturn handle_on_activate(const rclcpp_lifecycle::State &)
boost::optional< LaneChangeInformation > upcoming_lane_change_information_
carma_ros2_utils::PubPtr< carma_planning_msgs::msg::UpcomingLaneChangeStatus > upcoming_lane_change_status_pub_
carma_planning_msgs::msg::UpcomingLaneChangeStatus upcoming_lane_change_status_
bool isTrajectoryValid(const carma_planning_msgs::msg::TrajectoryPlan &trajectory_plan) const noexcept
Example if a trajectory plan contains at least two trajectory points.
carma_ros2_utils::CallbackReturn handle_on_configure(const rclcpp_lifecycle::State &)
bool isManeuverExpired(const carma_planning_msgs::msg::Maneuver &maneuver, rclcpp::Time current_time) const
Example if a maneuver end time has passed current system time.
void guidanceStateCallback(carma_planning_msgs::msg::GuidanceState::UniquePtr plan)
Callback function of guidance state subscriber.
void updateManeuverParameters(carma_planning_msgs::msg::Maneuver &maneuver)
Update the starting downtrack, ending downtrack, and maneuver-specific Lanelet ID parameters associat...
rclcpp::TimerBase::SharedPtr traj_timer_
std::shared_ptr< tf2_ros::TransformListener > tf2_listener_
carma_ros2_utils::SubPtr< carma_planning_msgs::msg::ManeuverPlan > plan_sub_
bool isTrajectoryLongEnough(const carma_planning_msgs::msg::TrajectoryPlan &plan) const noexcept
Example if a trajectory plan is longer than configured time thresheld.
carma_planning_msgs::msg::ManeuverPlan latest_maneuver_plan_
carma_ros2_utils::PubPtr< carma_planning_msgs::msg::TrajectoryPlan > traj_pub_
carma_ros2_utils::PubPtr< autoware_msgs::msg::LampCmd > turn_signal_command_pub_
boost::optional< LaneChangeInformation > current_lane_change_information_
std::unordered_map< std::string, carma_ros2_utils::ClientPtr< carma_planning_msgs::srv::PlanTrajectory > > trajectory_planners_
bool isManeuverPlanValid(const carma_planning_msgs::msg::ManeuverPlan &maneuver_plan) const noexcept
Example if a maneuver plan contains at least one maneuver.
carma_ros2_utils::SubPtr< geometry_msgs::msg::PoseStamped > pose_sub_
geometry_msgs::msg::TwistStamped latest_twist_
double length_to_front_bumper_
std::optional< carma_planning_msgs::msg::TrajectoryPlan > last_successful_traj_
rclcpp::CallbackGroup::SharedPtr timer_callback_group_
void lookupFrontBumperTransform()
Lookup transfrom from front bumper to base link.
geometry_msgs::msg::PoseStamped latest_pose_
PlanDelegator(const rclcpp::NodeOptions &)
PlanDelegator constructor.
void maneuverPlanCallback(carma_planning_msgs::msg::ManeuverPlan::UniquePtr plan)
Callback function of maneuver plan subscriber.
std::shared_ptr< tf2_ros::Buffer > tf2_buffer_
autoware_msgs::msg::LampCmd latest_turn_signal_command_
void publishTurnSignalCommand(const boost::optional< LaneChangeInformation > ¤t_lane_change_information, const carma_planning_msgs::msg::UpcomingLaneChangeStatus &upcoming_lane_change_status)
Function for processing an optional LaneChangeInformation object pertaining to the currently-occurrin...
void publishUpcomingLaneChangeStatus(const boost::optional< LaneChangeInformation > &upcoming_lane_change_information)
Function for processing an optional LaneChangeInformation object pertaining to an upcoming lane chang...
carma_wm::WMListener wml_
auto to_string(const UtmZone &zone) -> std::string
void rpyFromQuaternion(const tf2::Quaternion &q, double &roll, double &pitch, double &yaw)
Extract extrinsic roll-pitch-yaw from quaternion.
std::string getManeuverEndingLaneletId(carma_planning_msgs::msg::Maneuver mvr)
Anonymous function to get the ending lanelet id for all maneuver types except lane following....
void setManeuverEndingLaneletId(carma_planning_msgs::msg::Maneuver &mvr, lanelet::Id end_id)
Anonymous function to set the ending_lane_id for all maneuver types except lane following....
std::string getManeuverStartingLaneletId(carma_planning_msgs::msg::Maneuver mvr)
Anonymous function to get the starting lanelet id for all maneuver types except lane following....
void setManeuverStartingLaneletId(carma_planning_msgs::msg::Maneuver &mvr, lanelet::Id start_id)
Anonymous function to set the starting_lane_id for all maneuver types except lane following....
#define SET_MANEUVER_PROPERTY(mvr, property, value)
double trajectory_planning_rate
std::string planning_topic_suffix
int max_traj_generation_reattempt
std::string planning_topic_prefix
int tactical_plugin_service_call_timeout
double duration_to_signal_before_lane_change
double max_trajectory_duration