lanelet2_route_planning v2.0.0
Loading...
Searching...
No Matches
lanelet2_route_planning::Lanelet2RoutePlanning Class Reference

Lanelet2 route planning node. More...

#include <lanelet2_route_planning.hpp>

Inheritance diagram for lanelet2_route_planning::Lanelet2RoutePlanning:

Public Member Functions

 Lanelet2RoutePlanning ()
 Constructor.
 

Private Member Functions

template<typename T >
void declareAndLoadParameter (const std::string &name, T &param, const std::string &description, const bool add_to_auto_reconfigurable_params=true, const bool is_required=false, const bool read_only=false, const std::optional< double > &from_value=std::nullopt, const std::optional< double > &to_value=std::nullopt, const std::optional< double > &step_value=std::nullopt, const std::string &additional_constraints="")
 Declares and loads a ROS parameter.
 
rcl_interfaces::msg::SetParametersResult parametersCallback (const std::vector< rclcpp::Parameter > &parameters)
 Handles reconfiguration when a parameter value is changed.
 
void setup ()
 Sets up subscribers, publishers, etc. to configure the node.
 
bool checkMap (bool handle_update)
 Checks if map is loaded and handles map updates.
 
bool buildRoutingGraph ()
 Builds the lanelet2 routing graph based on the current map.
 
void egoDataCallback (const perception_msgs::msg::EgoData::SharedPtr msg)
 Callback for EgoData.
 
void publishTimerCallback ()
 Callback to periodically publish the route.
 
void globalRoutePublishTimerCallback ()
 Callback to periodically publish the adaptively sampled global route.
 
rclcpp_action::GoalResponse actionHandleGoal (const rclcpp_action::GoalUUID &uuid, std::shared_ptr< const route_planning_msgs::action::PlanRoute::Goal > goal)
 Action goal callback: processes a route planning request.
 
rclcpp_action::CancelResponse actionHandleCancel (const std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > goal_handle)
 Action cancel callback: cancels a running action.
 
void actionHandleAccepted (const std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > goal_handle)
 Action accepted callback: starts action execution.
 
void actionExecute (const std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > goal_handle)
 Action execution: continually publishes route progress.
 
bool planRoute (const geometry_msgs::msg::PointStamped &destination, const std::vector< geometry_msgs::msg::PointStamped > &intermediate_destinations={})
 Plans a lanelet route to the destination.
 
void buildGlobalRouteMessage ()
 Builds a global ROS route message from the latest planned lanelet route.
 
void buildEnrichedRouteMessage ()
 Builds an enriched ROS route message from the latest planned lanelet route.
 
void publishHealth (const unsigned char status, const std::string &msg, const rclcpp::Time &now)
 Publishes health diagnostic.
 

Private Attributes

std::vector< std::tuple< std::string, std::function< void(const rclcpp::Parameter &)> > > auto_reconfigurable_params_
 Auto-reconfigurable parameters for dynamic reconfiguration.
 
OnSetParametersCallbackHandle::SharedPtr parameters_callback_
 Callback handle for dynamic parameter reconfiguration.
 
rclcpp::Subscription< perception_msgs::msg::EgoData >::SharedPtr subscriber_ego_data_
 Subscriber for ego data.
 
rclcpp::Publisher< route_planning_msgs::msg::Route >::SharedPtr publisher_route_
 Publisher for enriched route.
 
rclcpp::Publisher< route_planning_msgs::msg::Route >::SharedPtr publisher_global_route_
 Publisher for the adaptively sampled global route.
 
rclcpp::TimerBase::SharedPtr publish_timer_
 Timer for publishing the enriched route.
 
rclcpp::TimerBase::SharedPtr global_route_publish_timer_
 Timer for publishing the global route.
 
rclcpp_action::Server< route_planning_msgs::action::PlanRoute >::SharedPtr action_server_
 Action server.
 
route_planning_msgs::action::PlanRoute::Feedback::SharedPtr action_feedback_
 Latest action feedback.
 
route_planning_msgs::action::PlanRoute::Result::SharedPtr action_result_
 Latest action result.
 
std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > action_goal_handle_
 Latest action goal handle.
 
rclcpp::CallbackGroup::SharedPtr action_callback_group_
 Callback group for action server.
 
rclcpp::Time action_start_time_
 Latest action start time to compute action duration.
 
std::unique_ptr< tf2_ros::Buffer > tf_buffer_
 Transform buffer.
 
std::shared_ptr< tf2_ros::TransformListener > tf_listener_
 Transform listener.
 
perception_msgs::msg::EgoData latest_ego_data_
 Latest ego data in map frame.
 
std::unique_ptr< Lanelet2MapInterface > ll2_interface_
 Lanelet2 map interface.
 
lanelet::routing::RoutingGraphUPtr routing_graph_
 Lanelet routing graph for current map.
 
geometry_msgs::msg::Point starting_point_
 Starting point in map frame.
 
geometry_msgs::msg::Point destination_
 Destination point in map frame.
 
std::vector< geometry_msgs::msg::Point > intermediate_destinations_
 Intermediate points in map frame.
 
lanelet::routing::Route latest_route_
 Latest planned lanelet route.
 
bool has_enriched_route_ = false
 Flag indicating that route has been enriched at least once.
 
bool is_publishing_route_
 Controlling flag for route publication.
 
route_planning_msgs::msg::Route latest_route_msg_
 Latest route message to publish.
 
route_planning_msgs::msg::Route latest_full_route_msg_
 Latest complete minimal route used internally for progress tracking.
 
route_planning_msgs::msg::Route latest_global_route_msg_
 Latest adaptively sampled non-enriched global route.
 
std::vector< Eigen::Vector2d > latest_reference_line_
 Latest complete dense reference line in the map frame.
 
std::vector< size_t > latest_lanelet_idx_by_reference_line_point_idx_
 Latest mapping between global route reference line and lanelet indices.
 
std::vector< std::vector< int > > latest_suggested_turn_signal_distance_ahead_by_route_element_by_lane_element_
 Latest suggested turn signal distance ahead by route element by lane element.
 
std::string ll2_map_server_name_ = "lanelet2_map_server"
 Name of lanelet2_map_server node (parameter)
 
double publish_frequency_ = 10.0
 Frequency of route publication [Hz] (parameter)
 
double action_feedback_frequency_ = 1.0
 Frequency of action feedback publication [Hz] (parameter)
 
double publish_frequency_global_ = 1.0
 Frequency of global route publication [Hz] (parameter)
 
double sampling_distance_ = 1.0
 Distance between resampled points along route [m] (parameter)
 
double sampling_max_lateral_error_global_ = 0.5
 Maximum lateral error of the adaptively sampled global reference line [m] (parameter)
 
bool project_destination_to_reference_line_ = true
 Whether to project destination to reference line (parameter)
 
double destination_distance_threshold_ = 1.0
 Distance to destination where destination is considered reached [m] (parameter)
 
double required_traveled_distance_proportion_ = 0.5
 Proportion of route length that must have been traveled before considering destination reached [0..1] (parameter)
 
double enrich_route_ahead_ego_distance_ = 100.0
 Distance ahead of ego position where global route is enriched with more information [m] (negative=unlimited) (parameter)
 
double enrich_route_behind_ego_distance_ = 10.0
 Distance behind ego position where global route is enriched with more information [m] (negative=unlimited) (parameter)
 
double route_undershoot_distance_ = 0.0
 Undershoot route by this distance before ego position [m] (parameter)
 
double route_overshoot_distance_ = 0.0
 Overshoot route by this distance behind destination [m] (parameter)
 
double max_drivable_space_radius_ = 50.0
 Maximum distance to left/right drivable space bounds, if not otherwise restricted [m] (parameter)
 
int max_num_threads_ = 0
 Maximum number of threads for parallel processing (0=max available) (parameter)
 
double transform_timeout_ = 0.02
 How long to wait for a transform to be available [s] (parameter)
 
std::map< std::string, std::string > health_kv_
 Health key-value pairs for diagnostic message.
 
std::mutex health_kv_mutex_
 Mutex protecting health key-value pairs across threads.
 
rclcpp::Publisher< diagnostic_msgs::msg::DiagnosticArray >::SharedPtr health_diagnostic_pub_
 Health diagnostic publisher.
 
diagnostic_updater::Updater diagnostic_updater_
 Diagnostic updater for monitoring topic frequencies and timestamps.
 
std::unique_ptr< diagnostic_updater::TopicDiagnostic > ego_data_diagnostic_
 Diagnostic to auto-diagnose ego data topic.
 
std::unique_ptr< diagnostic_updater::HeaderlessTopicDiagnostic > route_timer_diagnostic_
 Diagnostic to auto-diagnose route timer frequency.
 
std::unique_ptr< diagnostic_updater::HeaderlessTopicDiagnostic > global_route_timer_diagnostic_
 Diagnostic to auto-diagnose global route timer frequency.
 
TopicDiagnosticConfig ego_data_diagnostic_config_ = {45.45, 55.55, 0.0, 0.002}
 Configuration for auto-diagnosed ego data topic.
 
TopicDiagnosticConfig route_timer_diagnostic_config_ = {18.18, 22.22}
 Configuration for auto-diagnosed route timer.
 
TopicDiagnosticConfig global_route_timer_diagnostic_config_ = {0.91, 1.11}
 Configuration for auto-diagnosed global route timer.
 

Detailed Description

Lanelet2 route planning node.

Definition at line 64 of file lanelet2_route_planning.hpp.

Constructor & Destructor Documentation

◆ Lanelet2RoutePlanning()

lanelet2_route_planning::Lanelet2RoutePlanning::Lanelet2RoutePlanning ( )

Constructor.

Definition at line 27 of file lanelet2_route_planning.cpp.

