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.
light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin Class Reference

Class containing primary business logic for the Light Controlled Intersection Tactical Plugin. More...

#include <light_controlled_intersection_tactical_plugin.hpp>

Collaboration diagram for light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin:
Collaboration graph

Public Member Functions

 LightControlledIntersectionTacticalPlugin (carma_wm::WorldModelConstPtr wm, const Config &config, const DebugPublisher &debug_publisher, const std::string &plugin_name, std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > nh)
 LightControlledIntersectionTacticalPlugin constructor. More...
 
void planTrajectoryCB (carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req, carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp)
 Function to process the light controlled intersection tactical plugin service call for trajectory planning. More...
 
void setConfig (const Config &config)
 Setter function to set a new config for this object. More...
 

Private Member Functions

void applyTrajectorySmoothingAlgorithm (const carma_wm::WorldModelConstPtr &wm, std::vector< PointSpeedPair > &points_and_target_speeds, double start_dist, double remaining_dist, double starting_speed, double departure_speed, TrajectoryParams tsp)
 Creates a speed profile according to case one or two of the light controlled intersection, where the vehicle accelerates (then cruises if needed) and decelerates into the intersection. More...
 
void applyOptimizedTargetSpeedProfile (const carma_planning_msgs::msg::Maneuver &maneuver, const double starting_speed, std::vector< PointSpeedPair > &points_and_target_speeds)
 Apply optimized target speeds to the trajectory determined for fixed-time and actuated signals. Based on TSMO USE CASE 2. Chapter 2. Trajectory Smoothing. More...
 
std::vector< PointSpeedPaircreateGeometryProfile (const std::vector< carma_planning_msgs::msg::Maneuver > &maneuvers, double max_starting_downtrack, const carma_wm::WorldModelConstPtr &wm, carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, const carma_planning_msgs::msg::VehicleState &state, const GeneralTrajConfig &general_config, const DetailedTrajConfig &detailed_config)
 Creates geometry profile to return a point speed pair struct for INTERSECTION_TRANSIT maneuver types (by converting it to LANE_FOLLOW) More...
 
double findSpeedLimit (const lanelet::ConstLanelet &llt, const carma_wm::WorldModelConstPtr &wm) const
 Given a Lanelet, find its associated Speed Limit. More...
 
void logDebugInfoAboutPreviousTrajectory ()
 Logs debug information about the previously planned trajectory. More...
 
bool shouldUseLastTrajectory (TSCase new_case, bool is_new_case_successful, const rclcpp::Time &current_time)
 Determines whether the last trajectory should be reused based on the planning case. Should use last case if 1) last traj is valid AND last case is the same as new case, OR 2) last traj is valid AND within certain evaluation zone before the intersection where the new case is not successful but last case is. More...
 
void planTrajectorySmoothing (carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req, carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp)
 Smooths the trajectory as part of the trajectory planning process. More...
 
carma_planning_msgs::msg::TrajectoryPlan generateNewTrajectory (const std::vector< carma_planning_msgs::msg::Maneuver > &maneuver_plan, const carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr &req, std::vector< double > &final_speeds)
 Generates a new trajectory plan based on the provided maneuver plan and request. NOTE: This function plans for the entire maneuver input and doesn't time bound it. More...
 
bool isLastTrajectoryValid (const rclcpp::Time &current_time, double min_remaining_time_seconds=0.0) const
 Checks if the last trajectory plan remains valid based on the current time. More...
 
 FRIEND_TEST (LCITacticalPluginTest, applyTrajectorySmoothingAlgorithm)
 
 FRIEND_TEST (LCITacticalPluginTest, applyOptimizedTargetSpeedProfile)
 
 FRIEND_TEST (LCITacticalPluginTest, planTrajectorySmoothing)
 
 FRIEND_TEST (LCITacticalPluginTest, createGeometryProfile)
 
 FRIEND_TEST (LCITacticalPluginTest, planTrajectoryCB)
 
 FRIEND_TEST (LCITacticalPluginTest, setConfig)
 

Private Attributes

carma_wm::WorldModelConstPtr wm_
 
Config config_
 
std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > nh_
 
uint32_t street_msg_timestamp_ = 0.0
 
uint32_t scheduled_stop_time_ = 0.0
 
uint32_t scheduled_enter_time_ = 0.0
 
uint32_t scheduled_depart_time_ = 0.0
 
uint32_t scheduled_latest_depart_time_ = 0.0
 
bool is_allowed_int_ = false
 
double speed_limit_ = 11.176
 
boost::optional< TSCaselast_case_
 
boost::optional< bool > is_last_case_successful_
 
carma_planning_msgs::msg::TrajectoryPlan last_trajectory_time_unbound_
 
const std::string LCI_TACTICAL_LOGGER = "light_controlled_intersection_tactical_plugin"
 
carma_planning_msgs::msg::VehicleState ending_state_before_buffer_
 
rclcpp::Time latest_traj_request_header_stamp_
 
double epsilon_ = 0.001
 
double current_downtrack_ = 0.0
 
double last_successful_ending_downtrack_
 
double last_successful_scheduled_entry_time_
 
std::string plugin_name_
 
DebugPublisher debug_publisher_
 
carma_debug_ros2_msgs::msg::TrajectoryCurvatureSpeeds debug_msg_
 
std::vector< double > last_speeds_time_unbound_
 
std::string light_controlled_intersection_strategy_ = "Carma/signalized_intersection"
 

Detailed Description

Class containing primary business logic for the Light Controlled Intersection Tactical Plugin.

Definition at line 105 of file light_controlled_intersection_tactical_plugin.hpp.

Constructor & Destructor Documentation

◆ LightControlledIntersectionTacticalPlugin()

light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::LightControlledIntersectionTacticalPlugin ( carma_wm::WorldModelConstPtr  wm,
const Config config,
const DebugPublisher debug_publisher,
const std::string &  plugin_name,
std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode >  nh 
)

LightControlledIntersectionTacticalPlugin constructor.

Definition at line 24 of file light_controlled_intersection_tactical_plugin.cpp.

References nh_, and basic_autonomy::set_logger().

Here is the call graph for this function:

