15 #include "nav2_route/route_server.hpp"
17 using std::placeholders::_1;
18 using std::placeholders::_2;
24 : nav2::LifecycleNode(
"route_server",
"", options)
30 RCLCPP_INFO(get_logger(),
"Configuring");
32 tf_ = nav2::create_transform_buffer(
this);
33 transform_listener_ = nav2::create_transform_listener(*tf_,
this,
true);
36 graph_vis_publisher_ =
37 node->create_publisher<visualization_msgs::msg::MarkerArray>(
40 route_publisher_ = create_publisher<nav2_msgs::msg::Route>(
"route");
42 compute_route_server_ = create_action_server<ComputeRoute>(
45 nullptr,
nullptr, std::chrono::milliseconds(500),
true);
47 compute_and_track_route_server_ = create_action_server<ComputeAndTrackRoute>(
48 "compute_and_track_route",
49 std::bind(&RouteServer::computeAndTrackRoute,
this),
50 nullptr,
nullptr, std::chrono::milliseconds(500),
true);
52 set_graph_service_ = node->create_service<nav2_msgs::srv::SetRouteGraph>(
53 std::string(node->get_name()) +
"/set_route_graph",
56 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
59 "route_frame", std::string(
"map"));
61 "base_frame", std::string(
"base_link"));
63 "max_planning_time", 2.0);
67 "costmap_topic", std::string(
"global_costmap/costmap_raw"));
68 costmap_subscriber_ = std::make_shared<nav2_costmap_2d::CostmapSubscriber>(node, costmap_topic);
71 graph_loader_ = std::make_shared<GraphLoader>(node, tf_, route_frame_);
72 if (!graph_loader_->loadGraphFromParameter(graph_, id_to_graph_map_)) {
73 return nav2::CallbackReturn::FAILURE;
76 goal_intent_extractor_ = std::make_shared<GoalIntentExtractor>();
77 goal_intent_extractor_->configure(
78 node, graph_, &id_to_graph_map_, tf_, costmap_subscriber_, route_frame_, base_frame_);
80 route_planner_ = std::make_shared<RoutePlanner>();
81 route_planner_->configure(node, tf_, costmap_subscriber_);
83 route_tracker_ = std::make_shared<RouteTracker>();
84 route_tracker_->configure(
85 node, tf_, costmap_subscriber_, compute_and_track_route_server_, route_frame_, base_frame_);
87 path_converter_ = std::make_shared<PathConverter>();
88 path_converter_->configure(node);
89 }
catch (std::exception & e) {
90 RCLCPP_FATAL(get_logger(),
"Failed to configure route server: %s", e.what());
91 return nav2::CallbackReturn::FAILURE;
94 return nav2::CallbackReturn::SUCCESS;
100 RCLCPP_INFO(get_logger(),
"Activating");
101 compute_route_server_->activate();
102 compute_and_track_route_server_->activate();
103 graph_vis_publisher_->on_activate();
104 graph_vis_publisher_->publish(utils::toMsg(graph_, route_frame_, this->now()));
105 route_publisher_->on_activate();
107 return nav2::CallbackReturn::SUCCESS;
113 RCLCPP_INFO(get_logger(),
"Deactivating");
114 compute_route_server_->deactivate();
115 compute_and_track_route_server_->deactivate();
116 graph_vis_publisher_->on_deactivate();
117 route_publisher_->on_deactivate();
119 return nav2::CallbackReturn::SUCCESS;
125 RCLCPP_INFO(get_logger(),
"Cleaning up");
126 compute_route_server_.reset();
127 compute_and_track_route_server_.reset();
128 set_graph_service_.reset();
129 graph_loader_.reset();
130 route_planner_.reset();
131 route_tracker_.reset();
132 path_converter_.reset();
133 goal_intent_extractor_.reset();
134 graph_vis_publisher_.reset();
135 route_publisher_.reset();
136 transform_listener_.reset();
139 return nav2::CallbackReturn::SUCCESS;
145 RCLCPP_INFO(get_logger(),
"Shutting down");
146 return nav2::CallbackReturn::SUCCESS;
152 auto cycle_duration = this->now() - start_time;
153 if (max_planning_time_ > 0.0 && cycle_duration.seconds() > max_planning_time_) {
156 "Route planner missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz",
157 1 / max_planning_time_, 1 / cycle_duration.seconds());
160 return cycle_duration;
163 template<
typename ActionT>
166 typename nav2::SimpleActionServer<ActionT>::SharedPtr & action_server)
169 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
174 RCLCPP_INFO(get_logger(),
"Goal was canceled. Canceling route planning action.");
179 if (graph_.empty()) {
180 RCLCPP_INFO(get_logger(),
"No graph set! Aborting request.");
189 std::shared_ptr<ComputeRoute::Result> result,
191 const nav_msgs::msg::Path & path,
192 const rclcpp::Duration & planning_duration)
194 result->route = utils::toMsg(route, route_frame_, this->now());
196 result->planning_time = planning_duration;
200 std::shared_ptr<ComputeAndTrackRoute::Result> result,
202 const nav_msgs::msg::Path &,
203 const rclcpp::Duration & execution_duration)
205 result->execution_duration = execution_duration;
208 template<
typename GoalT>
210 const std::shared_ptr<const GoalT> goal,
214 auto [start_route, end_route] = goal_intent_extractor_->findStartandGoal(goal);
217 if (rerouting_info.rerouting_start_id != std::numeric_limits<unsigned int>::max()) {
218 start_route = id_to_graph_map_.at(rerouting_info.rerouting_start_id);
219 goal_intent_extractor_->overrideStart(rerouting_info.rerouting_start_pose);
223 if (start_route == end_route) {
225 route.route_cost = 0.0;
226 route.start_node = &graph_.at(start_route);
230 route_request.start_nodeid = start_route;
231 route_request.goal_nodeid = end_route;
232 route_request.start_pose = goal_intent_extractor_->getStart();
233 route_request.goal_pose = goal->goal;
234 route_request.use_poses = goal->use_poses;
237 route = route_planner_->findRoute(
238 graph_, start_route, end_route, rerouting_info.blocked_ids, route_request);
241 return goal_intent_extractor_->pruneStartandGoal(route, goal, rerouting_info);
244 template<
typename ActionT>
247 typename nav2::SimpleActionServer<ActionT>::SharedPtr & action_server)
250 auto result = std::make_shared<typename ActionT::Result>();
252 auto start_time = this->now();
255 while (rclcpp::ok()) {
256 if (!isRequestValid<ActionT>(action_server)) {
261 RCLCPP_INFO(get_logger(),
"Computing new preempted route to goal.");
263 rerouting_info.reset();
269 get_logger(),
"Route found with %zu nodes and %zu edges",
270 route.edges.size() + 1u, route.edges.size());
272 auto path = path_converter_->densify(route, rerouting_info, route_frame_, this->now());
274 if (std::is_same<ActionT, ComputeAndTrackRoute>::value) {
276 switch (route_tracker_->trackRoute(route, path, rerouting_info)) {
277 case TrackerResult::COMPLETED:
281 case TrackerResult::INTERRUPTED:
284 case TrackerResult::EXITED:
297 result->error_code = ActionT::Result::NO_VALID_ROUTE;
298 result->error_msg = ex.what();
302 result->error_code = ActionT::Result::TIMEOUT;
303 result->error_msg = ex.what();
307 result->error_code = ActionT::Result::TF_ERROR;
308 result->error_msg = ex.what();
312 result->error_code = ActionT::Result::NO_VALID_GRAPH;
313 result->error_msg = ex.what();
317 result->error_code = ActionT::Result::INDETERMINANT_NODES_ON_GRAPH;
318 result->error_msg = ex.what();
322 result->error_code = ActionT::Result::INVALID_EDGE_SCORER_USE;
323 result->error_msg = ex.what();
329 result->error_code = ComputeAndTrackRoute::Result::OPERATION_FAILED;
330 result->error_msg = ex.what();
334 result->error_code = ActionT::Result::UNKNOWN;
335 result->error_msg = ex.what();
337 }
catch (std::exception & ex) {
339 result->error_code = ActionT::Result::UNKNOWN;
340 result->error_msg = ex.what();
348 RCLCPP_INFO(get_logger(),
"Computing route to goal.");
349 processRouteRequest<ComputeRoute>(compute_route_server_);
353 RouteServer::computeAndTrackRoute()
355 RCLCPP_INFO(get_logger(),
"Computing and tracking route to goal.");
356 processRouteRequest<ComputeAndTrackRoute>(compute_and_track_route_server_);
360 const std::shared_ptr<rmw_request_id_t>,
361 const std::shared_ptr<nav2_msgs::srv::SetRouteGraph::Request> request,
362 std::shared_ptr<nav2_msgs::srv::SetRouteGraph::Response> response)
364 RCLCPP_INFO(get_logger(),
"Setting new route graph: %s.", request->graph_filepath.c_str());
366 id_to_graph_map_.clear();
368 if (graph_loader_->loadGraphFromFile(graph_, id_to_graph_map_, request->graph_filepath)) {
369 goal_intent_extractor_->setGraph(graph_, &id_to_graph_map_);
370 graph_vis_publisher_->publish(utils::toMsg(graph_, route_frame_, this->now()));
371 response->success =
true;
374 }
catch (std::exception & ex) {
379 "Failed to set new route graph: %s!", request->graph_filepath.c_str());
380 response->success =
false;
386 if (route_publisher_->is_activated() && route_publisher_->get_subscription_count() > 0) {
387 auto msg = std::make_unique<nav2_msgs::msg::Route>(
388 utils::toMsg(route, route_frame_, this->now()));
389 route_publisher_->publish(std::move(msg));
393 template<
typename GoalT>
395 const std::shared_ptr<const GoalT> goal,
396 const std::exception & ex)
400 "Route server failed on request: Start: [(%0.2f, %0.2f) / %i] Goal: [(%0.2f, %0.2f) / %i]:"
401 " \"%s\"", goal->start.pose.position.x, goal->start.pose.position.y, goal->start_id,
402 goal->goal.pose.position.x, goal->goal.pose.position.y, goal->goal_id, ex.what());
407 #include "rclcpp_components/register_node_macro.hpp"
void destroyBond()
Destroy bond connection to lifecycle manager.
nav2::LifecycleNode::SharedPtr shared_from_this()
Get a shared pointer of this.
ParameterT declare_or_get_parameter(const std::string ¶meter_name, const ParameterDescriptor ¶meter_descriptor=ParameterDescriptor())
Declares or gets a parameter with specified type (not value). If the parameter is already declared,...
void createBond()
Create bond connection to lifecycle manager.
void terminate_current(typename std::shared_ptr< typename ActionT::Result > result=std::make_shared< typename ActionT::Result >())
Terminate the active action.
const std::shared_ptr< const typename ActionT::Goal > get_current_goal() const
Get the current goal object.
bool is_cancel_requested() const
Whether or not a cancel command has come in.
void terminate_all(typename std::shared_ptr< typename ActionT::Result > result=std::make_shared< typename ActionT::Result >())
Terminate all pending and active actions.
bool is_preempt_requested() const
Whether the action server has been asked to be preempted with a new goal.
void succeeded_current(typename std::shared_ptr< typename ActionT::Result > result=std::make_shared< typename ActionT::Result >())
Return success of the active action.
bool is_server_active()
Whether the action server is active or not.
const std::shared_ptr< const typename ActionT::Goal > accept_pending_goal()
Accept pending goals.
A QoS profile for latched, reliable topics with a history of 1 messages.
An action server implements a Navigation Route-Graph planner to compliment free-space planning in the...
void computeRoute()
Main route action server callbacks for computing and tracking a route.
void setRouteGraph(const std::shared_ptr< rmw_request_id_t >, const std::shared_ptr< nav2_msgs::srv::SetRouteGraph::Request > request, std::shared_ptr< nav2_msgs::srv::SetRouteGraph::Response > response)
The service callback to set a new route graph.
rclcpp::Duration findPlanningDuration(const rclcpp::Time &start_time)
Find the planning duration of the request and log warnings.
void publishRoute(const Route &route)
Publish the route msg.
Route findRoute(const std::shared_ptr< const GoalT > goal, ReroutingState &rerouting_info)
Compute a route to the goal, incorporating rerouting information.
nav2::CallbackReturn on_configure(const rclcpp_lifecycle::State &state) override
Configure member variables and initializes planner.
nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
Activate member variables.
bool isRequestValid(typename nav2::SimpleActionServer< ActionT >::SharedPtr &action_server)
Find the routing request is valid (action server OK and not cancelled)
RouteServer(const rclcpp::NodeOptions &options=rclcpp::NodeOptions())
A constructor for nav2_route::RouteServer.
void exceptionWarning(const std::shared_ptr< const GoalT > goal, const std::exception &ex)
Log exception warnings, templated by action message type.
nav2::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &state) override
Reset member variables.
nav2::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &state) override
Deactivate member variables.
nav2::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &state) override
Called when in shutdown state.
void populateActionResult(std::shared_ptr< ComputeRoute::Result > result, const Route &route, const nav_msgs::msg::Path &path, const rclcpp::Duration &planning_duration)
Populate result for compute route action.
void processRouteRequest(typename nav2::SimpleActionServer< ActionT >::SharedPtr &action_server)
Main processing called by both action server callbacks to centralize the great deal of shared code be...
State shared to objects to communicate important rerouting data to avoid rerouting over blocked edges...
An object to store salient features of the route request including its start and goal node ids,...
An ordered set of nodes and edges corresponding to the planned route.