21 namespace std_ph = std::placeholders;
61 auto error = update_params<std::string>(
65 auto error_2 = update_params<double>(
86 auto error_3 = update_params<int>(
93 rcl_interfaces::msg::SetParametersResult result;
95 result.successful = !error && !error_2 && !error_3;
102 RCLCPP_INFO_STREAM(
get_logger(),
"CooperativeLaneChangePlugin trying to configure");
141 pose_sub_ = create_subscription<geometry_msgs::msg::PoseStamped>(
"current_pose", 1,
143 twist_sub_ = create_subscription<geometry_msgs::msg::TwistStamped>(
"current_velocity", 1,
147 georeference_sub_ = create_subscription<std_msgs::msg::String>(
"georeference", 1,
149 bsm_sub_ = create_subscription<carma_v2x_msgs::msg::BSM>(
"bsm_outbound", 1,
154 lanechange_status_pub_ = create_publisher<carma_planning_msgs::msg::LaneChangeStatus>(
"cooperative_lane_change_status", 10);
160 return CallbackReturn::SUCCESS;
167 carma_planning_msgs::msg::LaneChangeStatus lc_status_msg;
171 lc_status_msg.status = carma_planning_msgs::msg::LaneChangeStatus::ACCEPTANCE_RECEIVED;
172 lc_status_msg.description =
"Received lane merge acceptance";
177 lc_status_msg.status = carma_planning_msgs::msg::LaneChangeStatus::REJECTION_RECEIVED;
178 lc_status_msg.description =
"Received lane merge rejection";
185 RCLCPP_DEBUG_STREAM(
get_logger(),
"received mobility response is not related to CLC");
193 RCLCPP_DEBUG_STREAM(
get_logger(),
"entered find_current_gap");
194 double current_gap = 0.0;
195 lanelet::BasicPoint2d ego_pos(ego_state.x_pos_global, ego_state.y_pos_global);
198 lanelet::LaneletMapConstPtr const_map(
wm_->getMap());
199 lanelet::ConstLanelet veh2_lanelet = const_map->laneletLayer.get(veh2_lanelet_id);
200 RCLCPP_DEBUG_STREAM(
get_logger(),
"veh2_lanelet id " << veh2_lanelet.id());
202 auto current_lanelets = lanelet::geometry::findNearest(const_map->laneletLayer, ego_pos, 10);
203 if(current_lanelets.size() == 0)
205 RCLCPP_WARN_STREAM(
get_logger(),
"Cannot find any lanelet in map!");
208 lanelet::ConstLanelet current_lanelet = current_lanelets[0].second;
209 RCLCPP_DEBUG_STREAM(
get_logger(),
"current llt id " << current_lanelet.id());
212 lanelet::ConstLanelet start_lanelet = veh2_lanelet;
213 lanelet::ConstLanelet end_lanelet = current_lanelet;
215 auto map_graph =
wm_->getMapRoutingGraph();
216 RCLCPP_DEBUG_STREAM(
get_logger(),
"Graph created");
218 auto temp_route = map_graph->getRoute(start_lanelet, end_lanelet);
219 RCLCPP_DEBUG_STREAM(
get_logger(),
"Route created");
222 lanelet::routing::LaneletPath shortest_path2;
225 shortest_path2 = temp_route.get().shortestPath();
228 RCLCPP_ERROR_STREAM(
get_logger(),
"No path exists from roadway object to subject");
229 throw std::invalid_argument(
"No path exists from roadway object to subject");
232 RCLCPP_DEBUG_STREAM(
get_logger(),
"Shorted path created size: " << shortest_path2.size());
233 for (
auto llt : shortest_path2)
235 RCLCPP_DEBUG_STREAM(
get_logger(),
"llt id route: " << llt.id());
239 double veh1_current_downtrack =
wm_->routeTrackPos(ego_pos).downtrack;
240 RCLCPP_DEBUG_STREAM(
get_logger(),
"ego_current_downtrack:" << veh1_current_downtrack);
242 current_gap = veh1_current_downtrack - veh2_downtrack;
243 RCLCPP_DEBUG_STREAM(
get_logger(),
"Finding current gap");
244 RCLCPP_DEBUG_STREAM(
get_logger(),
"Veh1 current downtrack: " << veh1_current_downtrack <<
" veh2 downtrack: " << veh2_downtrack);
265 std::shared_ptr<rmw_request_id_t>,
266 carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req,
267 carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp)
269 std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now();
278 std::vector<carma_planning_msgs::msg::Maneuver> maneuver_plan;
279 if(req->maneuver_plan.maneuvers[req->maneuver_index_to_plan].type != carma_planning_msgs::msg::Maneuver::LANE_CHANGE)
281 throw std::invalid_argument (
"Cooperative Lane Change Plugin doesn't support this maneuver type");
283 maneuver_plan.push_back(req->maneuver_plan.maneuvers[req->maneuver_index_to_plan]);
286 long target_lanelet_id = stol(maneuver_plan[0].lane_change_maneuver.ending_lane_id);
287 double target_downtrack = maneuver_plan[0].lane_change_maneuver.end_dist;
290 lanelet::BasicPoint2d veh_pos(req->vehicle_state.x_pos_global, req->vehicle_state.y_pos_global);
291 double current_downtrack =
wm_->routeTrackPos(veh_pos).downtrack;
293 RCLCPP_DEBUG_STREAM(
get_logger(),
"target_lanelet_id: " << target_lanelet_id);
294 RCLCPP_DEBUG_STREAM(
get_logger(),
"target_downtrack: " << target_downtrack);
295 RCLCPP_DEBUG_STREAM(
get_logger(),
"current_downtrack: " << current_downtrack);
296 RCLCPP_DEBUG_STREAM(
get_logger(),
"Starting CLC downtrack: " << maneuver_plan[0].lane_change_maneuver.start_dist);
300 "Lane change trajectory will not be planned. current_downtrack is more than "
303 std::chrono::system_clock::time_point end_time = std::chrono::system_clock::now();
305 auto duration = end_time - start_time;
308 "CLC ExecutionTime: " << std::chrono::duration<double>(duration).count());
311 auto current_lanelets = lanelet::geometry::findNearest(
wm_->getMap()->laneletLayer, veh_pos, 10);
312 long current_lanelet_id = current_lanelets[0].second.id();
314 carma_planning_msgs::msg::LaneChangeStatus lc_status_msg;
315 lc_status_msg.status = carma_planning_msgs::msg::LaneChangeStatus::PLANNING_SUCCESS;
320 long veh2_lanelet_id = 0;
321 double veh2_downtrack = 0.0, veh2_speed = 0.0;
322 bool foundRoadwayObject =
false;
323 bool negotiate =
true;
324 std::vector<carma_perception_msgs::msg::RoadwayObstacle> rwol =
wm_->getRoadwayObjects();
326 for(
int i = 0;
i < rwol.size();
i++){
327 if(rwol[
i].connected_vehicle_type.type == carma_perception_msgs::msg::ConnectedVehicleType::NOT_CONNECTED){
328 veh2_lanelet_id = rwol[0].lanelet_id;
329 veh2_downtrack = rwol[0].down_track;
330 veh2_speed = rwol[0].object.velocity.twist.linear.x;
331 foundRoadwayObject =
true;
335 if(foundRoadwayObject){
336 RCLCPP_DEBUG_STREAM(
get_logger(),
"Found Roadway object");
338 RCLCPP_DEBUG_STREAM(
get_logger(),
"veh2_lanelet_id: " << veh2_lanelet_id <<
", veh2_downtrack: " << veh2_downtrack);
340 double current_gap =
find_current_gap(veh2_lanelet_id, veh2_downtrack, req->vehicle_state);
341 RCLCPP_DEBUG_STREAM(
get_logger(),
"Current gap: " << current_gap);
345 RCLCPP_DEBUG_STREAM(
get_logger(),
"Relative velocity: " << relative_velocity);
347 RCLCPP_DEBUG_STREAM(
get_logger(),
"Desired gap: " << desired_gap);
359 RCLCPP_DEBUG_STREAM(
get_logger(),
"No roadway object");
364 RCLCPP_DEBUG_STREAM(
get_logger(),
"Planning lane change trajectory");
366 std::string maneuver_id = maneuver_plan[0].lane_change_maneuver.parameters.maneuver_id;
369 RCLCPP_DEBUG_STREAM(
get_logger(),
"Received maneuver id " << maneuver_id <<
" for the first time");
370 RCLCPP_DEBUG_STREAM(
get_logger(),
"Original start dist is " << maneuver_plan[0].lane_change_maneuver.start_dist);
371 RCLCPP_DEBUG_STREAM(
get_logger(),
"Original starting_lane_id is " << maneuver_plan[0].lane_change_maneuver.starting_lane_id);
387 RCLCPP_DEBUG_STREAM(
get_logger(),
"Lane change maneuver " << maneuver_id <<
" has started, maintaining speed (in m/s): " <<
392 std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint> planned_trajectory_points =
plan_lanechange(req);
395 RCLCPP_DEBUG_STREAM(
get_logger(),
"Negotiating");
398 carma_v2x_msgs::msg::MobilityRequest request =
create_mobility_request(planned_trajectory_points, maneuver_plan[0]);
404 carma_planning_msgs::msg::LaneChangeStatus lc_status_msg;
405 lc_status_msg.status = carma_planning_msgs::msg::LaneChangeStatus::PLAN_SENT;
406 lc_status_msg.description =
"Requested lane merge";
412 RCLCPP_DEBUG_STREAM(
get_logger(),
"negotiate:" << negotiate);
415 RCLCPP_DEBUG_STREAM(
get_logger(),
"Adding to response");
424 rclcpp::Time planning_end_time = this->now();
427 carma_planning_msgs::msg::LaneChangeStatus lc_status_msg;
428 lc_status_msg.status = carma_planning_msgs::msg::LaneChangeStatus::TIMED_OUT;
429 lc_status_msg.description =
"Request timed out for lane merge";
436 for (
auto& p : resp->trajectory_plan.trajectory_points) {
440 std::chrono::system_clock::time_point end_time = std::chrono::system_clock::now();
442 auto duration = end_time - start_time;
445 "CLC ExecutionTime: " << std::chrono::duration<double>(duration).count());
449 carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp,
450 const std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint>& planned_trajectory_points)
452 carma_planning_msgs::msg::TrajectoryPlan trajectory_plan;
453 trajectory_plan.header.frame_id =
"map";
454 trajectory_plan.header.stamp = this->now();
457 trajectory_plan.trajectory_points = planned_trajectory_points;
458 trajectory_plan.initial_longitudinal_velocity = std::max(req->vehicle_state.longitudinal_vel,
config_.
minimum_speed);
459 resp->trajectory_plan = trajectory_plan;
461 resp->related_maneuvers.push_back(req->maneuver_index_to_plan);
463 resp->maneuver_status.push_back(carma_planning_msgs::srv::PlanTrajectory::Response::MANEUVER_IN_PROGRESS);
468 carma_v2x_msgs::msg::MobilityRequest request_msg;
469 carma_v2x_msgs::msg::MobilityHeader header;
475 header.timestamp = rclcpp::Time(trajectory_plan.front().target_time).nanoseconds() * 1000000;
476 request_msg.m_header = header;
478 request_msg.strategy =
"carma/cooperative-lane-change";
479 request_msg.plan_type.type = carma_v2x_msgs::msg::PlanType::CHANGE_LANE_LEFT;
493 request_msg.urgency = urgency;
497 using boost::property_tree::ptree;
499 double end_speed_floor = std::floor(maneuver.lane_change_maneuver.end_speed);
500 int end_speed_fractional = (maneuver.lane_change_maneuver.end_speed - end_speed_floor) * 10;
502 RCLCPP_DEBUG_STREAM(
get_logger(),
"end_speed_floor: " << end_speed_floor);
503 RCLCPP_DEBUG_STREAM(
get_logger(),
"end_speed_fractional: " << end_speed_fractional);
504 RCLCPP_DEBUG_STREAM(
get_logger(),
"start_lanelet_id: " << maneuver.lane_change_maneuver.starting_lane_id);
505 RCLCPP_DEBUG_STREAM(
get_logger(),
"end_lanelet_id: " << maneuver.lane_change_maneuver.ending_lane_id);
507 pt.put(
"s",(
int)end_speed_floor);
508 pt.put(
"f",end_speed_fractional);
509 pt.put(
"sl",maneuver.lane_change_maneuver.starting_lane_id);
510 pt.put(
"el", maneuver.lane_change_maneuver.ending_lane_id);
512 std::stringstream body_stream;
513 boost::property_tree::json_parser::write_json(body_stream,pt);
514 request_msg.strategy_params = body_stream.str();
515 RCLCPP_DEBUG_STREAM(
get_logger(),
"request_msg.strategy_params: " << request_msg.strategy_params);
518 carma_v2x_msgs::msg::Trajectory trajectory;
522 carma_planning_msgs::msg::TrajectoryPlanPoint temp_loc_to_convert;
523 temp_loc_to_convert.x =
pose_msg_.pose.position.x;
524 temp_loc_to_convert.y =
pose_msg_.pose.position.y;
528 location.timestamp = rclcpp::Time(trajectory_plan.front().target_time).nanoseconds() * 1000000;
530 request_msg.location = location;
534 RCLCPP_ERROR_STREAM(
get_logger(),
"Map projection not available to be used with request message");
537 request_msg.trajectory = trajectory;
538 request_msg.expiration = rclcpp::Time(trajectory_plan.back().target_time).seconds();
539 RCLCPP_DEBUG_STREAM(
get_logger(),
"request_msg.expiration: " << request_msg.expiration <<
" of which string size: " <<
std::to_string(request_msg.expiration).size());
546 carma_v2x_msgs::msg::Trajectory traj;
549 if (traj_points.size() < 2){
550 RCLCPP_WARN_STREAM(
get_logger(),
"Received Trajectory Plan is too small");
554 carma_v2x_msgs::msg::LocationECEF prev_point = ecef_location;
555 for (
size_t i = 1;
i < traj_points.size();
i++){
557 carma_v2x_msgs::msg::LocationOffsetECEF offset;
559 offset.offset_x = (int16_t)(new_point.ecef_x - prev_point.ecef_x);
560 offset.offset_y = (int16_t)(new_point.ecef_y - prev_point.ecef_y);
561 offset.offset_z = (int16_t)(new_point.ecef_z - prev_point.ecef_z);
562 prev_point = new_point;
563 traj.offsets.push_back(offset);
567 traj.location = ecef_location;
575 throw std::invalid_argument(
"No map projector available for ecef conversion");
577 carma_v2x_msgs::msg::LocationECEF location;
579 lanelet::BasicPoint3d ecef_point =
map_projector_->projectECEF({traj_point.x, traj_point.y, 0.0}, 1);
580 location.ecef_x = ecef_point.x() * 100.0;
581 location.ecef_y = ecef_point.y() * 100.0;
582 location.ecef_z = ecef_point.z() * 100.0;
589 lanelet::BasicPoint2d veh_pos(req->vehicle_state.x_pos_global, req->vehicle_state.y_pos_global);
590 double current_downtrack =
wm_->routeTrackPos(veh_pos).downtrack;
593 std::vector<carma_planning_msgs::msg::Maneuver> maneuver_plan;
594 if(req->maneuver_plan.maneuvers[req->maneuver_index_to_plan].type != carma_planning_msgs::msg::Maneuver::LANE_CHANGE) {
595 throw std::invalid_argument (
"Cooperative Lane Change Plugin doesn't support this maneuver type");
597 maneuver_plan.push_back(req->maneuver_plan.maneuvers[req->maneuver_index_to_plan]);
599 if(current_downtrack >= maneuver_plan.front().lane_change_maneuver.end_dist){
615 RCLCPP_DEBUG_STREAM(
get_logger(),
"Current downtrack: " << current_downtrack);
617 std::string maneuver_id = maneuver_plan.front().lane_change_maneuver.parameters.maneuver_id;
618 double original_start_dist = current_downtrack;
623 RCLCPP_DEBUG_STREAM(
get_logger(),
"Maneuver id " << maneuver_id <<
" original start_dist is " << original_start_dist);
627 RCLCPP_DEBUG_STREAM(
get_logger(),
"Updated maneuver id " << maneuver_id <<
" starting_lane_id to its original value of " <<
original_lc_maneuver_values_[maneuver_id].original_starting_lane_id);
632 RCLCPP_DEBUG_STREAM(
get_logger(),
"Updating vehicle_state.longitudinal_vel to the initial lane change value of " <<
original_lc_maneuver_values_[maneuver_id].original_longitudinal_vel_ms);
636 RCLCPP_WARN_STREAM(
get_logger(),
"No original values for lane change maneuver were found!");
639 double starting_downtrack = std::min(current_downtrack, original_start_dist);
644 auto maneuver_end_dist = maneuver_plan.back().lane_change_maneuver.end_dist;
645 auto maneuver_start_dist = maneuver_plan.front().lane_change_maneuver.start_dist;
648 RCLCPP_DEBUG_STREAM(
get_logger(),
"Maneuvers to points size: " << points_and_target_speeds.size());
649 auto downsampled_points = carma_ros2_utils::containers::downsample_vector(points_and_target_speeds,
config_.
downsample_ratio);
653 RCLCPP_DEBUG_STREAM(
get_logger(),
"Compose Trajectory size: " << trajectory_points.size());
654 return trajectory_points;
662 map_projector_ = std::make_shared<lanelet::projection::LocalFrameProjector>(msg->data.c_str());
668 std::string res =
"";
669 for (
size_t i = 0;
i < bsm_core.id.size();
i++){
685#include "rclcpp_components/register_node_macro.hpp"
std::string get_plugin_name() const
Return the name of this plugin.
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...
The class responsible for generating cooperative lanechange trajectories from received lane change ma...
carma_v2x_msgs::msg::LocationECEF trajectory_point_to_ecef(const carma_planning_msgs::msg::TrajectoryPlanPoint &traj_point) const
Converts Trajectory Point to ECEF frame using map projection.
geometry_msgs::msg::PoseStamped pose_msg_
std::string map_georeference_
carma_planning_msgs::msg::VehicleState ending_state_before_buffer_
bool get_availability() override
Get the availability status of this plugin based on the current operating environment....
carma_v2x_msgs::msg::MobilityRequest create_mobility_request(std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > &trajectory_plan, carma_planning_msgs::msg::Maneuver &maneuver)
Creates a mobility request message from planned trajectory and requested maneuver info.
void bsm_cb(const carma_v2x_msgs::msg::BSM::UniquePtr msg)
Callback for the BSM subscriber, which will store the latest BSM Core Data broadcasted by the host ve...
carma_ros2_utils::SubPtr< geometry_msgs::msg::TwistStamped > twist_sub_
void add_trajectory_to_response(carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req, carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp, const std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > &planned_trajectory_points)
Adds the generated trajectory plan to the service response.
std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > plan_lanechange(carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req)
Creates a vector of Trajectory Points from maneuver information in trajectory request.
void mobilityresponse_cb(const carma_v2x_msgs::msg::MobilityResponse::UniquePtr msg)
Callback to subscribed mobility response topic.
std::unordered_map< std::string, LaneChangeManeuverOriginalValues > original_lc_maneuver_values_
double find_current_gap(long veh2_lanelet_id, double veh2_downtrack, carma_planning_msgs::msg::VehicleState &ego_state) const
Calculates distance between subject vehicle and vehicle 2.
void plan_trajectory_callback(std::shared_ptr< rmw_request_id_t >, carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req, carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp) override
Extending class provided callback which should return a planned trajectory based on the provided traj...
carma_ros2_utils::SubPtr< carma_v2x_msgs::msg::BSM > bsm_sub_
std::string bsmIDtoString(carma_v2x_msgs::msg::BSMCoreData bsm_core)
Method for extracting the BSM ID from a BSM Core Data object and converting it to a string.
CooperativeLaneChangePlugin(const rclcpp::NodeOptions &)
CooperativeLaneChangePlugin constructor.
carma_v2x_msgs::msg::BSMCoreData bsm_core_
bool is_lanechange_accepted_
void pose_cb(const geometry_msgs::msg::PoseStamped::UniquePtr msg)
Callback for the pose subscriber, which will store latest pose locally.
carma_ros2_utils::SubPtr< std_msgs::msg::String > georeference_sub_
carma_wm::WorldModelConstPtr wm_
std::string get_version_id() override
Returns the version id of this plugin.
void twist_cb(const geometry_msgs::msg::TwistStamped::UniquePtr msg)
Callback for the twist subscriber, which will store latest twist locally.
carma_ros2_utils::PubPtr< carma_planning_msgs::msg::LaneChangeStatus > lanechange_status_pub_
carma_ros2_utils::PubPtr< carma_v2x_msgs::msg::MobilityRequest > outgoing_mobility_request_pub_
std::string clc_request_id_
void georeference_cb(const std_msgs::msg::String::UniquePtr msg)
Callback for map projection string to define lat/lon -> map conversion.
std::shared_ptr< lanelet::projection::LocalFrameProjector > map_projector_
rcl_interfaces::msg::SetParametersResult parameter_update_callback(const std::vector< rclcpp::Parameter > ¶meters)
Callback for dynamic parameter updates.
carma_ros2_utils::CallbackReturn on_configure_plugin()
This method should be used to load parameters and will be called on the configure state transition.
carma_ros2_utils::SubPtr< geometry_msgs::msg::PoseStamped > pose_sub_
rclcpp::Time request_sent_time_
std::string DEFAULT_STRING_
carma_ros2_utils::SubPtr< carma_v2x_msgs::msg::MobilityResponse > incoming_mobility_response_sub_
carma_v2x_msgs::msg::Trajectory trajectory_plan_to_trajectory(const std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > &traj_points) const
Converts Trajectory Plan to (Mobility) Trajectory.
double maneuver_fraction_completed_
GeneralTrajConfig compose_general_trajectory_config(const std::string &trajectory_type, int default_downsample_ratio, int turn_downsample_ratio)
std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > compose_lanechange_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, const DetailedTrajConfig &detailed_config)
Method converts a list of lanelet centerline points and current vehicle state into a usable list of t...
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< PointSpeedPair > create_geometry_profile(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 LANE FOLLOW and LANE CHANGE maneuver...
void set_logger(rclcpp::Logger logger)
Replace the module-level logger used by all basic_autonomy functions.
rclcpp::Logger get_logger()
Return the module-level logger used by all basic_autonomy functions.
auto to_string(const UtmZone &zone) -> std::string
Stuct containing the algorithm configuration values for cooperative_lanechange.
double starting_downtrack_range
int speed_moving_average_window_size
double minimum_lookahead_distance
double curve_resample_step_size
double trajectory_time_length
double minimum_lookahead_speed
int curvature_moving_average_window_size
double maximum_lookahead_speed
int curvature_calc_lookahead_count
double lateral_accel_limit
std::string control_plugin_name
double maximum_lookahead_distance
int turn_downsample_ratio
double lanechange_time_out
double buffer_ending_downtrack
Convenience struct for storing the original start_dist and starting_lane_id associated with a receive...
double original_start_dist
std::string original_starting_lane_id