Member Function Documentation

◆ applyOptimizedTargetSpeedProfile()

void light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::applyOptimizedTargetSpeedProfile ( const carma_planning_msgs::msg::Maneuver &  maneuver,
const double  starting_speed,
std::vector< PointSpeedPair > &  points_and_target_speeds 
)
private

Apply optimized target speeds to the trajectory determined for fixed-time and actuated signals. Based on TSMO USE CASE 2. Chapter 2. Trajectory Smoothing.

Parameters
maneuverManeuver associated that has starting downtrack and desired entry time
starting_speedStarting speed of the vehicle
pointsThe set of points with raw speed limits whose speed profile to be changed. These points must be in the same lane as the vehicle and must extend in front of it though it is fine if they also extend behind it.

Definition at line 509 of file light_controlled_intersection_tactical_plugin.cpp.

510 {
511 if(GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data).size() < 9 ||
512 GET_MANEUVER_PROPERTY(maneuver, parameters.int_valued_meta_data).size() < 2 ){
513 throw std::invalid_argument("There must be 9 float_valued_meta_data and 2 int_valued_meta_data to apply algorithm's parameters.");
514 }
515
516 TrajectoryParams tsp;
517
518 tsp.a1_ = GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data[0]);
519 tsp.v1_ = GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data[1]);
520 tsp.x1_ = GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data[2]);
521
522 tsp.a2_ = GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data[3]);
523 tsp.v2_ = GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data[4]);
524 tsp.x2_ = GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data[5]);
525
526 tsp.a3_ = GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data[6]);
527 tsp.v3_ = GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data[7]);
528 tsp.x3_ = GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data[8]);
529
530 double starting_downtrack = GET_MANEUVER_PROPERTY(maneuver, start_dist);
531 double ending_downtrack = GET_MANEUVER_PROPERTY(maneuver, end_dist);
532 double departure_speed = GET_MANEUVER_PROPERTY(maneuver, end_speed);
533 double scheduled_entry_time = rclcpp::Time(GET_MANEUVER_PROPERTY(maneuver, end_time)).seconds();
534 double entry_dist = ending_downtrack - starting_downtrack;
535
536 // change speed profile depending on algorithm case starting from maneuver start_dist
537 applyTrajectorySmoothingAlgorithm(wm_, points_and_target_speeds, starting_downtrack,
538 entry_dist, starting_speed, departure_speed, tsp);
539 }
#define GET_MANEUVER_PROPERTY(mvr, property)
Macro definition to enable easier access to fields shared across the maneuver types.
void applyTrajectorySmoothingAlgorithm(const carma_wm::WorldModelConstPtr &wm, std::vector< PointSpeedPair > &points_and_target_speeds, double start_dist, double remaining_dist, double starting_speed, double departure_speed, TrajectoryParams tsp)
Creates a speed profile according to case one or two of the light controlled intersection,...

References light_controlled_intersection_tactical_plugin::TrajectoryParams::a1_, light_controlled_intersection_tactical_plugin::TrajectoryParams::a2_, light_controlled_intersection_tactical_plugin::TrajectoryParams::a3_, applyTrajectorySmoothingAlgorithm(), GET_MANEUVER_PROPERTY, light_controlled_intersection_tactical_plugin::TrajectoryParams::v1_, light_controlled_intersection_tactical_plugin::TrajectoryParams::v2_, light_controlled_intersection_tactical_plugin::TrajectoryParams::v3_, wm_, light_controlled_intersection_tactical_plugin::TrajectoryParams::x1_, light_controlled_intersection_tactical_plugin::TrajectoryParams::x2_, and light_controlled_intersection_tactical_plugin::TrajectoryParams::x3_.

Referenced by generateNewTrajectory().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ applyTrajectorySmoothingAlgorithm()

void light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::applyTrajectorySmoothingAlgorithm ( const carma_wm::WorldModelConstPtr wm,
std::vector< PointSpeedPair > &  points_and_target_speeds,
double  start_dist,
double  remaining_dist,
double  starting_speed,
double  departure_speed,
TrajectoryParams  tsp 
)
private

Creates a speed profile according to case one or two of the light controlled intersection, where the vehicle accelerates (then cruises if needed) and decelerates into the intersection.

Parameters
wmworld_model pointer
points_and_target_speedsof centerline points paired with speed limits whose speeds are to be modified:
start_diststarting downtrack of the maneuver to be planned (excluding buffer points) in m
remaining_distdistance for the maneuver to be planned (excluding buffer points) in m
starting_speedstarting speed at the start of the maneuver in m/s
departure_speedending speed of the maneuver a.k.a entry speed into the intersection m/s
tsptrajectory smoothing parameters NOTE: Cruising speed profile is applied (case 1) if speed before deceleration is higher than speed limit. Otherwise Case 2. NOTE: when applying the speed profile, the function ignores buffer points beyond start_dist and end_dist. Internally uses: config_.back_distance and speed_limit_

Definition at line 422 of file light_controlled_intersection_tactical_plugin.cpp.