27 : Node("lanelet2_route_planning"), diagnostic_updater_(this) {
28 this->declareAndLoadParameter("ll2_map_server_name", ll2_map_server_name_, "Name of lanelet2_map_server node", false, false,
29 true);
30 this->declareAndLoadParameter("publish_frequency", publish_frequency_, "Frequency of route publication [Hz]", true, false,
31 false, 0.1, 20.0);
32 this->declareAndLoadParameter("publish_frequency_global", publish_frequency_global_,
33 "Frequency of global route publication [Hz]", true, false, false, 0.1, 20.0);
34 this->declareAndLoadParameter("action_feedback_frequency", action_feedback_frequency_,
35 "Frequency of action feedback publication [Hz]", true, false, false, 0.1, 20.0);
36 this->declareAndLoadParameter("sampling_distance", sampling_distance_, "Distance between resampled points along route [m]",
37 true, false, false, 0.1, 3.0);
38 this->declareAndLoadParameter("sampling_max_lateral_error_global", sampling_max_lateral_error_global_,
39 "Maximum lateral error of the adaptively sampled global reference line [m]", true, false, false,
40 0.0, 100.0);
41 this->declareAndLoadParameter("project_destination_to_reference_line", project_destination_to_reference_line_,
42 "Whether to project destination to reference line", true, false, false);
43 this->declareAndLoadParameter("destination_distance_threshold", destination_distance_threshold_,
44 "Distance to destination where destination is considered reached [m]", true, false, false, 0.1,
45 200.0);
47 "required_traveled_distance_proportion", required_traveled_distance_proportion_,
48 "Proportion of route length that must have been traveled before considering destination reached [0..1]", true, false, false,
49 0.0, 1.0);
51 "enrich_route_ahead_ego_distance", enrich_route_ahead_ego_distance_,
52 "Distance ahead of ego position where global route is enriched with more information [m] (negative=unlimited)", true, false,
53 false, -1.0, 1000.0);
55 "enrich_route_behind_ego_distance", enrich_route_behind_ego_distance_,
56 "Distance behind ego position where global route is enriched with more information [m] (negative=unlimited)", true, false,
57 false, -1.0, 1000.0);
58 this->declareAndLoadParameter("route_undershoot_distance", route_undershoot_distance_,
59 "Undershoot route by this distance before ego position [m]", true, false, false, 0.0, 50.0);
60 this->declareAndLoadParameter("route_overshoot_distance", route_overshoot_distance_,
61 "Overshoot route by this distance behind destination [m]", true, false, false, 0.0, 100.0);
62 this->declareAndLoadParameter("max_drivable_space_radius", max_drivable_space_radius_,
63 "Maximum distance to left/right drivable space bounds, if not otherwise restricted [m]", true,
64 false, false, 3.0, 100.0);
65 this->declareAndLoadParameter("max_num_threads", max_num_threads_,
66 "Maximum number of threads for parallel processing (0=max available)", true, false, false, 0,
67 omp_get_max_threads(), 1);
68 this->declareAndLoadParameter("transform_timeout", transform_timeout_, "How long to wait for a transform to be available [s]",
69 true, false, false, 0.0, 1.0);
71 enrich_route_ahead_ego_distance_ = std::numeric_limits<double>::infinity();
72 }
74 enrich_route_behind_ego_distance_ = std::numeric_limits<double>::infinity();
75 }
76 if (max_num_threads_ <= 0) {
77 max_num_threads_ = omp_get_max_threads();
78 }
79 omp_set_num_threads(max_num_threads_);
80
81 this->declareAndLoadParameter("diagnostic_updater.ego_data_diagnostic.min_frequency", ego_data_diagnostic_config_.min_frequency,
82 "Minimum frequency for incoming ego data topic", false, false, false);
83 this->declareAndLoadParameter("diagnostic_updater.ego_data_diagnostic.max_frequency", ego_data_diagnostic_config_.max_frequency,
84 "Maximum frequency for incoming ego data topic", false, false, false);
85 this->declareAndLoadParameter("diagnostic_updater.ego_data_diagnostic.min_acceptable_timestamp_delta",
87 "Minimum acceptable timestamp delta for incoming ego data topic", false, false, false);
88 this->declareAndLoadParameter("diagnostic_updater.ego_data_diagnostic.max_acceptable_timestamp_delta",
90 "Maximum acceptable timestamp delta for incoming ego data topic", false, false, false);
91 this->declareAndLoadParameter("diagnostic_updater.route_timer_diagnostic.min_frequency",
92 route_timer_diagnostic_config_.min_frequency, "Minimum frequency for route timer", false, false,
93 false);
94 this->declareAndLoadParameter("diagnostic_updater.route_timer_diagnostic.max_frequency",
95 route_timer_diagnostic_config_.max_frequency, "Maximum frequency for route timer", false, false,
96 false);
97 this->declareAndLoadParameter("diagnostic_updater.global_route_timer_diagnostic.min_frequency",
98 global_route_timer_diagnostic_config_.min_frequency, "Minimum frequency for global route timer",
99 false, false, false);
100 this->declareAndLoadParameter("diagnostic_updater.global_route_timer_diagnostic.max_frequency",
101 global_route_timer_diagnostic_config_.max_frequency, "Maximum frequency for global route timer",
102 false, false, false);
103
104 this->setup();
105}
double sampling_distance_
Distance between resampled points along route [m] (parameter)
double max_drivable_space_radius_
Maximum distance to left/right drivable space bounds, if not otherwise restricted [m] (parameter)
double action_feedback_frequency_
Frequency of action feedback publication [Hz] (parameter)
double required_traveled_distance_proportion_
Proportion of route length that must have been traveled before considering destination reached [0....
double sampling_max_lateral_error_global_
Maximum lateral error of the adaptively sampled global reference line [m] (parameter)
double enrich_route_behind_ego_distance_
Distance behind ego position where global route is enriched with more information [m] (negative=unlim...
double route_overshoot_distance_
Overshoot route by this distance behind destination [m] (parameter)
void setup()
Sets up subscribers, publishers, etc. to configure the node.
std::string ll2_map_server_name_
Name of lanelet2_map_server node (parameter)
double publish_frequency_global_
Frequency of global route publication [Hz] (parameter)
TopicDiagnosticConfig global_route_timer_diagnostic_config_
Configuration for auto-diagnosed global route timer.
diagnostic_updater::Updater diagnostic_updater_
Diagnostic updater for monitoring topic frequencies and timestamps.
double destination_distance_threshold_
Distance to destination where destination is considered reached [m] (parameter)
double publish_frequency_
Frequency of route publication [Hz] (parameter)
double enrich_route_ahead_ego_distance_
Distance ahead of ego position where global route is enriched with more information [m] (negative=unl...
int max_num_threads_
Maximum number of threads for parallel processing (0=max available) (parameter)
double route_undershoot_distance_
Undershoot route by this distance before ego position [m] (parameter)
TopicDiagnosticConfig route_timer_diagnostic_config_
Configuration for auto-diagnosed route timer.
bool project_destination_to_reference_line_
Whether to project destination to reference line (parameter)
void declareAndLoadParameter(const std::string &name, T &param, const std::string &description, const bool add_to_auto_reconfigurable_params=true, const bool is_required=false, const bool read_only=false, const std::optional< double > &from_value=std::nullopt, const std::optional< double > &to_value=std::nullopt, const std::optional< double > &step_value=std::nullopt, const std::string &additional_constraints="")
Declares and loads a ROS parameter.
TopicDiagnosticConfig ego_data_diagnostic_config_
Configuration for auto-diagnosed ego data topic.
double transform_timeout_
How long to wait for a transform to be available [s] (parameter)
double max_acceptable_timestamp_delta
Maximum acceptable difference between message timestamp and receipt time (in seconds)
double min_acceptable_timestamp_delta
Minimum acceptable difference between message timestamp and receipt time (in seconds)

Member Function Documentation

◆ actionExecute()

void lanelet2_route_planning::Lanelet2RoutePlanning::actionExecute ( const std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > goal_handle)
private

Action execution: continually publishes route progress.

Periodically publishes route traveling progress. Checks for goal completion or cancellation.

Parameters
[in]goal_handleaction goal handle

Definition at line 512 of file lanelet2_route_planning.cpp.

513 {
514 RCLCPP_INFO(this->get_logger(), "Executing action goal");
515
516 {
517 std::scoped_lock lock(health_kv_mutex_);
518 health_kv_["action_status"] = "executing";
519 }
520
521 rclcpp::Rate feedback_rate(action_feedback_frequency_);
522 bool has_reached_destination = false;
523 while (goal_handle->is_executing() && !goal_handle->is_canceling() && !has_reached_destination) {
524 // update feedback and result
527 action_feedback_->time_traveled = this->now() - action_start_time_;
528 action_feedback_->time_remaining =
529 rclcpp::Duration::from_seconds(route_planning_msgs::route_access::estimateRemainingTime(latest_full_route_msg_));
530 action_result_->distance_traveled = action_feedback_->distance_traveled;
531 action_result_->time_traveled = action_feedback_->time_traveled;
532
533 // check if destination reached (criteria: close to destination and some distance traveled)
534 double distance_to_destination = (toEigen2d(egoPosition(latest_ego_data_)) - toEigen2d(destination_)).norm();
535 double total_route_distance = action_feedback_->distance_traveled + action_feedback_->distance_remaining;
536 bool is_close_to_destination = (distance_to_destination <= destination_distance_threshold_);
537 bool has_traveled_sufficient_distance =
538 (action_feedback_->distance_traveled >= required_traveled_distance_proportion_ * total_route_distance);
539 has_reached_destination = (is_close_to_destination && has_traveled_sufficient_distance);
540
541 // publish feedback
542 goal_handle->publish_feedback(action_feedback_);
543 if (!has_reached_destination) {
544 feedback_rate.sleep();
545 }
546 }
547
548 // prepare result
549 action_result_->distance_traveled = action_feedback_->distance_traveled + action_feedback_->distance_remaining;
550 action_result_->time_traveled = this->now() - action_start_time_;
551 action_result_->destination_reached = has_reached_destination;
552
553 // publish result
554 if (goal_handle->is_canceling()) {
555 goal_handle->canceled(action_result_);
556 {
557 std::scoped_lock lock(health_kv_mutex_);
558 health_kv_["action_status"] = "canceled";
559 }
560 RCLCPP_INFO(this->get_logger(), "Goal canceled");
561 } else if (!goal_handle->is_executing()) {
562 {
563 std::scoped_lock lock(health_kv_mutex_);
564 health_kv_["action_status"] = "aborted";
565 }
566 RCLCPP_INFO(this->get_logger(), "Goal aborted");
567 } else if (rclcpp::ok()) {
568 is_publishing_route_ = false; // stop publishing route
569 goal_handle->succeed(action_result_);
570 {
571 std::scoped_lock lock(health_kv_mutex_);
572 health_kv_["action_status"] = "succeeded";
573 }
574 RCLCPP_INFO(this->get_logger(), "Goal succeeded");
575 }
576}
geometry_msgs::msg::Point destination_
Destination point in map frame.
bool is_publishing_route_
Controlling flag for route publication.
std::map< std::string, std::string > health_kv_
Health key-value pairs for diagnostic message.
route_planning_msgs::action::PlanRoute::Result::SharedPtr action_result_
Latest action result.
route_planning_msgs::action::PlanRoute::Feedback::SharedPtr action_feedback_
Latest action feedback.
perception_msgs::msg::EgoData latest_ego_data_
Latest ego data in map frame.
rclcpp::Time action_start_time_
Latest action start time to compute action duration.
route_planning_msgs::msg::Route latest_full_route_msg_
Latest complete minimal route used internally for progress tracking.
std::mutex health_kv_mutex_
Mutex protecting health key-value pairs across threads.
geometry_msgs::msg::Point egoPosition(const perception_msgs::msg::EgoData &ego_data)
Extracts an EgoData position as a ROS point.
double distanceTraveled(const route_planning_msgs::msg::Route &route)
Computes the traveled distance along the route.
Definition utils.cpp:993
Eigen::Vector2d toEigen2d(const geometry_msgs::msg::Point &point)
Converts a ROS point to a 2D Eigen point.
double distanceRemaining(const route_planning_msgs::msg::Route &route)
Computes the remaining distance along the route.
Definition utils.cpp:1004

◆ actionHandleAccepted()

void lanelet2_route_planning::Lanelet2RoutePlanning::actionHandleAccepted ( const std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > goal_handle)
private

Action accepted callback: starts action execution.

Processes accepted action goal requests.

Initializes action feedback and starts action execution in a separate thread.

Parameters
[in]goal_handleaction goal handle
goal_handleaction goal handle

Definition at line 482 of file lanelet2_route_planning.cpp.

483 {
484 action_goal_handle_ = goal_handle;
485
486 {
487 std::scoped_lock lock(health_kv_mutex_);
488 health_kv_["action_status"] = "accepted";
489 }
490
491 // initialize feedback and result
492 action_start_time_ = this->now();
493 action_feedback_ = std::make_shared<route_planning_msgs::action::PlanRoute::Feedback>();
494 action_feedback_->distance_traveled = 0.0;
495 action_feedback_->distance_remaining = 0.0;
497 action_feedback_->time_traveled = rclcpp::Duration::from_seconds(0.0);
498 action_feedback_->time_remaining =
499 rclcpp::Duration::from_seconds(route_planning_msgs::route_access::estimateRemainingTime(latest_full_route_msg_));
500 action_result_ = std::make_shared<route_planning_msgs::action::PlanRoute::Result>();
501 action_result_->distance_traveled = 0.0;
502 action_result_->time_traveled = rclcpp::Duration::from_seconds(0.0);
503 action_result_->destination_reached = false;
504
505 // start publishing route
507
508 // execute action in a separate thread to avoid blocking
509 std::thread{std::bind(&Lanelet2RoutePlanning::actionExecute, this, std::placeholders::_1), goal_handle}.detach();
510}
std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > action_goal_handle_
Latest action goal handle.
void actionExecute(const std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > goal_handle)
Action execution: continually publishes route progress.

◆ actionHandleCancel()

rclcpp_action::CancelResponse lanelet2_route_planning::Lanelet2RoutePlanning::actionHandleCancel ( const std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > goal_handle)
private

Action cancel callback: cancels a running action.

Sets a flag to cancel action execution.

Parameters
[in]goal_handleaction goal handle
Returns
cancel response

Definition at line 467 of file lanelet2_route_planning.cpp.

468 {
469 (void)goal_handle;
470
471 RCLCPP_INFO(this->get_logger(), "Received request to cancel action goal");
472 is_publishing_route_ = false; // stop publishing route
473
474 return rclcpp_action::CancelResponse::ACCEPT;
475}

◆ actionHandleGoal()

rclcpp_action::GoalResponse lanelet2_route_planning::Lanelet2RoutePlanning::actionHandleGoal ( const rclcpp_action::GoalUUID & uuid,
std::shared_ptr< const route_planning_msgs::action::PlanRoute::Goal > goal )
private

Action goal callback: processes a route planning request.

Plans a global route to the destination before accepting the goal. Aborts any existing running action.

Parameters
[in]uuidunique goal identifier
[in]goalaction goal
Returns
goal response

Definition at line 425 of file lanelet2_route_planning.cpp.

426 {
427 (void)uuid;
428 (void)goal;
429
430 const geometry_msgs::msg::PointStamped& destination = goal->destination;
431 const std::vector<geometry_msgs::msg::PointStamped>& intermediate_destinations = goal->intermediate_destinations;
432 RCLCPP_INFO(this->get_logger(), "Received request to plan route to destination (%.3f, %.3f, %.3f) in frame '%s'",
433 destination.point.x, destination.point.y, destination.point.z, destination.header.frame_id.c_str());
434
435 // check for and handle map updates
436 if (!this->checkMap(true)) {
437 RCLCPP_ERROR(this->get_logger(), "Cannot plan route, map not loaded by '%s'", ll2_map_server_name_.c_str());
438 return rclcpp_action::GoalResponse::REJECT;
439 }
440
441 // plan route
442 auto t0 = std::chrono::steady_clock::now();
443 bool success = this->planRoute(destination, intermediate_destinations);
444 auto t1 = std::chrono::steady_clock::now();
445 auto dt = std::chrono::duration_cast<std::chrono::duration<double>>(t1 - t0).count();
446 if (!success) {
447 RCLCPP_ERROR(this->get_logger(), "Failed to plan route to destination, rejecting request");
448 return rclcpp_action::GoalResponse::REJECT;
449 }
450
451 // convert route to ROS message
453 RCLCPP_INFO(this->get_logger(), "Successfully planned route to destination (%.3fs)", dt);
454
455 // abort current action if running
456 if (action_goal_handle_ && action_goal_handle_->is_active()) {
457 RCLCPP_WARN(this->get_logger(), "Existing action detected, aborting before accepting new goal");
458 is_publishing_route_ = false; // stop publishing route
460 action_goal_handle_.reset();
461 }
462
463 // accept action goal request
464 return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
465}
void buildGlobalRouteMessage()
Builds a global ROS route message from the latest planned lanelet route.
bool checkMap(bool handle_update)
Checks if map is loaded and handles map updates.
bool planRoute(const geometry_msgs::msg::PointStamped &destination, const std::vector< geometry_msgs::msg::PointStamped > &intermediate_destinations={})
Plans a lanelet route to the destination.

◆ buildEnrichedRouteMessage()

void lanelet2_route_planning::Lanelet2RoutePlanning::buildEnrichedRouteMessage ( )
private

Builds an enriched ROS route message from the latest planned lanelet route.

The enriched route message is locally enriched around the ego position. The enriched part contains adjacent lanes, drivable space, and regulatory elements.

Definition at line 843 of file lanelet2_route_planning.cpp.

843 {
844 if (latest_full_route_msg_.route_elements.empty() || latest_reference_line_.empty()) {
845 return;
846 }
847
848 // find point of global reference line closest to and behind of ego position
849 const Eigen::Vector2d ego_position = toEigen2d(egoPosition(latest_ego_data_));
850 const size_t global_closest_point =
851 matchPointToLineString(latest_reference_line_, ego_position, latest_full_route_msg_.current_route_element_idx, true, true);
852 latest_full_route_msg_.current_route_element_idx = global_closest_point;
853 const auto& full_route_elements = latest_full_route_msg_.route_elements;
854 LocalRouteWindow local_route_window = extractLocalRouteWindow(
856 const size_t first_global_idx = local_route_window.first_global_idx;
857 route_planning_msgs::msg::Route route_msg = std::move(local_route_window.route);
858 std::vector<route_planning_msgs::msg::RouteElement>& route_elements = route_msg.route_elements;
859 if (route_elements.empty()) {
860 return;
861 }
862
864 std::vector<std::vector<int>>(route_elements.size());
865 const lanelet::routing::LaneletPath shortest_path = latest_route_.shortestPath();
866
867// parallelize independent geometry, map, and regulatory-element extraction per local route element
868#pragma omp parallel for
869 for (size_t c = 0; c < route_elements.size(); ++c) {
870 const size_t global_c = first_global_idx + c;
871 route_planning_msgs::msg::RouteElement& route_element_msg = route_elements[c];
872 route_planning_msgs::msg::LaneElement& lane_element_msg =
873 route_element_msg.lane_elements[route_element_msg.suggested_lane_idx];
874
875 // get current, previous and next centerline point
876 const route_planning_msgs::msg::LaneElement prev_lane_element_msg =
877 (global_c > 0) ? route_planning_msgs::route_access::getSuggestedLaneElement(full_route_elements[global_c - 1])
878 : lane_element_msg;
879 const route_planning_msgs::msg::LaneElement next_lane_element_msg =
880 (global_c + 1 < full_route_elements.size())
881 ? route_planning_msgs::route_access::getSuggestedLaneElement(full_route_elements[global_c + 1])
882 : lane_element_msg;
883 const Eigen::Vector2d point = toEigen2d(lane_element_msg.reference_pose.position);
884 const Eigen::Vector2d prev_point = toEigen2d(prev_lane_element_msg.reference_pose.position);
885 const Eigen::Vector2d next_point = toEigen2d(next_lane_element_msg.reference_pose.position);
886 const double point_z = lane_element_msg.reference_pose.position.z; // assuming constant z across route elements
887
888 // get lanelet corresponding to centerline point
889 const lanelet::ConstLanelet& lanelet = shortest_path[latest_lanelet_idx_by_reference_line_point_idx_[global_c]];
890
891 // identify lane changes
892 const bool changes_lane_from_prev_point =
893 changesLaneFromPointToPoint(prev_point, point, sampling_distance_); // NOLINT(readability-suspicious-call-argument)
894 const bool changes_lane_to_next_point = changesLaneFromPointToPoint(point, next_point, sampling_distance_);
895
896 // determine neighboring points for projection
897 Eigen::Vector2d prev_point_for_projection = changes_lane_from_prev_point ? point : prev_point;
898 Eigen::Vector2d next_point_for_projection = changes_lane_to_next_point ? point : next_point;
899
900 // get adjacent lanelets
901 std::vector<lanelet::ConstLanelet> adjacent_left_lanelets = adjacentLeftOrRightLanelets(lanelet, routing_graph_, true);
902 std::vector<lanelet::ConstLanelet> adjacent_right_lanelets = adjacentLeftOrRightLanelets(lanelet, routing_graph_, false);
903 const int suggested_lane_idx = static_cast<int>(adjacent_left_lanelets.size());
904 const int n_lanes = static_cast<int>(adjacent_left_lanelets.size() + 1 + adjacent_right_lanelets.size());
907 }
908
909 // project centerline point to lanelet and adjacent lanelet centerlines and bounds
910 auto lanelet_projected_points =
911 projectPointToLaneletLines(point, prev_point_for_projection, next_point_for_projection,
912 std::vector<lanelet::ConstLanelet>{lanelet}, this->get_logger())[0];
913 auto adjacent_left_lanelets_projected_points = projectPointToLaneletLines(
914 point, prev_point_for_projection, next_point_for_projection, adjacent_left_lanelets, this->get_logger());
915 auto adjacent_right_lanelets_projected_points = projectPointToLaneletLines(
916 point, prev_point_for_projection, next_point_for_projection, adjacent_right_lanelets, this->get_logger());
917
918 // compute offset of lane element indices from current to next route element
919 const lanelet::ConstLanelet& lanelet_of_next_point =
920 (global_c + 1 < full_route_elements.size()) ? shortest_path[latest_lanelet_idx_by_reference_line_point_idx_[global_c + 1]]
921 : lanelet;
922 int following_lane_idx_offset = 0;
923 if (auto result = computeFollowingLaneIdxOffset(lanelet, lanelet_of_next_point, routing_graph_)) {
924 following_lane_idx_offset = *result;
925 } else {
926 RCLCPP_ERROR(this->get_logger(),
927 "Failed to find following lane index offset for route element %ld on lanelet %ld, assuming no offset",
928 global_c, lanelet.id());
929 following_lane_idx_offset = 0;
930 }
931
932 // extract drivable space
933 Eigen::Vector2d drivable_space_left, drivable_space_right;
934 std::tie(drivable_space_left, drivable_space_right) =
935 extractDrivableSpace(ll2_interface_->getMapPtr()->lineStringLayer,
936 {prev_point_for_projection, point, next_point_for_projection}, max_drivable_space_radius_);
937
938 // extract regulatory elements
939 auto regulatory_element_extraction =
940 extractRegulatoryElements(lanelet, adjacent_left_lanelets, adjacent_right_lanelets, {prev_point, point, next_point});
941
942// enrich RouteElement with local route information
943#pragma omp critical // prevent race condition when accessing prev/next suggested lane element set by other threads
944 {
945 route_element_msg.lane_elements = {};
946 route_element_msg.is_enriched = true;
947 route_element_msg.left_boundary = toRos(to3d(drivable_space_left, point_z));
948 route_element_msg.right_boundary = toRos(to3d(drivable_space_right, point_z));
949 route_element_msg.regulatory_elements = regulatory_element_extraction.regulatory_element_msgs;
950 route_element_msg.suggested_lane_idx = suggested_lane_idx;
951 route_element_msg.will_change_suggested_lane = changes_lane_to_next_point;
952 // route_element_msg.s already set in global route
953 size_t lane_element_idx = route_element_msg.lane_elements.size();
954
955 // create LaneElements for left adjacent lanes
956 for (size_t a = 0; a < adjacent_left_lanelets_projected_points.size(); ++a) {
957 route_planning_msgs::msg::LaneElement lane_element_msg;
958 lane_element_msg.reference_pose.position =
959 toRos(to3d(adjacent_left_lanelets_projected_points[a].centerline_point, point_z));
960 // lane_element_msg.reference_pose.orientation computed in postprocessRouteMessage
961 lane_element_msg.left_boundary.point = toRos(to3d(adjacent_left_lanelets_projected_points[a].left_bound_point, point_z));
962 lane_element_msg.left_boundary.type = laneBoundaryType(adjacent_left_lanelets[a].leftBound2d());
963 lane_element_msg.right_boundary.point =
964 toRos(to3d(adjacent_left_lanelets_projected_points[a].right_bound_point, point_z));
965 lane_element_msg.right_boundary.type = laneBoundaryType(adjacent_left_lanelets[a].rightBound2d());
966 lane_element_msg.speed_limit =
967 speedLimit(adjacent_left_lanelets[a], adjacent_left_lanelets_projected_points[a].centerline_point);
968 lane_element_msg.regulatory_element_idcs = regulatory_element_extraction.adjacent_left_regulatory_element_idcs[a];
969 const int computed_following_lane_idx =
970 static_cast<int>(route_element_msg.lane_elements.size()) + following_lane_idx_offset;
971 lane_element_msg.has_following_lane_idx = (computed_following_lane_idx >= 0 && computed_following_lane_idx < n_lanes);
972 if (lane_element_msg.has_following_lane_idx) {
973 lane_element_msg.following_lane_idx = computed_following_lane_idx;
974 }
975 std::tie(lane_element_msg.suggested_turn_signal,
977 suggestedTurnSignal(adjacent_left_lanelets[a], this->get_logger());
978 route_element_msg.lane_elements.push_back(lane_element_msg);
979 lane_element_idx = route_element_msg.lane_elements.size();
980 }
981
982 // create LaneElement for centerline lane
983 route_planning_msgs::msg::LaneElement centerline_lane_element_msg;
984 centerline_lane_element_msg.reference_pose.position = toRos(to3d(point, point_z));
985 // centerline_lane_element_msg.reference_pose.orientation computed in postprocessRouteMessage
986 centerline_lane_element_msg.left_boundary.point = toRos(to3d(lanelet_projected_points.left_bound_point, point_z));
987 centerline_lane_element_msg.left_boundary.type = laneBoundaryType(lanelet.leftBound2d());
988 centerline_lane_element_msg.right_boundary.point = toRos(to3d(lanelet_projected_points.right_bound_point, point_z));
989 centerline_lane_element_msg.right_boundary.type = laneBoundaryType(lanelet.rightBound2d());
990 centerline_lane_element_msg.speed_limit = speedLimit(lanelet, point);
991 centerline_lane_element_msg.regulatory_element_idcs = regulatory_element_extraction.regulatory_element_idcs;
992 const int computed_following_lane_idx =
993 static_cast<int>(route_element_msg.lane_elements.size()) + following_lane_idx_offset;
994 centerline_lane_element_msg.has_following_lane_idx =
995 (computed_following_lane_idx >= 0 && computed_following_lane_idx < n_lanes);
996 if (centerline_lane_element_msg.has_following_lane_idx) {
997 centerline_lane_element_msg.following_lane_idx = computed_following_lane_idx;
998 }
999 std::tie(centerline_lane_element_msg.suggested_turn_signal,
1001 suggestedTurnSignal(lanelet, this->get_logger());
1002 route_element_msg.lane_elements.push_back(centerline_lane_element_msg);
1003 lane_element_idx = route_element_msg.lane_elements.size();
1004
1005 // create LaneElements for right adjacent lanes
1006 for (size_t a = 0; a < adjacent_right_lanelets_projected_points.size(); ++a) {
1007 route_planning_msgs::msg::LaneElement lane_element_msg;
1008 lane_element_msg.reference_pose.position =
1009 toRos(to3d(adjacent_right_lanelets_projected_points[a].centerline_point, point_z));
1010 // lane_element_msg.reference_pose.orientation computed in postprocessRouteMessage
1011 lane_element_msg.left_boundary.point = toRos(to3d(adjacent_right_lanelets_projected_points[a].left_bound_point, point_z));
1012 lane_element_msg.left_boundary.type = laneBoundaryType(adjacent_right_lanelets[a].leftBound2d());
1013 lane_element_msg.right_boundary.point =
1014 toRos(to3d(adjacent_right_lanelets_projected_points[a].right_bound_point, point_z));
1015 lane_element_msg.right_boundary.type = laneBoundaryType(adjacent_right_lanelets[a].rightBound2d());
1016 lane_element_msg.speed_limit =
1017 speedLimit(adjacent_right_lanelets[a], adjacent_right_lanelets_projected_points[a].centerline_point);
1018 lane_element_msg.regulatory_element_idcs = regulatory_element_extraction.adjacent_right_regulatory_element_idcs[a];
1019 const int computed_following_lane_idx =
1020 static_cast<int>(route_element_msg.lane_elements.size()) + following_lane_idx_offset;
1021 lane_element_msg.has_following_lane_idx = (computed_following_lane_idx >= 0 && computed_following_lane_idx < n_lanes);
1022 if (lane_element_msg.has_following_lane_idx) {
1023 lane_element_msg.following_lane_idx = computed_following_lane_idx;
1024 }
1025 std::tie(lane_element_msg.suggested_turn_signal,
1027 suggestedTurnSignal(adjacent_right_lanelets[a], this->get_logger());
1028 route_element_msg.lane_elements.push_back(lane_element_msg);
1029 lane_element_idx = route_element_msg.lane_elements.size();
1030 }
1031 }
1032 }
1033
1034 route_msg.header.stamp = latest_ego_data_.header.stamp;
1035
1036 // postprocess route message
1038
1039 // save as latest route message
1040 latest_route_msg_ = route_msg;
1041 has_enriched_route_ = true;
1042}
bool has_enriched_route_
Flag indicating that route has been enriched at least once.
lanelet::routing::Route latest_route_
Latest planned lanelet route.
route_planning_msgs::msg::Route latest_route_msg_
Latest route message to publish.
lanelet::routing::RoutingGraphUPtr routing_graph_
Lanelet routing graph for current map.
std::vector< std::vector< int > > latest_suggested_turn_signal_distance_ahead_by_route_element_by_lane_element_
Latest suggested turn signal distance ahead by route element by lane element.
std::vector< Eigen::Vector2d > latest_reference_line_
Latest complete dense reference line in the map frame.
std::vector< size_t > latest_lanelet_idx_by_reference_line_point_idx_
Latest mapping between global route reference line and lanelet indices.
std::unique_ptr< Lanelet2MapInterface > ll2_interface_
Lanelet2 map interface.
uint8_t laneBoundaryType(const lanelet::ConstLineString2d &line)
Extracts the lane boundary type of a lanelet line.
Definition utils.cpp:666
bool changesLaneFromPointToPoint(const Eigen::Vector2d &point, const Eigen::Vector2d &next_point, const double sampling_distance)
Identifies a lane change based on the distance between two reference line points.
Definition utils.cpp:177
size_t matchPointToLineString(const std::vector< Eigen::Vector2d > &line_string, const Eigen::Vector2d &point, const size_t idx_indication, const bool consider_order=false, const bool behind=true)
Finds the index of a point in a line string that is locally closest to another point.
Definition utils.cpp:94
LocalRouteWindow extractLocalRouteWindow(const route_planning_msgs::msg::Route &full_route, size_t current_global_idx, double distance_behind, double distance_ahead)
Extracts a local route window while preserving absolute route data.
Definition utils.cpp:1169
Eigen::Vector3d to3d(const Eigen::Vector2d &point)
Converts a 2D Eigen point to a 3D Eigen point.
ExtractRegulatoryElementsResult extractRegulatoryElements(const lanelet::ConstLanelet &lanelet, const std::vector< lanelet::ConstLanelet > &adjacent_left_lanelets, const std::vector< lanelet::ConstLanelet > &adjacent_right_lanelets, const PointSequence &point_sequence)
Extracts regulatory element information for a route element.
Definition utils.cpp:481
uint8_t speedLimit(const lanelet::ConstLanelet &lanelet, const bool consider_regulatory_elements=true)
Extracts the speed limit of a lanelet.
Definition utils.cpp:704
std::optional< int > computeFollowingLaneIdxOffset(const lanelet::ConstLanelet &lanelet, const lanelet::ConstLanelet &lanelet_of_next_point, const lanelet::routing::RoutingGraphUPtr &routing_graph)
Computes the offset of lane element indices from current to next route element.
Definition utils.cpp:252
geometry_msgs::msg::Point toRos(const Eigen::Vector2d &point)
Converts a 2D Eigen point to a ROS point.
void postprocessRouteMessage(route_planning_msgs::msg::Route &route_msg, std::vector< std::vector< int > > &suggested_turn_signal_distance_ahead_by_route_element_by_lane_element)
Postprocesses a route message, filling missing information that can be inferred from other message co...
Definition utils.cpp:1031
std::pair< Eigen::Vector2d, Eigen::Vector2d > extractDrivableSpace(const lanelet::LineStringLayer &line_string_layer, const PointSequence &point_sequence, const double max_distance)
Extracts drivable space boundaries for a route element.
Definition utils.cpp:375
std::vector< lanelet::ConstLanelet > adjacentLeftOrRightLanelets(const lanelet::ConstLanelet &lanelet, const lanelet::routing::RoutingGraphUPtr &routing_graph, bool left, bool sort_from_left=true)
Finds lanelets adjacent to the left or right of a given lanelet.
Definition utils.cpp:184
std::vector< ProjectedLaneletPoints > projectPointToLaneletLines(const Eigen::Vector2d &point, const Eigen::Vector2d &prev_point, const Eigen::Vector2d &next_point, const std::vector< lanelet::ConstLanelet > &lanelets, const rclcpp::Logger &logger=rclcpp::get_logger("lanelet2_route_planning"))
Projects a point to the centerline and bounds of a set of lanelets.
Definition utils.cpp:208
std::tuple< uint8_t, int > suggestedTurnSignal(const lanelet::ConstLanelet &lanelet, const rclcpp::Logger &logger)
Extracts the suggested turn signal of a lanelet.
Definition utils.cpp:833

◆ buildGlobalRouteMessage()

void lanelet2_route_planning::Lanelet2RoutePlanning::buildGlobalRouteMessage ( )
private

Builds a global ROS route message from the latest planned lanelet route.

The global route message only contains a global reference line along a single lane of the shortest path of the route.

Definition at line 736 of file lanelet2_route_planning.cpp.

736 {
737 // initialize the complete minimal route before deriving local and global views
738 route_planning_msgs::msg::Route route_msg;
739 route_msg.header.stamp = latest_ego_data_.header.stamp;
740 route_msg.header.frame_id = ll2_interface_->map_frame_id_;
741 route_msg.destination = destination_;
742 route_msg.intermediate_destinations = intermediate_destinations_;
743
744 // resample the shortest path to form the reference line
745 const lanelet::routing::LaneletPath shortest_path = latest_route_.shortestPath();
746 const auto resampling_result = resampleCenterlinesAlongPath(shortest_path, sampling_distance_, true);
747 const std::vector<Eigen::Vector3d>& shortest_path_centerline_3d = resampling_result.centerline;
748 const std::vector<Eigen::Vector2d> shortest_path_centerline = to2d(shortest_path_centerline_3d);
749 latest_reference_line_ = shortest_path_centerline;
750 latest_lanelet_idx_by_reference_line_point_idx_ = resampling_result.lanelet_idx_by_point;
751
752 // create one minimal route element for each reference-line point
753 double accumulated_distance = 0.0;
754 for (size_t c = 0; c < shortest_path_centerline.size(); ++c) {
755 const Eigen::Vector2d& point = shortest_path_centerline[c];
756 const Eigen::Vector3d& point_3d = shortest_path_centerline_3d[c];
757 const Eigen::Vector2d& prev_point = c > 0 ? shortest_path_centerline[c - 1] : point;
758 const Eigen::Vector2d& next_point = c + 1 < shortest_path_centerline.size() ? shortest_path_centerline[c + 1] : point;
759 const lanelet::ConstLanelet& lanelet = shortest_path[latest_lanelet_idx_by_reference_line_point_idx_[c]];
760 const bool changes_lane_from_prev_point =
761 changesLaneFromPointToPoint(prev_point, point, sampling_distance_); // NOLINT(readability-suspicious-call-argument)
762 const bool changes_lane_to_next_point = changesLaneFromPointToPoint(point, next_point, sampling_distance_);
763 const Eigen::Vector2d orientation = tangentOfPointAlongLineString(point, changes_lane_from_prev_point ? point : prev_point,
764 changes_lane_to_next_point ? point : next_point);
765 accumulated_distance += (point - prev_point).norm();
766 route_msg.route_elements.push_back(createMinimalRouteElement(toRos(point_3d), toRosQuaternion(orientation),
767 accumulated_distance, changes_lane_to_next_point,
768 speedLimit(lanelet, point)));
769 }
770
771 // optionally align route endpoints with the reference line
773 starting_point_ = toRos(projectPointToLineString(toEigen(starting_point_), shortest_path_centerline_3d));
774 for (auto& destination : intermediate_destinations_) {
775 destination = toRos(projectPointToLineString(toEigen(destination), shortest_path_centerline_3d));
776 }
777 destination_ = toRos(projectPointToLineString(toEigen(destination_), shortest_path_centerline_3d));
778 }
779 route_msg.destination = destination_;
780 route_msg.intermediate_destinations = intermediate_destinations_;
781 // locate the route endpoints and current position in the complete route
782 route_msg.starting_route_element_idx =
783 matchPointToLineString(shortest_path_centerline, toEigen2d(starting_point_), 0, true, true);
784 route_msg.current_route_element_idx = matchPointToLineString(shortest_path_centerline, toEigen2d(egoPosition(latest_ego_data_)),
785 route_msg.starting_route_element_idx, true, true);
786 route_msg.destination_route_element_idx =
787 indexOfLineStringPointClosestToPoint(shortest_path_centerline, toEigen2d(destination_), true, false);
788
789 has_enriched_route_ = false;
790 latest_route_msg_ = route_planning_msgs::msg::Route();
791 latest_full_route_msg_ = route_planning_msgs::msg::Route();
792 latest_global_route_msg_ = route_planning_msgs::msg::Route();
793
794 const size_t start_idx = route_msg.starting_route_element_idx;
795 const size_t destination_idx = route_msg.destination_route_element_idx;
796 if (start_idx >= route_msg.route_elements.size() || destination_idx >= route_msg.route_elements.size() ||
797 start_idx > destination_idx) {
798 RCLCPP_WARN(this->get_logger(), "Invalid start or destination index, not building global route");
799 return;
800 }
801
802 latest_full_route_msg_ = route_msg;
803
804 // retain only the route segment from start to destination for the global route
805 std::vector<Eigen::Vector2d> global_reference_line;
806 global_reference_line.reserve(destination_idx - start_idx + 1);
807 std::vector<size_t> break_after_indices;
808 for (size_t c = start_idx; c <= destination_idx; ++c) {
809 global_reference_line.push_back(shortest_path_centerline[c]);
810 if (c < destination_idx && route_msg.route_elements[c].will_change_suggested_lane) {
811 break_after_indices.push_back(c - start_idx);
812 }
813 }
814 // adaptively sample each continuous global-route segment
815 const std::vector<size_t> retained_indices =
816 adaptivelySampleLineString(global_reference_line, sampling_max_lateral_error_global_, break_after_indices);
817 if (retained_indices.empty()) {
818 RCLCPP_WARN(this->get_logger(), "Global reference line is empty, not building global route");
819 return;
820 }
821
822 latest_global_route_msg_ = route_msg;
823 latest_global_route_msg_.route_elements.clear();
824 latest_global_route_msg_.route_elements.reserve(retained_indices.size());
825 for (const size_t retained_idx : retained_indices) {
826 latest_global_route_msg_.route_elements.push_back(route_msg.route_elements[start_idx + retained_idx]);
827 }
828 // the global route contains one lane element per route element, which always continues in lane zero
829 for (size_t i = 0; i + 1 < latest_global_route_msg_.route_elements.size(); ++i) {
830 auto& lane_element = latest_global_route_msg_.route_elements[i].lane_elements[0];
831 lane_element.has_following_lane_idx = true;
832 lane_element.following_lane_idx = 0;
833 }
834 latest_global_route_msg_.route_elements.back().lane_elements[0].has_following_lane_idx = false;
835
836 latest_global_route_msg_.starting_route_element_idx = 0;
837 latest_global_route_msg_.destination_route_element_idx = latest_global_route_msg_.route_elements.size() - 1;
838 latest_global_route_msg_.current_route_element_idx = 0;
839 RCLCPP_INFO(this->get_logger(), "Built global route with %ld/%ld route elements", retained_indices.size(),
840 global_reference_line.size());
841}
geometry_msgs::msg::Point starting_point_
Starting point in map frame.
std::vector< geometry_msgs::msg::Point > intermediate_destinations_
Intermediate points in map frame.
route_planning_msgs::msg::Route latest_global_route_msg_
Latest adaptively sampled non-enriched global route.
Eigen::Vector2d tangentOfPointAlongLineString(const Eigen::Vector2d &point, const Eigen::Vector2d &prev_point, const Eigen::Vector2d &next_point)
Computes a unit vector tangential to a point along a line string.
Definition geometry.cpp:123
Eigen::Vector2d projectPointToLineString(const Eigen::Vector2d &point, const std::vector< Eigen::Vector2d > &line_string)
Projects a point to the closest line segment of a line string.
Definition geometry.cpp:231
std::vector< size_t > adaptivelySampleLineString(const std::vector< Eigen::Vector2d > &line_string, double max_lateral_error, const std::vector< size_t > &break_after_indices={})
Simplifies a 2D line string within a maximum lateral error.
Definition geometry.cpp:188
route_planning_msgs::msg::RouteElement createMinimalRouteElement(const geometry_msgs::msg::Point &position, const geometry_msgs::msg::Quaternion &orientation, double s=0.0, bool will_change_suggested_lane=false, uint8_t speed_limit=0)
Create a minimal route element message.
Definition utils.cpp:345
geometry_msgs::msg::Quaternion toRosQuaternion(const Eigen::Vector2d &vector)
Converts a 2D Eigen vector pointing in a specific direction to a ROS quaternion.
size_t indexOfLineStringPointClosestToPoint(const std::vector< Eigen::Vector2d > &line_string, const Eigen::Vector2d &point, const bool consider_order=false, const bool behind=true)
Finds the index of a point in a line string that is closest to another point.
Definition utils.cpp:67
Eigen::Vector2d to2d(const Eigen::Vector3d &point)
Converts a 3D Eigen point to a 2D Eigen point.
ResampleCenterlinesAlongPathResult resampleCenterlinesAlongPath(const lanelet::routing::LaneletPath &path, const double delta_s, bool monotonically)
Equidistantly resamples lanelet centerlines along a path to one joint centerline.
Definition utils.cpp:946
Eigen::Vector3d toEigen(const geometry_msgs::msg::Point &point)
Converts a ROS point to a 3D Eigen point.

◆ buildRoutingGraph()

bool lanelet2_route_planning::Lanelet2RoutePlanning::buildRoutingGraph ( )
private

Builds the lanelet2 routing graph based on the current map.

Returns
whether successful

Definition at line 295 of file lanelet2_route_planning.cpp.

295 {
296 if (!this->checkMap(false)) {
297 RCLCPP_ERROR(this->get_logger(), "Cannot build routing graph, map not loaded by '%s'", ll2_map_server_name_.c_str());
298 return false;
299 }
300
301 // get map and traffic rules
302 lanelet::LaneletMapConstPtr map = ll2_interface_->getMapPtr();
303 lanelet::traffic_rules::TrafficRulesPtr traffic_rules = getTrafficRules();
304
305 // build routing graph
306 routing_graph_ = lanelet::routing::RoutingGraph::build(*map, *traffic_rules);
307 lanelet::routing::Route::Errors errors = routing_graph_->checkValidity();
308 if (!errors.empty()) {
309 RCLCPP_ERROR(this->get_logger(), "Failed to build valid routing graph");
310 for (size_t i = 0; i < errors.size(); ++i) {
311 RCLCPP_ERROR_STREAM(this->get_logger(), errors[i]);
312 }
313 return false;
314 }
315
316 RCLCPP_INFO(this->get_logger(), "Successfully built routing graph");
317 return true;
318}
lanelet::traffic_rules::TrafficRulesPtr getTrafficRules()
Get traffic rules.
Definition utils.cpp:879

◆ checkMap()

bool lanelet2_route_planning::Lanelet2RoutePlanning::checkMap ( bool handle_update)
private

Checks if map is loaded and handles map updates.

Parameters
[in]handle_updatewhether to handle map update
Returns
whether map is loaded (and updated, if supposed to handle update)

Definition at line 222 of file lanelet2_route_planning.cpp.

222 {
223 bool map_status = ll2_interface_->map_loaded_;
224 // update routing graph on map update
225 if (handle_update && ll2_interface_->update_pending_ && ll2_interface_->map_loaded_) {
226 if (this->buildRoutingGraph()) {
227 ll2_interface_->update_pending_ = false;
228 }
229 map_status = map_status && !ll2_interface_->update_pending_;
230 }
231 {
232 std::scoped_lock lock(health_kv_mutex_);
233 health_kv_["map_loaded"] = map_status ? "true" : "false";
234 }
235 return map_status;
236}
bool buildRoutingGraph()
Builds the lanelet2 routing graph based on the current map.

◆ declareAndLoadParameter()

template<typename T >
void lanelet2_route_planning::Lanelet2RoutePlanning::declareAndLoadParameter ( const std::string & name,
T & param,
const std::string & description,
const bool add_to_auto_reconfigurable_params = true,
const bool is_required = false,
const bool read_only = false,
const std::optional< double > & from_value = std::nullopt,
const std::optional< double > & to_value = std::nullopt,
const std::optional< double > & step_value = std::nullopt,
const std::string & additional_constraints = "" )
private

Declares and loads a ROS parameter.

Parameters
[in]namename
[in]paramparameter variable to load into
[in]descriptiondescription
[in]add_to_auto_reconfigurable_paramsenable reconfiguration of parameter
[in]is_requiredwhether failure to load parameter will stop node
[in]read_onlyset parameter to read-only
[in]from_valueparameter range minimum
[in]to_valueparameter range maximum
[in]step_valueparameter range step
[in]additional_constraintsadditional constraints description

Definition at line 108 of file lanelet2_route_planning.cpp.

117 {
118 rcl_interfaces::msg::ParameterDescriptor param_desc;
119 param_desc.description = description;
120 param_desc.additional_constraints = additional_constraints;
121 param_desc.read_only = read_only;
122
123 auto type = rclcpp::ParameterValue(param).get_type();
124
125 if (from_value.has_value() && to_value.has_value()) {
126 if constexpr (std::is_integral_v<T>) {
127 rcl_interfaces::msg::IntegerRange range;
128 range.set__from_value(static_cast<T>(from_value.value())).set__to_value(static_cast<T>(to_value.value()));
129 if (step_value.has_value()) range.set__step(static_cast<T>(step_value.value()));
130 param_desc.integer_range = {range};
131 } else if constexpr (std::is_floating_point_v<T>) {
132 rcl_interfaces::msg::FloatingPointRange range;
133 range.set__from_value(static_cast<T>(from_value.value())).set__to_value(static_cast<T>(to_value.value()));
134 if (step_value.has_value()) range.set__step(static_cast<T>(step_value.value()));
135 param_desc.floating_point_range = {range};
136 } else {
137 RCLCPP_WARN(this->get_logger(), "Parameter type of parameter '%s' does not support specifying a range", name.c_str());
138 }
139 }
140
141 this->declare_parameter(name, type, param_desc);
142
143 try {
144 param = this->get_parameter(name).get_value<T>();
145 std::stringstream ss;
146 ss << "Loaded parameter '" << name << "': ";
147 if constexpr (is_vector_v<T>) {
148 ss << "[";
149 for (const auto& element : param) ss << element << (&element != &param.back() ? ", " : "");
150 ss << "]";
151 } else {
152 ss << param;
153 }
154 RCLCPP_INFO_STREAM(this->get_logger(), ss.str());
155 } catch (rclcpp::exceptions::ParameterUninitializedException&) {
156 if (is_required) {
157 RCLCPP_FATAL_STREAM(this->get_logger(), "Missing required parameter '" << name << "', exiting");
158 exit(EXIT_FAILURE);
159 } else {
160 std::stringstream ss;
161 ss << "Missing parameter '" << name << "', using default value: ";
162 if constexpr (is_vector_v<T>) {
163 ss << "[";
164 for (const auto& element : param) ss << element << (&element != &param.back() ? ", " : "");
165 ss << "]";
166 } else {
167 ss << param;
168 }
169 RCLCPP_WARN_STREAM(this->get_logger(), ss.str());
170 this->set_parameters({rclcpp::Parameter(name, rclcpp::ParameterValue(param))});
171 }
172 }
173
174 if (add_to_auto_reconfigurable_params) {
175 std::function<void(const rclcpp::Parameter&)> setter = [&param](const rclcpp::Parameter& p) { param = p.get_value<T>(); };
176 auto_reconfigurable_params_.push_back(std::make_tuple(name, setter));
177 }
178}
std::vector< std::tuple< std::string, std::function< void(const rclcpp::Parameter &)> > > auto_reconfigurable_params_
Auto-reconfigurable parameters for dynamic reconfiguration.

◆ egoDataCallback()

void lanelet2_route_planning::Lanelet2RoutePlanning::egoDataCallback ( const perception_msgs::msg::EgoData::SharedPtr msg)
private

Callback for EgoData.

Recomputes the local route if the node is currently publishing a route.

Parameters
[in]msg

Definition at line 320 of file lanelet2_route_planning.cpp.

320 {
321 ego_data_diagnostic_->tick(msg->header.stamp);
322
323 if (!this->checkMap(false)) {
324 return;
325 }
326
327 // transform ego data to map frame
328 if (msg->header.frame_id != ll2_interface_->map_frame_id_) {
329 try {
330 latest_ego_data_ = tf_buffer_->transform(*msg, ll2_interface_->map_frame_id_, tf2::durationFromSec(transform_timeout_));
331 } catch (tf2::TransformException& ex) {
332 std::stringstream ss;
333 ss << "Could not transform ego data from frame '" << msg->header.frame_id << "' to frame '" << ll2_interface_->map_frame_id_
334 << "': " << ex.what();
335 RCLCPP_ERROR_STREAM(this->get_logger(), ss.str());
336 {
337 std::scoped_lock lock(health_kv_mutex_);
338 health_kv_["latest_error"] = ss.str();
339 }
340 }
341 } else {
342 latest_ego_data_ = *msg;
343 }
344
345 // recompute local route
347 auto t0 = std::chrono::steady_clock::now();
349 auto t1 = std::chrono::steady_clock::now();
350 auto dt = std::chrono::duration_cast<std::chrono::duration<double>>(t1 - t0).count();
351 RCLCPP_DEBUG(this->get_logger(), "Recomputed route (%.3fs)", dt);
352 {
353 std::scoped_lock lock(health_kv_mutex_);
354 health_kv_["dt_buildEnrichedRouteMessage"] = std::to_string(dt);
355 }
356 }
357}
std::unique_ptr< tf2_ros::Buffer > tf_buffer_
Transform buffer.
std::unique_ptr< diagnostic_updater::TopicDiagnostic > ego_data_diagnostic_
Diagnostic to auto-diagnose ego data topic.
void buildEnrichedRouteMessage()
Builds an enriched ROS route message from the latest planned lanelet route.

◆ globalRoutePublishTimerCallback()

void lanelet2_route_planning::Lanelet2RoutePlanning::globalRoutePublishTimerCallback ( )
private

Callback to periodically publish the adaptively sampled global route.

Definition at line 406 of file lanelet2_route_planning.cpp.

406 {
408 if (!is_publishing_route_ || latest_global_route_msg_.route_elements.empty()) {
409 return;
410 }
411 std::vector<Eigen::Vector2d> reference_line;
412 reference_line.reserve(latest_global_route_msg_.route_elements.size());
413 for (const auto& route_element : latest_global_route_msg_.route_elements) {
414 if (route_element.lane_elements.empty()) {
415 return;
416 }
417 reference_line.push_back(toEigen2d(route_element.lane_elements.front().reference_pose.position));
418 }
419 latest_global_route_msg_.current_route_element_idx =
420 matchPointToLineString(reference_line, toEigen2d(egoPosition(latest_ego_data_)), 0, true, true);
421 latest_global_route_msg_.header.stamp = latest_ego_data_.header.stamp;
423}
std::unique_ptr< diagnostic_updater::HeaderlessTopicDiagnostic > global_route_timer_diagnostic_
Diagnostic to auto-diagnose global route timer frequency.
rclcpp::Publisher< route_planning_msgs::msg::Route >::SharedPtr publisher_global_route_
Publisher for the adaptively sampled global route.

◆ parametersCallback()

rcl_interfaces::msg::SetParametersResult lanelet2_route_planning::Lanelet2RoutePlanning::parametersCallback ( const std::vector< rclcpp::Parameter > & parameters)
private

Handles reconfiguration when a parameter value is changed.

Parameters
[in]parametersparameters
Returns
parameter change result

Definition at line 180 of file lanelet2_route_planning.cpp.

181 {
182 for (const auto& param : parameters) {
183 for (auto& auto_reconfigurable_param : auto_reconfigurable_params_) {
184 if (param.get_name() == std::get<0>(auto_reconfigurable_param)) {
185 std::get<1>(auto_reconfigurable_param)(param);
186 RCLCPP_INFO(this->get_logger(), "Reconfigured parameter '%s'", param.get_name().c_str());
187 break;
188 }
189 }
190 }
191
192 // parameter-specific reconfigurations
193 for (const auto& param : parameters) {
194 if (param.get_name() == "publish_frequency") {
195 publish_timer_->cancel();
196 publish_timer_ = this->create_wall_timer(std::chrono::duration<double>(1.0 / publish_frequency_),
198 } else if (param.get_name() == "publish_frequency_global") {
201 this->create_wall_timer(std::chrono::duration<double>(1.0 / publish_frequency_global_),
203 }
204 }
206 enrich_route_ahead_ego_distance_ = std::numeric_limits<double>::infinity();
207 }
209 enrich_route_behind_ego_distance_ = std::numeric_limits<double>::infinity();
210 }
211 if (max_num_threads_ <= 0) {
212 max_num_threads_ = omp_get_max_threads();
213 }
214 omp_set_num_threads(max_num_threads_);
215
216 rcl_interfaces::msg::SetParametersResult result;
217 result.successful = true;
218
219 return result;
220}
rclcpp::TimerBase::SharedPtr publish_timer_
Timer for publishing the enriched route.
rclcpp::TimerBase::SharedPtr global_route_publish_timer_
Timer for publishing the global route.
void globalRoutePublishTimerCallback()
Callback to periodically publish the adaptively sampled global route.
void publishTimerCallback()
Callback to periodically publish the route.

◆ planRoute()

bool lanelet2_route_planning::Lanelet2RoutePlanning::planRoute ( const geometry_msgs::msg::PointStamped & destination,
const std::vector< geometry_msgs::msg::PointStamped > & intermediate_destinations = {} )
private

Plans a lanelet route to the destination.

Planned lanelet route is stored in latest_route_.

Parameters
[in]destinationdestination
Returns
whether route planning was successful

Definition at line 578 of file lanelet2_route_planning.cpp.

579 {
580 if (!this->checkMap(false)) {
581 RCLCPP_ERROR(this->get_logger(), "Cannot plan route, map not loaded by '%s'", ll2_map_server_name_.c_str());
582 return false;
583 }
584
585 // transform destination to map frame
586 geometry_msgs::msg::PointStamped destination_map_stamped;
587 if (destination.header.frame_id != ll2_interface_->map_frame_id_) {
588 try {
589 destination_map_stamped =
590 tf_buffer_->transform(destination, ll2_interface_->map_frame_id_, tf2::durationFromSec(transform_timeout_));
591 } catch (tf2::TransformException& ex) {
592 std::stringstream ss;
593 ss << "Could not transform destination from frame '" << destination.header.frame_id << "' to frame '"
594 << ll2_interface_->map_frame_id_ << "': " << ex.what();
595 RCLCPP_ERROR_STREAM(this->get_logger(), ss.str());
596 {
597 std::scoped_lock lock(health_kv_mutex_);
598 health_kv_["latest_error"] = ss.str();
599 }
600 return false;
601 }
602 } else {
603 destination_map_stamped = destination;
604 }
605 geometry_msgs::msg::Point& destination_map = destination_map_stamped.point;
606
607 // transform intermediate destinations to map frame
608 std::vector<geometry_msgs::msg::Point> intermediate_destinations_map;
609 for (const auto& intermediate : intermediate_destinations) {
610 geometry_msgs::msg::PointStamped intermediate_map_stamped;
611 if (intermediate.header.frame_id != ll2_interface_->map_frame_id_) {
612 try {
613 intermediate_map_stamped =
614 tf_buffer_->transform(intermediate, ll2_interface_->map_frame_id_, tf2::durationFromSec(transform_timeout_));
615 } catch (tf2::TransformException& ex) {
616 std::stringstream ss;
617 ss << "Could not transform intermediate destination from frame '" << intermediate.header.frame_id << "' to frame '"
618 << ll2_interface_->map_frame_id_ << "': " << ex.what();
619 RCLCPP_ERROR_STREAM(this->get_logger(), ss.str());
620 {
621 std::scoped_lock lock(health_kv_mutex_);
622 health_kv_["latest_error"] = ss.str();
623 }
624 return false;
625 }
626 intermediate_destinations_map.push_back(intermediate_map_stamped.point);
627 } else {
628 intermediate_destinations_map.push_back(intermediate.point);
629 }
630 }
631
632 // get map and traffic rules
633 lanelet::LaneletMapConstPtr map = ll2_interface_->getMapPtr();
634 lanelet::traffic_rules::TrafficRulesPtr traffic_rules = getTrafficRules();
635
636 // check validity of ego data
637 const double timeout_ego_data = 1.0;
638 if ((this->now() - latest_ego_data_.header.stamp).seconds() > timeout_ego_data) {
639 RCLCPP_WARN(this->get_logger(), "Ego data is outdated by %.3fs > %.3fs",
640 (this->now() - latest_ego_data_.header.stamp).seconds(), timeout_ego_data);
641 }
642 if (latest_ego_data_.header.frame_id != ll2_interface_->map_frame_id_) {
643 std::stringstream ss;
644 ss << "Ego data frame '" << latest_ego_data_.header.frame_id << "' does not match map frame '"
645 << ll2_interface_->map_frame_id_ << "'";
646 RCLCPP_ERROR_STREAM(this->get_logger(), ss.str());
647 {
648 std::scoped_lock lock(health_kv_mutex_);
649 health_kv_["latest_error"] = ss.str();
650 }
651 return false;
652 }
653
654 // project ego position to lanelet
655 lanelet::ConstLanelet ego_ll;
656 if (auto result = laneletAtPoint(toEigen2d(egoPosition(latest_ego_data_)), map)) {
657 ego_ll = *result;
658 } else {
659 std::string msg = "Failed to find lanelet at ego position";
660 RCLCPP_ERROR_STREAM(this->get_logger(), msg);
661 {
662 std::scoped_lock lock(health_kv_mutex_);
663 health_kv_["latest_error"] = msg;
664 }
665 return false;
666 }
667 Eigen::Vector2d ego_ll_position =
668 projectPointToLineString(toEigen2d(egoPosition(latest_ego_data_)), toEigen(ego_ll.centerline2d().basicLineString()));
669
670 // project destination to lanelet
671 lanelet::ConstLanelet destination_ll;
672 if (auto result = laneletAtPoint(toEigen2d(destination_map), map)) {
673 destination_ll = *result;
674 } else {
675 std::string msg = "Failed to find lanelet at destination";
676 RCLCPP_ERROR_STREAM(this->get_logger(), msg);
677 {
678 std::scoped_lock lock(health_kv_mutex_);
679 health_kv_["latest_error"] = msg;
680 }
681 return false;
682 }
683 Eigen::Vector2d destination_ll_position =
684 projectPointToLineString(toEigen2d(destination_map), toEigen(destination_ll.centerline2d().basicLineString()));
685
686 // project intermediate destinations to lanelets
687 std::vector<lanelet::ConstLanelet> intermediate_destination_lls;
688 std::vector<geometry_msgs::msg::Point> intermediate_destinations_on_route;
689 for (const auto& intermediate : intermediate_destinations_map) {
690 lanelet::ConstLanelet intermediate_ll;
691 if (auto result = laneletAtPoint(toEigen2d(intermediate), map)) {
692 intermediate_destination_lls.push_back(*result);
693 intermediate_destinations_on_route.push_back(intermediate);
694 } else {
695 std::stringstream ss;
696 ss << "Failed to find lanelet at intermediate point (" << intermediate.x << ", " << intermediate.y << "), skipping";
697 RCLCPP_WARN_STREAM(this->get_logger(), ss.str());
698 {
699 std::scoped_lock lock(health_kv_mutex_);
700 health_kv_["latest_warning"] = ss.str();
701 }
702 continue; // skip this intermediate if no lanelet found
703 }
704 }
705
706 // undershoot/overshoot route endpoints to enable context before start position and behind destination
707 lanelet::ConstLanelet undershot_ego_ll =
709 lanelet::ConstLanelet overshot_destination_ll =
710 followLaneletsAlongRoutingGraph(routing_graph_, destination_ll, destination_ll_position, route_overshoot_distance_);
711
712 // compute route from start to destination along intermediate destinations
713 std::vector<lanelet::ConstLanelet> route_lanelets = {undershot_ego_ll};
714 route_lanelets.insert(route_lanelets.end(), intermediate_destination_lls.begin(), intermediate_destination_lls.end());
715 route_lanelets.push_back(overshot_destination_ll);
716 std::optional<lanelet::routing::Route> planned_route = getRoute(routing_graph_, route_lanelets);
717
718 if (planned_route) {
720 destination_ = destination_map;
721 intermediate_destinations_ = intermediate_destinations_on_route;
722 latest_route_ = std::move(*planned_route);
723 return true;
724 } else {
725 std::stringstream ss;
726 ss << "Failed to plan route from lanelet " << ego_ll.id() << " to lanelet " << destination_ll.id();
727 RCLCPP_ERROR_STREAM(this->get_logger(), ss.str());
728 {
729 std::scoped_lock lock(health_kv_mutex_);
730 health_kv_["latest_error"] = ss.str();
731 }
732 return false;
733 }
734}
lanelet::ConstLanelet followLaneletsAlongRoutingGraph(const lanelet::routing::RoutingGraphUPtr &routing_graph, const lanelet::ConstLanelet &lanelet, const Eigen::Vector2d &position, const double distance)
Follows a lanelet's and following lanelets' centerline for a given distance.
Definition utils.cpp:914
std::optional< lanelet::routing::Route > getRoute(const lanelet::routing::RoutingGraphUPtr &routing_graph, const std::vector< lanelet::ConstLanelet > &route_lanelets)
Computes a route from start to destination along intermediate destinations.
Definition utils.cpp:26
std::optional< lanelet::ConstLanelet > laneletAtPoint(const Eigen::Vector2d &point, const lanelet::LaneletMapConstPtr &map, const std::optional< lanelet::traffic_rules::TrafficRulesPtr > traffic_rules=std::nullopt)
Find lanelet at arbitrary point.
Definition utils.cpp:885

◆ publishHealth()

void lanelet2_route_planning::Lanelet2RoutePlanning::publishHealth ( const unsigned char status,
const std::string & msg,
const rclcpp::Time & now )
private

Publishes health diagnostic.

Parameters
statusstatus code
msgstatus message
nowcurrent time for stamping

Definition at line 1044 of file lanelet2_route_planning.cpp.

1044 {
1045 diagnostic_msgs::msg::DiagnosticArray diagnostics;
1046 diagnostics.header.stamp = now;
1047 auto& health = diagnostics.status.emplace_back();
1048 health.name = this->get_fully_qualified_name() + std::string(": health");
1049 health.hardware_id = "none";
1050 health.level = status;
1051 health.message = msg;
1052 std::map<std::string, std::string> health_kv_snapshot;
1053 {
1054 std::scoped_lock lock(health_kv_mutex_);
1055 health_kv_snapshot = health_kv_;
1056 }
1057 for (const auto& [key, value] : health_kv_snapshot) {
1058 auto& key_value = health.values.emplace_back();
1059 key_value.key = key;
1060 key_value.value = value;
1061 }
1062
1063 health_diagnostic_pub_->publish(diagnostics);
1064}
rclcpp::Publisher< diagnostic_msgs::msg::DiagnosticArray >::SharedPtr health_diagnostic_pub_
Health diagnostic publisher.

◆ publishTimerCallback()

void lanelet2_route_planning::Lanelet2RoutePlanning::publishTimerCallback ( )
private

Callback to periodically publish the route.

Definition at line 359 of file lanelet2_route_planning.cpp.

359 {
363 }
364
365 // check health
366 unsigned char health_status = diagnostic_msgs::msg::DiagnosticStatus::OK;
367 std::string health_msg = "OK";
368 std::map<std::string, std::string> health_kv_snapshot;
369 {
370 std::scoped_lock lock(health_kv_mutex_);
371 health_kv_snapshot = health_kv_;
372 }
373 if (health_kv_snapshot.count("map_loaded") > 0 && health_kv_snapshot["map_loaded"] == "false") {
374 // map not loaded
375 health_status = diagnostic_msgs::msg::DiagnosticStatus::ERROR;
376 health_msg = "Map not loaded";
377 } else if (health_kv_snapshot.count("latest_error") > 0) {
378 // at least one error
379 health_status = diagnostic_msgs::msg::DiagnosticStatus::ERROR;
380 health_msg = health_kv_snapshot["latest_error"];
381 } else if (health_kv_snapshot.count("latest_warning") > 0) {
382 // at least one warning
383 health_status = diagnostic_msgs::msg::DiagnosticStatus::WARN;
384 health_msg = health_kv_snapshot["latest_warning"];
385 } else if (health_kv_snapshot.count("dt_buildEnrichedRouteMessage") > 0) {
386 // enrichment cannot keep up with ego data
387 double dt = std::stod(health_kv_snapshot["dt_buildEnrichedRouteMessage"]);
388 double callback_freq = ego_data_diagnostic_config_.max_frequency;
389 if (callback_freq > 0.0 && dt > 1.0 / callback_freq) {
390 health_status = diagnostic_msgs::msg::DiagnosticStatus::WARN;
391 health_msg = "Building enriched route takes longer than ego data frequency allows";
392 }
393 }
394
395 // publish health diagnostics
396 this->publishHealth(health_status, health_msg, this->now());
397
398 // reset latest warning and error
399 {
400 std::scoped_lock lock(health_kv_mutex_);
401 health_kv_.erase("latest_warning");
402 health_kv_.erase("latest_error");
403 }
404}
rclcpp::Publisher< route_planning_msgs::msg::Route >::SharedPtr publisher_route_
Publisher for enriched route.
std::unique_ptr< diagnostic_updater::HeaderlessTopicDiagnostic > route_timer_diagnostic_
Diagnostic to auto-diagnose route timer frequency.
void publishHealth(const unsigned char status, const std::string &msg, const rclcpp::Time &now)
Publishes health diagnostic.

◆ setup()

void lanelet2_route_planning::Lanelet2RoutePlanning::setup ( )
private

Sets up subscribers, publishers, etc. to configure the node.

Definition at line 238 of file lanelet2_route_planning.cpp.

238 {
239 // map interface
240 ll2_interface_ = std::make_unique<Lanelet2MapInterface>(*this, ll2_map_server_name_);
241
242 // callback for dynamic parameter configuration
244 this->add_on_set_parameters_callback(std::bind(&Lanelet2RoutePlanning::parametersCallback, this, std::placeholders::_1));
245
246 // tf transform listener
247 tf_buffer_ = std::make_unique<tf2_ros::Buffer>(this->get_clock());
248 tf_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);
249
250 // publishers
251 publisher_route_ = this->create_publisher<route_planning_msgs::msg::Route>("~/route", 1);
252 publisher_global_route_ = this->create_publisher<route_planning_msgs::msg::Route>("~/global_route", 1);
253 publish_timer_ = this->create_wall_timer(std::chrono::duration<double>(1.0 / publish_frequency_),
255 global_route_publish_timer_ = this->create_wall_timer(std::chrono::duration<double>(1.0 / publish_frequency_global_),
257 is_publishing_route_ = false;
258 RCLCPP_INFO(this->get_logger(), "Publishing enriched-only route to '%s'", publisher_route_->get_topic_name());
259 RCLCPP_INFO(this->get_logger(), "Publishing non-enriched global route to '%s'", publisher_global_route_->get_topic_name());
260
261 // subscribers
262 subscriber_ego_data_ = this->create_subscription<perception_msgs::msg::EgoData>(
263 "~/ego_data", 1, std::bind(&Lanelet2RoutePlanning::egoDataCallback, this, std::placeholders::_1));
264 RCLCPP_INFO(this->get_logger(), "Subscribed to '%s'", subscriber_ego_data_->get_topic_name());
265
266 // action server for handling action goal requests
267 action_callback_group_ = this->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
268 action_server_ = rclcpp_action::create_server<route_planning_msgs::action::PlanRoute>(
269 this, "~/plan_route",
270 std::bind(&Lanelet2RoutePlanning::actionHandleGoal, this, std::placeholders::_1, std::placeholders::_2),
271 std::bind(&Lanelet2RoutePlanning::actionHandleCancel, this, std::placeholders::_1),
272 std::bind(&Lanelet2RoutePlanning::actionHandleAccepted, this, std::placeholders::_1),
273 rcl_action_server_get_default_options(), action_callback_group_);
274 RCLCPP_INFO(this->get_logger(), "Action server started");
275
276 // set up health diagnostic publisher and diagnostic updater for monitoring topic frequencies and timestamps
277 health_diagnostic_pub_ = this->create_publisher<diagnostic_msgs::msg::DiagnosticArray>("/diagnostics", 1);
278 diagnostic_updater_.setHardwareID("none");
279 ego_data_diagnostic_ = std::make_unique<diagnostic_updater::TopicDiagnostic>(
280 "~/ego_data", diagnostic_updater_,
281 diagnostic_updater::FrequencyStatusParam(&ego_data_diagnostic_config_.min_frequency,
283 diagnostic_updater::TimeStampStatusParam(ego_data_diagnostic_config_.min_acceptable_timestamp_delta,
285 route_timer_diagnostic_ = std::make_unique<diagnostic_updater::HeaderlessTopicDiagnostic>(
286 "route_timer", diagnostic_updater_,
287 diagnostic_updater::FrequencyStatusParam(&route_timer_diagnostic_config_.min_frequency,
289 global_route_timer_diagnostic_ = std::make_unique<diagnostic_updater::HeaderlessTopicDiagnostic>(
290 "global_route_timer", diagnostic_updater_,
291 diagnostic_updater::FrequencyStatusParam(&global_route_timer_diagnostic_config_.min_frequency,
293}
rcl_interfaces::msg::SetParametersResult parametersCallback(const std::vector< rclcpp::Parameter > &parameters)
Handles reconfiguration when a parameter value is changed.
void egoDataCallback(const perception_msgs::msg::EgoData::SharedPtr msg)
Callback for EgoData.
rclcpp_action::GoalResponse actionHandleGoal(const rclcpp_action::GoalUUID &uuid, std::shared_ptr< const route_planning_msgs::action::PlanRoute::Goal > goal)
Action goal callback: processes a route planning request.
std::shared_ptr< tf2_ros::TransformListener > tf_listener_
Transform listener.
rclcpp::Subscription< perception_msgs::msg::EgoData >::SharedPtr subscriber_ego_data_
Subscriber for ego data.
void actionHandleAccepted(const std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > goal_handle)
Action accepted callback: starts action execution.
OnSetParametersCallbackHandle::SharedPtr parameters_callback_
Callback handle for dynamic parameter reconfiguration.
rclcpp_action::CancelResponse actionHandleCancel(const std::shared_ptr< rclcpp_action::ServerGoalHandle< route_planning_msgs::action::PlanRoute > > goal_handle)
Action cancel callback: cancels a running action.
rclcpp::CallbackGroup::SharedPtr action_callback_group_
Callback group for action server.
rclcpp_action::Server< route_planning_msgs::action::PlanRoute >::SharedPtr action_server_
Action server.

Member Data Documentation

◆ action_callback_group_

rclcpp::CallbackGroup::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::action_callback_group_
private

Callback group for action server.

Definition at line 280 of file lanelet2_route_planning.hpp.

◆ action_feedback_

route_planning_msgs::action::PlanRoute::Feedback::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::action_feedback_
private

Latest action feedback.

Definition at line 265 of file lanelet2_route_planning.hpp.

◆ action_feedback_frequency_

double lanelet2_route_planning::Lanelet2RoutePlanning::action_feedback_frequency_ = 1.0
private

Frequency of action feedback publication [Hz] (parameter)

Definition at line 398 of file lanelet2_route_planning.hpp.

◆ action_goal_handle_

std::shared_ptr<rclcpp_action::ServerGoalHandle<route_planning_msgs::action::PlanRoute> > lanelet2_route_planning::Lanelet2RoutePlanning::action_goal_handle_
private

Latest action goal handle.

Definition at line 275 of file lanelet2_route_planning.hpp.

◆ action_result_

route_planning_msgs::action::PlanRoute::Result::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::action_result_
private

Latest action result.

Definition at line 270 of file lanelet2_route_planning.hpp.

◆ action_server_

rclcpp_action::Server<route_planning_msgs::action::PlanRoute>::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::action_server_
private

Action server.

Definition at line 260 of file lanelet2_route_planning.hpp.

◆ action_start_time_

rclcpp::Time lanelet2_route_planning::Lanelet2RoutePlanning::action_start_time_
private

Latest action start time to compute action duration.

Definition at line 285 of file lanelet2_route_planning.hpp.

◆ auto_reconfigurable_params_

std::vector<std::tuple<std::string, std::function<void(const rclcpp::Parameter&)> > > lanelet2_route_planning::Lanelet2RoutePlanning::auto_reconfigurable_params_
private

Auto-reconfigurable parameters for dynamic reconfiguration.

Definition at line 225 of file lanelet2_route_planning.hpp.

◆ destination_

geometry_msgs::msg::Point lanelet2_route_planning::Lanelet2RoutePlanning::destination_
private

Destination point in map frame.

This is affected by project_destination_to_reference_line_.

Definition at line 324 of file lanelet2_route_planning.hpp.

◆ destination_distance_threshold_

double lanelet2_route_planning::Lanelet2RoutePlanning::destination_distance_threshold_ = 1.0
private

Distance to destination where destination is considered reached [m] (parameter)

Definition at line 423 of file lanelet2_route_planning.hpp.

◆ diagnostic_updater_

diagnostic_updater::Updater lanelet2_route_planning::Lanelet2RoutePlanning::diagnostic_updater_
private

Diagnostic updater for monitoring topic frequencies and timestamps.

Definition at line 483 of file lanelet2_route_planning.hpp.

◆ ego_data_diagnostic_

std::unique_ptr<diagnostic_updater::TopicDiagnostic> lanelet2_route_planning::Lanelet2RoutePlanning::ego_data_diagnostic_
private

Diagnostic to auto-diagnose ego data topic.

Definition at line 488 of file lanelet2_route_planning.hpp.

◆ ego_data_diagnostic_config_

TopicDiagnosticConfig lanelet2_route_planning::Lanelet2RoutePlanning::ego_data_diagnostic_config_ = {45.45, 55.55, 0.0, 0.002}
private

Configuration for auto-diagnosed ego data topic.

Definition at line 503 of file lanelet2_route_planning.hpp.

503{45.45, 55.55, 0.0, 0.002};

◆ enrich_route_ahead_ego_distance_

double lanelet2_route_planning::Lanelet2RoutePlanning::enrich_route_ahead_ego_distance_ = 100.0
private

Distance ahead of ego position where global route is enriched with more information [m] (negative=unlimited) (parameter)

Definition at line 433 of file lanelet2_route_planning.hpp.

◆ enrich_route_behind_ego_distance_

double lanelet2_route_planning::Lanelet2RoutePlanning::enrich_route_behind_ego_distance_ = 10.0
private

Distance behind ego position where global route is enriched with more information [m] (negative=unlimited) (parameter)

Definition at line 438 of file lanelet2_route_planning.hpp.

◆ global_route_publish_timer_

rclcpp::TimerBase::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::global_route_publish_timer_
private

Timer for publishing the global route.

Definition at line 255 of file lanelet2_route_planning.hpp.

◆ global_route_timer_diagnostic_

std::unique_ptr<diagnostic_updater::HeaderlessTopicDiagnostic> lanelet2_route_planning::Lanelet2RoutePlanning::global_route_timer_diagnostic_
private

Diagnostic to auto-diagnose global route timer frequency.

Definition at line 498 of file lanelet2_route_planning.hpp.

◆ global_route_timer_diagnostic_config_

TopicDiagnosticConfig lanelet2_route_planning::Lanelet2RoutePlanning::global_route_timer_diagnostic_config_ = {0.91, 1.11}
private

Configuration for auto-diagnosed global route timer.

Definition at line 513 of file lanelet2_route_planning.hpp.

513{0.91, 1.11};

◆ has_enriched_route_

bool lanelet2_route_planning::Lanelet2RoutePlanning::has_enriched_route_ = false
private

Flag indicating that route has been enriched at least once.

Useful because the initial non-enriched global route is invalid as traveled and remaining route are not yet split.

Definition at line 344 of file lanelet2_route_planning.hpp.

◆ health_diagnostic_pub_

rclcpp::Publisher<diagnostic_msgs::msg::DiagnosticArray>::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::health_diagnostic_pub_
private

Health diagnostic publisher.

Definition at line 478 of file lanelet2_route_planning.hpp.

◆ health_kv_

std::map<std::string, std::string> lanelet2_route_planning::Lanelet2RoutePlanning::health_kv_
private

Health key-value pairs for diagnostic message.

Definition at line 468 of file lanelet2_route_planning.hpp.

◆ health_kv_mutex_

std::mutex lanelet2_route_planning::Lanelet2RoutePlanning::health_kv_mutex_
mutableprivate

Mutex protecting health key-value pairs across threads.

Definition at line 473 of file lanelet2_route_planning.hpp.

◆ intermediate_destinations_

std::vector<geometry_msgs::msg::Point> lanelet2_route_planning::Lanelet2RoutePlanning::intermediate_destinations_
private

Intermediate points in map frame.

Used for route planning with intermediate waypoints. These are affected by project_destination_to_reference_line_.

Definition at line 332 of file lanelet2_route_planning.hpp.

◆ is_publishing_route_

bool lanelet2_route_planning::Lanelet2RoutePlanning::is_publishing_route_
private

Controlling flag for route publication.

Definition at line 349 of file lanelet2_route_planning.hpp.

◆ latest_ego_data_

perception_msgs::msg::EgoData lanelet2_route_planning::Lanelet2RoutePlanning::latest_ego_data_
private

Latest ego data in map frame.

Definition at line 300 of file lanelet2_route_planning.hpp.

◆ latest_full_route_msg_

route_planning_msgs::msg::Route lanelet2_route_planning::Lanelet2RoutePlanning::latest_full_route_msg_
private

Latest complete minimal route used internally for progress tracking.

Definition at line 359 of file lanelet2_route_planning.hpp.

◆ latest_global_route_msg_

route_planning_msgs::msg::Route lanelet2_route_planning::Lanelet2RoutePlanning::latest_global_route_msg_
private

Latest adaptively sampled non-enriched global route.

Definition at line 362 of file lanelet2_route_planning.hpp.

◆ latest_lanelet_idx_by_reference_line_point_idx_

std::vector<size_t> lanelet2_route_planning::Lanelet2RoutePlanning::latest_lanelet_idx_by_reference_line_point_idx_
private

Latest mapping between global route reference line and lanelet indices.

Used to easily find lanelet for a given point on the global reference line. Indexes into latest_route_.shortestPath().

Definition at line 375 of file lanelet2_route_planning.hpp.

◆ latest_reference_line_

std::vector<Eigen::Vector2d> lanelet2_route_planning::Lanelet2RoutePlanning::latest_reference_line_
private

Latest complete dense reference line in the map frame.

Definition at line 367 of file lanelet2_route_planning.hpp.

◆ latest_route_

lanelet::routing::Route lanelet2_route_planning::Lanelet2RoutePlanning::latest_route_
private

Latest planned lanelet route.

Definition at line 337 of file lanelet2_route_planning.hpp.

◆ latest_route_msg_

route_planning_msgs::msg::Route lanelet2_route_planning::Lanelet2RoutePlanning::latest_route_msg_
private

Latest route message to publish.

Definition at line 354 of file lanelet2_route_planning.hpp.

◆ latest_suggested_turn_signal_distance_ahead_by_route_element_by_lane_element_

std::vector<std::vector<int> > lanelet2_route_planning::Lanelet2RoutePlanning::latest_suggested_turn_signal_distance_ahead_by_route_element_by_lane_element_
private

Latest suggested turn signal distance ahead by route element by lane element.

Used to store the suggested turn signal distances ahead for each lane element, which can only be propagated to preceding lane elements during postprocessing.

Definition at line 383 of file lanelet2_route_planning.hpp.

◆ ll2_interface_

std::unique_ptr<Lanelet2MapInterface> lanelet2_route_planning::Lanelet2RoutePlanning::ll2_interface_
private

Lanelet2 map interface.

Definition at line 305 of file lanelet2_route_planning.hpp.

◆ ll2_map_server_name_

std::string lanelet2_route_planning::Lanelet2RoutePlanning::ll2_map_server_name_ = "lanelet2_map_server"
private

Name of lanelet2_map_server node (parameter)

Definition at line 388 of file lanelet2_route_planning.hpp.

◆ max_drivable_space_radius_

double lanelet2_route_planning::Lanelet2RoutePlanning::max_drivable_space_radius_ = 50.0
private

Maximum distance to left/right drivable space bounds, if not otherwise restricted [m] (parameter)

Definition at line 453 of file lanelet2_route_planning.hpp.

◆ max_num_threads_

int lanelet2_route_planning::Lanelet2RoutePlanning::max_num_threads_ = 0
private

Maximum number of threads for parallel processing (0=max available) (parameter)

Definition at line 458 of file lanelet2_route_planning.hpp.

◆ parameters_callback_

OnSetParametersCallbackHandle::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::parameters_callback_
private

Callback handle for dynamic parameter reconfiguration.

Definition at line 230 of file lanelet2_route_planning.hpp.

◆ project_destination_to_reference_line_

bool lanelet2_route_planning::Lanelet2RoutePlanning::project_destination_to_reference_line_ = true
private

Whether to project destination to reference line (parameter)

Definition at line 418 of file lanelet2_route_planning.hpp.

◆ publish_frequency_

double lanelet2_route_planning::Lanelet2RoutePlanning::publish_frequency_ = 10.0
private

Frequency of route publication [Hz] (parameter)

Definition at line 393 of file lanelet2_route_planning.hpp.

◆ publish_frequency_global_

double lanelet2_route_planning::Lanelet2RoutePlanning::publish_frequency_global_ = 1.0
private

Frequency of global route publication [Hz] (parameter)

Definition at line 403 of file lanelet2_route_planning.hpp.

◆ publish_timer_

rclcpp::TimerBase::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::publish_timer_
private

Timer for publishing the enriched route.

Definition at line 250 of file lanelet2_route_planning.hpp.

◆ publisher_global_route_

rclcpp::Publisher<route_planning_msgs::msg::Route>::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::publisher_global_route_
private

Publisher for the adaptively sampled global route.

Definition at line 245 of file lanelet2_route_planning.hpp.

◆ publisher_route_

rclcpp::Publisher<route_planning_msgs::msg::Route>::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::publisher_route_
private

Publisher for enriched route.

Definition at line 240 of file lanelet2_route_planning.hpp.

◆ required_traveled_distance_proportion_

double lanelet2_route_planning::Lanelet2RoutePlanning::required_traveled_distance_proportion_ = 0.5
private

Proportion of route length that must have been traveled before considering destination reached [0..1] (parameter)

Definition at line 428 of file lanelet2_route_planning.hpp.

◆ route_overshoot_distance_

double lanelet2_route_planning::Lanelet2RoutePlanning::route_overshoot_distance_ = 0.0
private

Overshoot route by this distance behind destination [m] (parameter)

Definition at line 448 of file lanelet2_route_planning.hpp.

◆ route_timer_diagnostic_

std::unique_ptr<diagnostic_updater::HeaderlessTopicDiagnostic> lanelet2_route_planning::Lanelet2RoutePlanning::route_timer_diagnostic_
private

Diagnostic to auto-diagnose route timer frequency.

Definition at line 493 of file lanelet2_route_planning.hpp.

◆ route_timer_diagnostic_config_

TopicDiagnosticConfig lanelet2_route_planning::Lanelet2RoutePlanning::route_timer_diagnostic_config_ = {18.18, 22.22}
private

Configuration for auto-diagnosed route timer.

Definition at line 508 of file lanelet2_route_planning.hpp.

508{18.18, 22.22};

◆ route_undershoot_distance_

double lanelet2_route_planning::Lanelet2RoutePlanning::route_undershoot_distance_ = 0.0
private

Undershoot route by this distance before ego position [m] (parameter)

Definition at line 443 of file lanelet2_route_planning.hpp.

◆ routing_graph_

lanelet::routing::RoutingGraphUPtr lanelet2_route_planning::Lanelet2RoutePlanning::routing_graph_
private

Lanelet routing graph for current map.

Definition at line 310 of file lanelet2_route_planning.hpp.

◆ sampling_distance_

double lanelet2_route_planning::Lanelet2RoutePlanning::sampling_distance_ = 1.0
private

Distance between resampled points along route [m] (parameter)

Definition at line 408 of file lanelet2_route_planning.hpp.

◆ sampling_max_lateral_error_global_

double lanelet2_route_planning::Lanelet2RoutePlanning::sampling_max_lateral_error_global_ = 0.5
private

Maximum lateral error of the adaptively sampled global reference line [m] (parameter)

Definition at line 413 of file lanelet2_route_planning.hpp.

◆ starting_point_

geometry_msgs::msg::Point lanelet2_route_planning::Lanelet2RoutePlanning::starting_point_
private

Starting point in map frame.

This is affected by project_destination_to_reference_line_.

Definition at line 317 of file lanelet2_route_planning.hpp.

◆ subscriber_ego_data_

rclcpp::Subscription<perception_msgs::msg::EgoData>::SharedPtr lanelet2_route_planning::Lanelet2RoutePlanning::subscriber_ego_data_
private

Subscriber for ego data.

Definition at line 235 of file lanelet2_route_planning.hpp.

◆ tf_buffer_

std::unique_ptr<tf2_ros::Buffer> lanelet2_route_planning::Lanelet2RoutePlanning::tf_buffer_
private

Transform buffer.

Definition at line 290 of file lanelet2_route_planning.hpp.

◆ tf_listener_

std::shared_ptr<tf2_ros::TransformListener> lanelet2_route_planning::Lanelet2RoutePlanning::tf_listener_
private

Transform listener.

Definition at line 295 of file lanelet2_route_planning.hpp.

◆ transform_timeout_

double lanelet2_route_planning::Lanelet2RoutePlanning::transform_timeout_ = 0.02
private

How long to wait for a transform to be available [s] (parameter)

Definition at line 463 of file lanelet2_route_planning.hpp.


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