424 {
425 if (points_and_target_speeds.empty())
426 {
427 throw std::invalid_argument("Point and target speed list is empty! Unable to apply case one speed profile...");
428 }
429
430 // Checking route geometry start against start_dist and adjust profile
431 double planning_downtrack_start = wm->routeTrackPos(points_and_target_speeds[0].point).downtrack; // this can include buffered points earlier than maneuver start_dist
432
433 //Check calculated total dist against maneuver limits
434 double total_distance_needed = remaining_dist;
435 double dist1 = tsp.x1_ - start_dist;
436 double dist2 = tsp.x2_ - start_dist;
437 double dist3 = tsp.x3_ - start_dist;
438
439 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER), "total_distance_needed: " << total_distance_needed << "\n" <<
440 "dist1: " << dist1 << "\n" <<
441 "dist2: " << dist2 << "\n" <<
442 "dist3: " << dist3);
443 double algo_min_speed = std::min({tsp.v1_,tsp.v2_,tsp.v3_});
444 double algo_max_speed = std::max({tsp.v1_,tsp.v2_,tsp.v3_});
445
446 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER), "found algo_minimum_speed: " << algo_min_speed << "\n" <<
447 "algo_max_speed: " << algo_max_speed);
448
449 double total_dist_planned = 0; //Starting dist for maneuver treated as 0.0
450
451 if (planning_downtrack_start < start_dist)
452 {
453 //Account for the buffer distance that is technically not part of this maneuver
454
455 total_dist_planned = planning_downtrack_start - start_dist;
456 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER), "buffered section is present. Adjusted total_dist_planned to: " << total_dist_planned);
457 }
458
459 double prev_speed = starting_speed;
460 auto prev_point = points_and_target_speeds.front();
461
462 for(auto& p : points_and_target_speeds)
463 {
464 double delta_d = lanelet::geometry::distance2d(prev_point.point, p.point);
465 total_dist_planned += delta_d;
466
467 //Apply the speed from algorithm at dist covered
468 //Kinematic: v_f = sqrt(v_o^2 + 2*a*d)
469 double speed_i;
470 if (total_dist_planned <= epsilon_)
471 {
472 //Keep target speed same for buffer distance portion
473 speed_i = starting_speed;
474 }
475 else if(total_dist_planned <= dist1 + epsilon_){
476 //First segment
477 speed_i = sqrt(pow(starting_speed, 2) + 2 * tsp.a1_ * total_dist_planned);
478 }
479 else if(total_dist_planned > dist1 && total_dist_planned <= dist2 + epsilon_){
480 //Second segment
481 speed_i = sqrt(std::max(pow(tsp.v1_, 2) + 2 * tsp.a2_ * (total_dist_planned - dist1), 0.0)); //std::max to ensure negative value is not sqrt
482 }
483 else if (total_dist_planned > dist2 && total_dist_planned <= dist3 + epsilon_)
484 {
485 //Third segment
486 speed_i = sqrt(std::max(pow(tsp.v2_, 2) + 2 * tsp.a3_ * (total_dist_planned - dist2), 0.0)); //std::max to ensure negative value is not sqrt
487 }
488 else
489 {
490 //buffer points that will be cut
491 speed_i = prev_speed;
492 }
493
494 if (isnan(speed_i))
495 {
496 speed_i = std::max(config_.minimum_speed, algo_min_speed);
497 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER), "Detected nan number from equations. Set to " << speed_i);
498 }
499
500 p.speed = std::max({speed_i, config_.minimum_speed, algo_min_speed});
501 p.speed = std::min({p.speed, speed_limit_, algo_max_speed});
502 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER), "Applied speed: " << p.speed << ", at dist: " << total_dist_planned);
503
504 prev_point = p;
505 prev_speed = p.speed;
506 }
507 }
rclcpp::Logger get_logger()
Return the module-level logger used by all basic_autonomy functions.
Definition: log.cpp:32

References light_controlled_intersection_tactical_plugin::TrajectoryParams::a1_, light_controlled_intersection_tactical_plugin::TrajectoryParams::a2_, light_controlled_intersection_tactical_plugin::TrajectoryParams::a3_, config_, epsilon_, basic_autonomy::get_logger(), LCI_TACTICAL_LOGGER, light_controlled_intersection_tactical_plugin::Config::minimum_speed, process_traj_logs::point, speed_limit_, light_controlled_intersection_tactical_plugin::TrajectoryParams::v1_, light_controlled_intersection_tactical_plugin::TrajectoryParams::v2_, light_controlled_intersection_tactical_plugin::TrajectoryParams::v3_, light_controlled_intersection_tactical_plugin::TrajectoryParams::x1_, light_controlled_intersection_tactical_plugin::TrajectoryParams::x2_, and light_controlled_intersection_tactical_plugin::TrajectoryParams::x3_.

Referenced by applyOptimizedTargetSpeedProfile().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ createGeometryProfile()

std::vector< PointSpeedPair > light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::createGeometryProfile ( const std::vector< carma_planning_msgs::msg::Maneuver > &  maneuvers,
double  max_starting_downtrack,
const carma_wm::WorldModelConstPtr wm,
carma_planning_msgs::msg::VehicleState &  ending_state_before_buffer,
const carma_planning_msgs::msg::VehicleState &  state,
const GeneralTrajConfig general_config,
const DetailedTrajConfig detailed_config 
)
private

Creates geometry profile to return a point speed pair struct for INTERSECTION_TRANSIT maneuver types (by converting it to LANE_FOLLOW)

Parameters
maneuversThe list of maneuvers to convert to geometry points and calculate associated raw speed limits
max_starting_downtrackThe maximum downtrack that is allowed for the first maneuver. This should be set to the vehicle position or earlier. If the first maneuver exceeds this then it's downtrack will be shifted to this value.
wmPointer to intialized world model for semantic map access
ending_state_before_bufferreference to Vehicle state, which is state before applying extra points for curvature calculation that are removed later
stateThe vehicle state at the time the function is called
general_configBasic autonomy struct defined to load general config parameters from tactical plugins
detailed_configBasic autonomy struct defined to load detailed config parameters from tactical plugins
Returns
A vector of point speed pair struct which contains geometry points as basicpoint::lanelet2d and speed as a double for the maneuver NOTE: This function is a slightly modified version of the same function in basic_autonomy library and currently only plans for the first maneuver

Definition at line 554 of file light_controlled_intersection_tactical_plugin.cpp.

557 {
558 std::vector<PointSpeedPair> points_and_target_speeds;
559
560 bool first = true;
561 std::unordered_set<lanelet::Id> visited_lanelets;
562 std::vector<carma_planning_msgs::msg::Maneuver> processed_maneuvers;
563 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER), "VehDowntrack: "<<max_starting_downtrack);
564
565 // Only one maneuver is expected in the received maneuver plan
566 if(maneuvers.size() == 1)
567 {
568 auto maneuver = maneuvers.front();
569
570 double starting_downtrack = GET_MANEUVER_PROPERTY(maneuver, start_dist);
571
572 starting_downtrack = std::min(starting_downtrack, max_starting_downtrack);
573
574 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER), "Used downtrack: " << starting_downtrack);
575
576 // check if required parameter from strategic planner is present
577 if(GET_MANEUVER_PROPERTY(maneuver, parameters.float_valued_meta_data).empty())
578 {
579 throw std::invalid_argument("No time_to_schedule_entry is provided in float_valued_meta_data");
580 }
581
582 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER), "Creating Lane Follow Geometry");
583 std::vector<PointSpeedPair> lane_follow_points = basic_autonomy::waypoint_generation::create_lanefollow_geometry(maneuver, starting_downtrack, wm, general_config, detailed_config, visited_lanelets);
584 points_and_target_speeds.insert(points_and_target_speeds.end(), lane_follow_points.begin(), lane_follow_points.end());
585 processed_maneuvers.push_back(maneuver);
586 }
587 else
588 {
589 throw std::invalid_argument("Light Control Intersection Tactical Plugin currently can"
590 " only create a geometry profile for one maneuver");
591 }
592
593 //Add buffer ending to lane follow points at the end of maneuver(s) end dist
594 if(!processed_maneuvers.empty() && processed_maneuvers.back().type == carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING){
595 points_and_target_speeds = add_lanefollow_buffer(wm, points_and_target_speeds, processed_maneuvers, ending_state_before_buffer, detailed_config);
596 }
597
598 return points_and_target_speeds;
599 }
std::vector< PointSpeedPair > create_lanefollow_geometry(const carma_planning_msgs::msg::Maneuver &maneuver, double max_starting_downtrack, const carma_wm::WorldModelConstPtr &wm, const GeneralTrajConfig &general_config, const DetailedTrajConfig &detailed_config, std::unordered_set< lanelet::Id > &visited_lanelets)
Converts a set of requested LANE_FOLLOWING maneuvers to point speed limit pairs.
std::vector< PointSpeedPair > add_lanefollow_buffer(const carma_wm::WorldModelConstPtr &wm, std::vector< PointSpeedPair > &points_and_target_speeds, const std::vector< carma_planning_msgs::msg::Maneuver > &maneuvers, carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, const DetailedTrajConfig &detailed_config)
Adds extra centerline points beyond required message length to lane follow maneuver points so that th...

References basic_autonomy::waypoint_generation::add_lanefollow_buffer(), basic_autonomy::waypoint_generation::create_lanefollow_geometry(), basic_autonomy::get_logger(), GET_MANEUVER_PROPERTY, and LCI_TACTICAL_LOGGER.

Referenced by generateNewTrajectory().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ findSpeedLimit()

double light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::findSpeedLimit ( const lanelet::ConstLanelet &  llt,
const carma_wm::WorldModelConstPtr wm 
) const
private

Given a Lanelet, find its associated Speed Limit.

Parameters
lltConstant Lanelet object.
wmWorld model pointer to query additional information.
Exceptions
std::invalid_argumentif the speed limit could not be retrieved.
Returns
Speed limit in meters per second.

Definition at line 541 of file light_controlled_intersection_tactical_plugin.cpp.

542 {
543 lanelet::Optional<carma_wm::TrafficRulesConstPtr> traffic_rules = wm->getTrafficRules();
544 if (traffic_rules)
545 {
546 return (*traffic_rules)->speedLimit(llt).speedLimit.value();
547 }
548 else
549 {
550 throw std::invalid_argument("Valid traffic rules object could not be built");
551 }
552 }

Referenced by planTrajectorySmoothing().

Here is the caller graph for this function:

◆ FRIEND_TEST() [1/6]

light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::FRIEND_TEST ( LCITacticalPluginTest  ,
applyOptimizedTargetSpeedProfile   
)
private

◆ FRIEND_TEST() [2/6]

light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::FRIEND_TEST ( LCITacticalPluginTest  ,
applyTrajectorySmoothingAlgorithm   
)
private

◆ FRIEND_TEST() [3/6]

light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::FRIEND_TEST ( LCITacticalPluginTest  ,
createGeometryProfile   
)
private

◆ FRIEND_TEST() [4/6]

light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::FRIEND_TEST ( LCITacticalPluginTest  ,
planTrajectoryCB   
)
private

◆ FRIEND_TEST() [5/6]

light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::FRIEND_TEST ( LCITacticalPluginTest  ,
planTrajectorySmoothing   
)
private

◆ FRIEND_TEST() [6/6]

light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::FRIEND_TEST ( LCITacticalPluginTest  ,
setConfig   
)
private

◆ generateNewTrajectory()

carma_planning_msgs::msg::TrajectoryPlan light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::generateNewTrajectory ( const std::vector< carma_planning_msgs::msg::Maneuver > &  maneuver_plan,
const carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr &  req,
std::vector< double > &  final_speeds 
)
private

Generates a new trajectory plan based on the provided maneuver plan and request. NOTE: This function plans for the entire maneuver input and doesn't time bound it.

Parameters
maneuver_planA vector of maneuver messages defining the planned maneuvers. The first maneuver is expected to have all the necessary TS parameters.
reqShared pointer to the trajectory planning request message.
final_speedsA vector that will be populated with the final speeds for each point as it is useful for late operations or debugging
Returns
A newly generated trajectory plan message.

Definition at line 107 of file light_controlled_intersection_tactical_plugin.cpp.

112 {
113 DetailedTrajConfig wpg_detail_config;
114 GeneralTrajConfig wpg_general_config;
115
117 "intersection_transit",
120
122 99.0, // trajectory time length in duration (seconds) is arbitrarily selected
123 // high to generate all at once
130
131 // Create trajectory with raw speed limits from maneuver
132 auto points_and_target_speeds = createGeometryProfile(
133 maneuver_plan, std::max((double)0, current_downtrack_ - config_.back_distance),
134 wm_, ending_state_before_buffer_, req->vehicle_state,
135 wpg_general_config, wpg_detail_config);
136
137 // Apply optimized speed profile
138 applyOptimizedTargetSpeedProfile(maneuver_plan.front(), req->vehicle_state.longitudinal_vel,
139 points_and_target_speeds);
140
141 // Create new trajectory
142 carma_planning_msgs::msg::TrajectoryPlan new_trajectory;
143 new_trajectory.header.frame_id = "map";
144 new_trajectory.header.stamp = req->header.stamp;
145 new_trajectory.trajectory_id = boost::uuids::to_string(boost::uuids::random_generator()());
146
147 // Generate points
148 new_trajectory.trajectory_points =
150 points_and_target_speeds,
151 req->vehicle_state, req->header.stamp, wm_, ending_state_before_buffer_, debug_msg_,
152 wpg_detail_config);
153
154 // Save final speeds
155 final_speeds = debug_msg_.velocity_profile;
156
157 return new_trajectory;
158 }
void applyOptimizedTargetSpeedProfile(const carma_planning_msgs::msg::Maneuver &maneuver, const double starting_speed, std::vector< PointSpeedPair > &points_and_target_speeds)
Apply optimized target speeds to the trajectory determined for fixed-time and actuated signals....
std::vector< PointSpeedPair > createGeometryProfile(const std::vector< carma_planning_msgs::msg::Maneuver > &maneuvers, double max_starting_downtrack, const carma_wm::WorldModelConstPtr &wm, carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, const carma_planning_msgs::msg::VehicleState &state, const GeneralTrajConfig &general_config, const DetailedTrajConfig &detailed_config)
Creates geometry profile to return a point speed pair struct for INTERSECTION_TRANSIT maneuver types ...
GeneralTrajConfig compose_general_trajectory_config(const std::string &trajectory_type, int default_downsample_ratio, int turn_downsample_ratio)
DetailedTrajConfig compose_detailed_trajectory_config(double trajectory_time_length, double curve_resample_step_size, double minimum_speed, double max_accel, double lateral_accel_limit, int speed_moving_average_window_size, int curvature_moving_average_window_size, double back_distance, double buffer_ending_downtrack, std::string desired_controller_plugin="default")
std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > compose_lanefollow_trajectory_from_path(const std::vector< PointSpeedPair > &points, const carma_planning_msgs::msg::VehicleState &state, const rclcpp::Time &state_time, const carma_wm::WorldModelConstPtr &wm, const carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, carma_debug_ros2_msgs::msg::TrajectoryCurvatureSpeeds &debug_msg, const DetailedTrajConfig &detailed_config)
Method converts a list of lanelet centerline points and current vehicle state into a usable list of t...
auto to_string(const UtmZone &zone) -> std::string
Definition: utm_zone.cpp:21
basic_autonomy::waypoint_generation::DetailedTrajConfig DetailedTrajConfig
basic_autonomy::waypoint_generation::GeneralTrajConfig GeneralTrajConfig

References applyOptimizedTargetSpeedProfile(), light_controlled_intersection_tactical_plugin::Config::back_distance, light_controlled_intersection_tactical_plugin::Config::buffer_ending_downtrack, basic_autonomy::waypoint_generation::compose_detailed_trajectory_config(), basic_autonomy::waypoint_generation::compose_general_trajectory_config(), basic_autonomy::waypoint_generation::compose_lanefollow_trajectory_from_path(), config_, createGeometryProfile(), current_downtrack_, light_controlled_intersection_tactical_plugin::Config::curvature_moving_average_window_size, light_controlled_intersection_tactical_plugin::Config::curve_resample_step_size, debug_msg_, light_controlled_intersection_tactical_plugin::Config::default_downsample_ratio, ending_state_before_buffer_, light_controlled_intersection_tactical_plugin::Config::lateral_accel_limit, light_controlled_intersection_tactical_plugin::Config::minimum_speed, light_controlled_intersection_tactical_plugin::Config::speed_moving_average_window_size, carma_cooperative_perception::to_string(), light_controlled_intersection_tactical_plugin::Config::turn_downsample_ratio, light_controlled_intersection_tactical_plugin::Config::vehicle_accel_limit, and wm_.

Referenced by planTrajectorySmoothing().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isLastTrajectoryValid()

bool light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::isLastTrajectoryValid ( const rclcpp::Time &  current_time,
double  min_remaining_time_seconds = 0.0 
) const
private

Checks if the last trajectory plan remains valid based on the current time.

This function verifies that the previously generated trajectory still meets timing and duration requirements. It can also enforce a minimum remaining duration if specified.

Parameters
current_timeThe current time stamp.
min_remaining_time_secondsOptional parameter specifying the minimum required remaining time (in seconds) for the trajectory to be considered valid.
Returns
True if the last trajectory is valid, false otherwise.

Definition at line 36 of file light_controlled_intersection_tactical_plugin.cpp.

39 {
40 // Check if we have at least 2 points in the trajectory
41 if (last_trajectory_time_unbound_.trajectory_points.size() < 2)
42 {
43 return false;
44 }
45
46 // Check if the last point's time is sufficiently in the future
47 auto last_point_time = rclcpp::Time(last_trajectory_time_unbound_.trajectory_points.back().target_time);
48
49
50 if (rclcpp::Duration min_time_remaining =
51 rclcpp::Duration::from_seconds(min_remaining_time_seconds);
52 last_point_time <= current_time + min_time_remaining)
53 {
54 return false;
55 }
56
57 // Check if we have case information from previous planning
58 if (is_last_case_successful_ == boost::none || last_case_ == boost::none)
59 {
60 return false;
61 }
62
63 // Ensure we have consistent speed data
64 if (last_speeds_time_unbound_.size() != last_trajectory_time_unbound_.trajectory_points.size())
65 {
66 return false;
67 }
68
69 return true;
70 }

References is_last_case_successful_, last_case_, last_speeds_time_unbound_, and last_trajectory_time_unbound_.

Referenced by shouldUseLastTrajectory().

Here is the caller graph for this function:

◆ logDebugInfoAboutPreviousTrajectory()

void light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::logDebugInfoAboutPreviousTrajectory ( )
private

Logs debug information about the previously planned trajectory.

This helper function outputs detailed internal state and trajectory information that can be used for debugging trajectory planning issues.

Definition at line 160 of file light_controlled_intersection_tactical_plugin.cpp.

161 {
162 if (is_last_case_successful_ != boost::none && last_case_ != boost::none)
163 {
164 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
165 "all variables are set!");
166 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
167 "is_last_case_successful_.get(): " << (int)is_last_case_successful_.get());
168 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
169 "evaluation distance: " << last_successful_ending_downtrack_ - current_downtrack_);
170 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
173 }
174 else
175 {
176 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
177 "Not all variables are set...");
178 }
179
180 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
181 "traj points size: " << last_trajectory_time_unbound_.trajectory_points.size() <<
182 ", last_speeds_time_unbound_ size: " << last_speeds_time_unbound_.size());
183 }

References current_downtrack_, basic_autonomy::get_logger(), is_last_case_successful_, last_case_, last_speeds_time_unbound_, last_successful_ending_downtrack_, last_successful_scheduled_entry_time_, last_trajectory_time_unbound_, latest_traj_request_header_stamp_, LCI_TACTICAL_LOGGER, and carma_cooperative_perception::to_string().

Referenced by planTrajectorySmoothing().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ planTrajectoryCB()

void light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::planTrajectoryCB ( carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr  req,
carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr  resp 
)

Function to process the light controlled intersection tactical plugin service call for trajectory planning.

Parameters
reqThe service request
respThe service response

Definition at line 402 of file light_controlled_intersection_tactical_plugin.cpp.

405 {
406 std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now();
407
408 latest_traj_request_header_stamp_ = rclcpp::Time(req->header.stamp); //for debugging
409
410 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
411 "Starting light controlled intersection trajectory planning");
412
413 planTrajectorySmoothing(req, resp);
414
415 std::chrono::system_clock::time_point end_time = std::chrono::system_clock::now();
416 auto duration = end_time - start_time;
417
418 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
419 "ExecutionTime: " << std::chrono::duration<double>(duration).count());
420 }
void planTrajectorySmoothing(carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req, carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp)
Smooths the trajectory as part of the trajectory planning process.

References basic_autonomy::get_logger(), latest_traj_request_header_stamp_, LCI_TACTICAL_LOGGER, and planTrajectorySmoothing().

Here is the call graph for this function:

◆ planTrajectorySmoothing()

void light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::planTrajectorySmoothing ( carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr  req,
carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr  resp 
)
private

Smooths the trajectory as part of the trajectory planning process.

This function takes a trajectory planning request, applies smoothing algorithms to refine the trajectory, and populates the response with the smoothed trajectory.

Parameters
reqShared pointer to the trajectory planning request message.
respShared pointer to the trajectory planning response message to be filled.

Definition at line 185 of file light_controlled_intersection_tactical_plugin.cpp.

188 {
189 // Validate request
190 if(req->maneuver_index_to_plan >= req->maneuver_plan.maneuvers.size())
191 {
192 throw std::invalid_argument(
193 "Light Control Intersection Tactical Plugin was asked to plan invalid "
194 "maneuver index: " + std::to_string(req->maneuver_index_to_plan)
195 + " for plan of size: " + std::to_string(req->maneuver_plan.maneuvers.size()));
196 }
197
198 // Extract maneuver plan
199 std::vector<carma_planning_msgs::msg::Maneuver> maneuver_plan;
200 if(req->maneuver_plan.maneuvers[req->maneuver_index_to_plan].type ==
201 carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING
202 && GET_MANEUVER_PROPERTY(req->maneuver_plan.maneuvers[req->maneuver_index_to_plan],
203 parameters.string_valued_meta_data.front()) == light_controlled_intersection_strategy_)
204 {
205 maneuver_plan.push_back(req->maneuver_plan.maneuvers[req->maneuver_index_to_plan]);
206 resp->related_maneuvers.push_back(req->maneuver_index_to_plan);
207 }
208 else
209 {
210 throw std::invalid_argument("Light Control Intersection Tactical Plugin "
211 "was asked to plan unsupported maneuver");
212 }
213
214 // Get vehicle position and update tracking variables
215 lanelet::BasicPoint2d veh_pos(req->vehicle_state.x_pos_global,
216 req->vehicle_state.y_pos_global);
217 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
218 "Planning state x:" << req->vehicle_state.x_pos_global
219 << " , y: " << req->vehicle_state.y_pos_global);
220
221 current_downtrack_ = wm_->routeTrackPos(veh_pos).downtrack;
222 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
223 "Current_downtrack: "<< current_downtrack_);
224
225 // Find current lanelet
226 auto current_lanelets = wm_->getLaneletsFromPoint({req->vehicle_state.x_pos_global,
227 req->vehicle_state.y_pos_global});
228
229 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER), "size: "
230 << current_lanelets.size());
231
232 lanelet::ConstLanelet current_lanelet;
233
234 if (current_lanelets.empty())
235 {
236 RCLCPP_ERROR_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
237 "Given vehicle position is not on the road! Returning...");
238 return;
239 }
240
241 // Get the lanelet that is on the route in case overlapping ones found
242 if (auto llt_on_route_optional = wm_->getFirstLaneletOnShortestPath(current_lanelets);
243 llt_on_route_optional)
244 {
245 current_lanelet = llt_on_route_optional.value();
246 }
247 else
248 {
249 RCLCPP_WARN_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
250 "When identifying the corresponding lanelet for requested trajectory plan's state, "
251 << "x: " << req->vehicle_state.x_pos_global
252 << ", y: " << req->vehicle_state.y_pos_global
253 << ", no possible lanelet was found to be on the shortest path."
254 << "Picking arbitrary lanelet: " << current_lanelets[0].id() << ", instead");
255
256 current_lanelet = current_lanelets[0];
257 }
258
259 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
260 "Current_lanelet: " << current_lanelet.id());
261
262 speed_limit_ = findSpeedLimit(current_lanelet, wm_);
263 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
264 "speed_limit_: " << speed_limit_);
265
266 // Get new case parameters
267 bool is_new_case_successful =
268 GET_MANEUVER_PROPERTY(maneuver_plan.front(), parameters.int_valued_meta_data[1]);
269
270 auto new_case =
271 static_cast<TSCase>GET_MANEUVER_PROPERTY(
272 maneuver_plan.front(), parameters.int_valued_meta_data[0]);
273
274 // Log debug info about previous trajectory
276
277 // Find closest point in last trajectory to current vehicle position
278 size_t idx_to_start_new_traj =
280 last_trajectory_time_unbound_.trajectory_points,
281 veh_pos);
282
283 // Update last trajectory to start from closest point (remove passed points)
284 if (!last_trajectory_time_unbound_.trajectory_points.empty()) {
285 last_speeds_time_unbound_ = std::vector<double>(
286 last_speeds_time_unbound_.begin() + idx_to_start_new_traj,
288 last_trajectory_time_unbound_.trajectory_points =
289 std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint>
290 (last_trajectory_time_unbound_.trajectory_points.begin() + idx_to_start_new_traj,
291 last_trajectory_time_unbound_.trajectory_points.end());
292 }
293
294 // Check if we should use the last trajectory completely
295 auto current_time = rclcpp::Time(req->header.stamp);
296
297
298 auto last_trajectory_time_bound =
301 if (shouldUseLastTrajectory(new_case, is_new_case_successful, current_time))
302 {
303 resp->trajectory_plan = last_trajectory_time_unbound_;
304 resp->trajectory_plan.trajectory_points = last_trajectory_time_bound;
305
306 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
307 "USING LAST TRAJ WITH CASE: " << (int)last_case_.get());
308
309 resp->trajectory_plan.initial_longitudinal_velocity = last_speeds_time_unbound_.front();
310
311 // Set the planning plugin field name
312 for (auto& p : resp->trajectory_plan.trajectory_points) {
313 p.planner_plugin_name = plugin_name_;
314 }
315
316 debug_msg_.trajectory_plan = resp->trajectory_plan;
317 debug_msg_.velocity_profile = last_speeds_time_unbound_;
319 return;
320 }
321
322 // Reaching here means the plugin needs to generate a new trajectory
323 std::vector<double> new_final_speeds;
324 if (carma_planning_msgs::msg::TrajectoryPlan new_trajectory =
325 generateNewTrajectory(maneuver_plan, req, new_final_speeds);
326 new_trajectory.trajectory_points.size() >= 2)
327 {
328 // New trajectory, by default, extends for the whole maneuver duration, so time bound it
329 auto new_trajectory_time_bound =
331 new_trajectory.trajectory_points, config_.trajectory_time_length);
332
333 resp->trajectory_plan = new_trajectory;
334 resp->trajectory_plan.trajectory_points = new_trajectory_time_bound;
335
336 // Update stored trajectories
337 last_trajectory_time_unbound_ = new_trajectory;
338 last_speeds_time_unbound_ = new_final_speeds;
339
340 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
341 "USING NEW TRAJECTORY for case: " << (int)new_case);
342 }
343 // Fall back to last trajectory if new is invalid but last is valid
344 else if (last_trajectory_time_unbound_.trajectory_points.size() >= 2 &&
345 rclcpp::Time(last_trajectory_time_unbound_.trajectory_points.back().target_time) > current_time)
346 {
347 resp->trajectory_plan = last_trajectory_time_unbound_;
348 resp->trajectory_plan.trajectory_points = last_trajectory_time_bound;
349
350 RCLCPP_WARN_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
351 "Failed to generate a new trajectory, so using last valid trajectory!");
352 }
353 // Last resort - return the invalid new trajectory
354 else
355 {
356 resp->trajectory_plan = new_trajectory;
357 RCLCPP_WARN_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
358 "Failed to generate a new trajectory or use old valid trajectory, "
359 "so returning empty/invalid trajectory!");
360 }
361
362 // Update stored case information
363
364 last_case_ = new_case;
365 is_last_case_successful_ = is_new_case_successful;
366
367 // Update variables for next evaluation
368 if (is_new_case_successful) {
369 // LCI Tactical plugin receives only single maneuver that can span multiple lanelets
370 // end of the maneuver is expected to be the start of the intersection
372 GET_MANEUVER_PROPERTY(maneuver_plan.front(), end_dist);
373
374 // Entry time to the intersection
376 rclcpp::Time(GET_MANEUVER_PROPERTY(maneuver_plan.front(), end_time)).seconds();
377
378 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
379 "last_successful_ending_downtrack_:" << last_successful_ending_downtrack_ <<
380 ", last_successful_scheduled_entry_time_: " <<
382 }
383
384 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(LCI_TACTICAL_LOGGER),
385 "Debug: new case:" << (int) new_case << ", is_new_case_successful: "
386 << is_new_case_successful);
387
388 resp->maneuver_status.push_back(
389 carma_planning_msgs::srv::PlanTrajectory::Response::MANEUVER_IN_PROGRESS);
390 resp->trajectory_plan.initial_longitudinal_velocity = last_speeds_time_unbound_.front();
391
392 // Set the planning plugin field name
393 for (auto& p : resp->trajectory_plan.trajectory_points) {
394 p.planner_plugin_name = plugin_name_;
395 }
396
397 debug_msg_.trajectory_plan = resp->trajectory_plan;
398 debug_msg_.velocity_profile = last_speeds_time_unbound_;
400 }
carma_planning_msgs::msg::TrajectoryPlan generateNewTrajectory(const std::vector< carma_planning_msgs::msg::Maneuver > &maneuver_plan, const carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr &req, std::vector< double > &final_speeds)
Generates a new trajectory plan based on the provided maneuver plan and request. NOTE: This function ...
double findSpeedLimit(const lanelet::ConstLanelet &llt, const carma_wm::WorldModelConstPtr &wm) const
Given a Lanelet, find its associated Speed Limit.
bool shouldUseLastTrajectory(TSCase new_case, bool is_new_case_successful, const rclcpp::Time &current_time)
Determines whether the last trajectory should be reused based on the planning case....
int get_nearest_point_index(const std::vector< lanelet::BasicPoint2d > &points, const carma_planning_msgs::msg::VehicleState &state)
Returns the nearest point (in terms of cartesian 2d distance) to the provided vehicle pose in the pro...
std::vector< PointSpeedPair > constrain_to_time_boundary(const std::vector< PointSpeedPair > &points, double time_span)
Reduces the input points to only those points that fit within the provided time boundary.

References config_, basic_autonomy::waypoint_generation::constrain_to_time_boundary(), current_downtrack_, debug_msg_, debug_publisher_, findSpeedLimit(), generateNewTrajectory(), basic_autonomy::get_logger(), GET_MANEUVER_PROPERTY, basic_autonomy::waypoint_generation::get_nearest_point_index(), is_last_case_successful_, last_case_, last_speeds_time_unbound_, last_successful_ending_downtrack_, last_successful_scheduled_entry_time_, last_trajectory_time_unbound_, LCI_TACTICAL_LOGGER, light_controlled_intersection_strategy_, logDebugInfoAboutPreviousTrajectory(), plugin_name_, shouldUseLastTrajectory(), speed_limit_, carma_cooperative_perception::to_string(), light_controlled_intersection_tactical_plugin::Config::trajectory_time_length, and wm_.

Referenced by planTrajectoryCB().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setConfig()

void light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::setConfig ( const Config config)

Setter function to set a new config for this object.

Parameters
configThe new config to be used by this object

Definition at line 601 of file light_controlled_intersection_tactical_plugin.cpp.

602 {
603 config_ = config;
604 }

References config_.

◆ shouldUseLastTrajectory()

bool light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::shouldUseLastTrajectory ( TSCase  new_case,
bool  is_new_case_successful,
const rclcpp::Time &  current_time 
)
private

Determines whether the last trajectory should be reused based on the planning case. Should use last case if 1) last traj is valid AND last case is the same as new case, OR 2) last traj is valid AND within certain evaluation zone before the intersection where the new case is not successful but last case is.

Parameters
new_caseAn enumerated type representing the new trajectory planning case.
is_new_case_successfulA boolean flag indicating if the new trajectory planning was successful.
current_timeThe current time stamp.
Returns
True if the last trajectory should be used, false otherwise.

Definition at line 72 of file light_controlled_intersection_tactical_plugin.cpp.

74 {
75 // Validate trajectory with 1 second minimum remaining time or vehicle_response_lag seconds
76 // This is because the vehicle executes speed command of vehicle_response_lag secs ahead
77 // Therefore, the trajectory should be enough to cover the vehicle_response_lag
78 if (!isLastTrajectoryValid(current_time, std::max(config_.vehicle_response_lag, 1.0)))
79 {
80 return false;
81 }
82
83 // New case is successful and is same as the last case
84 if (last_case_.get() == new_case && is_new_case_successful == true)
85 {
86 return true;
87 }
88
89 // Edge case - TS Alorithm successful to unsuccessful transition (Case (1-7) to 8)
90 // near the intersection. The vehicle should "lock in" to the last trajectory as it is
91 // expected for the TS algorithm to be unsuccessful near the intersection.
92 if (is_last_case_successful_.get() == true &&
93 is_new_case_successful == false &&
96 last_successful_scheduled_entry_time_ - current_time.seconds() <
98 {
99 return true;
100 }
101
102 // Returning false here means that it should use the new trajectory because:
103 // New case is not same as last case and not within the "lock in" distance
104 return false;
105 }
bool isLastTrajectoryValid(const rclcpp::Time &current_time, double min_remaining_time_seconds=0.0) const
Checks if the last trajectory plan remains valid based on the current time.

References config_, current_downtrack_, light_controlled_intersection_tactical_plugin::Config::dist_before_intersection_to_force_last_traj, is_last_case_successful_, isLastTrajectoryValid(), last_case_, last_successful_ending_downtrack_, last_successful_scheduled_entry_time_, light_controlled_intersection_tactical_plugin::Config::period_before_intersection_to_force_last_traj, and light_controlled_intersection_tactical_plugin::Config::vehicle_response_lag.

Referenced by planTrajectorySmoothing().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ config_

Config light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::config_
private

◆ current_downtrack_

double light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::current_downtrack_ = 0.0
private

◆ debug_msg_

carma_debug_ros2_msgs::msg::TrajectoryCurvatureSpeeds light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::debug_msg_
private

◆ debug_publisher_

DebugPublisher light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::debug_publisher_
private

◆ ending_state_before_buffer_

carma_planning_msgs::msg::VehicleState light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::ending_state_before_buffer_
private

◆ epsilon_

double light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::epsilon_ = 0.001
private

◆ is_allowed_int_

bool light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::is_allowed_int_ = false
private

◆ is_last_case_successful_

boost::optional<bool> light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::is_last_case_successful_
private

◆ last_case_

boost::optional<TSCase> light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::last_case_
private

◆ last_speeds_time_unbound_

std::vector<double> light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::last_speeds_time_unbound_
private

◆ last_successful_ending_downtrack_

double light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::last_successful_ending_downtrack_
private

◆ last_successful_scheduled_entry_time_

double light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::last_successful_scheduled_entry_time_
private

◆ last_trajectory_time_unbound_

carma_planning_msgs::msg::TrajectoryPlan light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::last_trajectory_time_unbound_
private

◆ latest_traj_request_header_stamp_

rclcpp::Time light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::latest_traj_request_header_stamp_
private

◆ LCI_TACTICAL_LOGGER

const std::string light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::LCI_TACTICAL_LOGGER = "light_controlled_intersection_tactical_plugin"
private

◆ light_controlled_intersection_strategy_

std::string light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::light_controlled_intersection_strategy_ = "Carma/signalized_intersection"
private

◆ nh_

std::shared_ptr<carma_ros2_utils::CarmaLifecycleNode> light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::nh_
private

◆ plugin_name_

std::string light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::plugin_name_
private

◆ scheduled_depart_time_

uint32_t light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::scheduled_depart_time_ = 0.0
private

◆ scheduled_enter_time_

uint32_t light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::scheduled_enter_time_ = 0.0
private

◆ scheduled_latest_depart_time_

uint32_t light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::scheduled_latest_depart_time_ = 0.0
private

◆ scheduled_stop_time_

uint32_t light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::scheduled_stop_time_ = 0.0
private

◆ speed_limit_

double light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::speed_limit_ = 11.176
private

◆ street_msg_timestamp_

uint32_t light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::street_msg_timestamp_ = 0.0
private

◆ wm_

carma_wm::WorldModelConstPtr light_controlled_intersection_tactical_plugin::LightControlledIntersectionTacticalPlugin::wm_
private

The documentation for this class was generated from the following files: