27 #include "lifecycle_msgs/msg/state.hpp"
28 #include "nav2_util/costmap.hpp"
29 #include "nav2_ros_common/node_utils.hpp"
30 #include "nav2_util/geometry_utils.hpp"
31 #include "nav2_costmap_2d/cost_values.hpp"
33 #include "nav2_planner/planner_server.hpp"
35 using namespace std::chrono_literals;
36 using rcl_interfaces::msg::ParameterType;
37 using std::placeholders::_1;
39 namespace nav2_planner
42 PlannerServer::PlannerServer(
const rclcpp::NodeOptions & options)
43 : nav2::LifecycleNode(
"planner_server",
"", options),
44 gp_loader_(
"nav2_core",
"nav2_core::GlobalPlanner"),
45 default_ids_{
"GridBased"},
46 default_types_{
"nav2_navfn_planner::NavfnPlanner"},
47 costmap_update_timeout_(1s),
50 RCLCPP_INFO(get_logger(),
"Creating");
53 declare_parameter(
"planner_plugins", default_ids_);
54 declare_parameter(
"expected_planner_frequency", 1.0);
55 declare_parameter(
"costmap_update_timeout", 1.0);
57 get_parameter(
"planner_plugins", planner_ids_);
58 if (planner_ids_ == default_ids_) {
59 for (
size_t i = 0; i < default_ids_.size(); ++i) {
60 declare_parameter(default_ids_[i] +
".plugin", default_types_[i]);
65 costmap_ros_ = std::make_shared<nav2_costmap_2d::Costmap2DROS>(
66 "global_costmap", std::string{get_namespace()},
67 get_parameter(
"use_sim_time").as_bool(), options);
77 costmap_thread_.reset();
83 RCLCPP_INFO(get_logger(),
"Configuring");
85 costmap_ros_->configure();
86 costmap_ = costmap_ros_->getCostmap();
88 if (!costmap_ros_->getUseRadius()) {
90 std::make_unique<nav2_costmap_2d::FootprintCollisionChecker<nav2_costmap_2d::Costmap2D *>>(
95 costmap_thread_ = std::make_unique<nav2::NodeThread>(costmap_ros_);
98 get_logger(),
"Costmap size: %d,%d",
101 tf_ = costmap_ros_->getTfBuffer();
103 planner_types_.resize(planner_ids_.size());
107 for (
size_t i = 0; i != planner_ids_.size(); i++) {
109 planner_types_[i] = nav2::get_plugin_type_param(
110 node, planner_ids_[i]);
111 nav2_core::GlobalPlanner::Ptr planner =
112 gp_loader_.createUniqueInstance(planner_types_[i]);
114 get_logger(),
"Created global planner plugin %s of type %s",
115 planner_ids_[i].c_str(), planner_types_[i].c_str());
116 planner->configure(node, planner_ids_[i], tf_, costmap_ros_);
117 planners_.insert({planner_ids_[i], planner});
118 }
catch (
const std::exception & ex) {
120 get_logger(),
"Failed to create global planner. Exception: %s",
123 return nav2::CallbackReturn::FAILURE;
127 for (
size_t i = 0; i != planner_ids_.size(); i++) {
128 planner_ids_concat_ += planner_ids_[i] + std::string(
" ");
133 "Planner Server has %s planners available.", planner_ids_concat_.c_str());
135 double expected_planner_frequency;
136 get_parameter(
"expected_planner_frequency", expected_planner_frequency);
137 if (expected_planner_frequency > 0) {
138 max_planner_duration_ = 1 / expected_planner_frequency;
142 "The expected planner frequency parameter is %.4f Hz. The value should to be greater"
143 " than 0.0 to turn on duration overrun warning messages", expected_planner_frequency);
144 max_planner_duration_ = 0.0;
148 plan_publisher_ = create_publisher<nav_msgs::msg::Path>(
"plan");
150 double costmap_update_timeout_dbl;
151 get_parameter(
"costmap_update_timeout", costmap_update_timeout_dbl);
152 costmap_update_timeout_ = rclcpp::Duration::from_seconds(costmap_update_timeout_dbl);
155 action_server_pose_ = create_action_server<ActionToPose>(
156 "compute_path_to_pose",
159 std::chrono::milliseconds(500),
162 action_server_poses_ = create_action_server<ActionThroughPoses>(
163 "compute_path_through_poses",
166 std::chrono::milliseconds(500),
169 return nav2::CallbackReturn::SUCCESS;
175 RCLCPP_INFO(get_logger(),
"Activating");
177 plan_publisher_->on_activate();
178 action_server_pose_->activate();
179 action_server_poses_->activate();
180 const auto costmap_ros_state = costmap_ros_->activate();
181 if (costmap_ros_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) {
182 return nav2::CallbackReturn::FAILURE;
185 PlannerMap::iterator it;
186 for (it = planners_.begin(); it != planners_.end(); ++it) {
187 it->second->activate();
190 is_path_valid_service_ = create_service<nav2_msgs::srv::IsPathValid>(
193 std::placeholders::_3));
196 dyn_params_handler_ = add_on_set_parameters_callback(
202 return nav2::CallbackReturn::SUCCESS;
208 RCLCPP_INFO(get_logger(),
"Deactivating");
210 action_server_pose_->deactivate();
211 action_server_poses_->deactivate();
212 plan_publisher_->on_deactivate();
221 costmap_ros_->deactivate();
223 PlannerMap::iterator it;
224 for (it = planners_.begin(); it != planners_.end(); ++it) {
225 it->second->deactivate();
228 dyn_params_handler_.reset();
233 return nav2::CallbackReturn::SUCCESS;
239 RCLCPP_INFO(get_logger(),
"Cleaning up");
241 is_path_valid_service_.reset();
242 action_server_pose_.reset();
243 action_server_poses_.reset();
244 plan_publisher_.reset();
247 costmap_ros_->cleanup();
249 PlannerMap::iterator it;
250 for (it = planners_.begin(); it != planners_.end(); ++it) {
251 it->second->cleanup();
255 costmap_thread_.reset();
257 return nav2::CallbackReturn::SUCCESS;
263 RCLCPP_INFO(get_logger(),
"Shutting down");
264 return nav2::CallbackReturn::SUCCESS;
269 typename nav2::SimpleActionServer<T>::SharedPtr & action_server)
272 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
283 auto waiting_start = now();
284 while (!costmap_ros_->isCurrent()) {
285 if (now() - waiting_start > costmap_update_timeout_) {
294 typename nav2::SimpleActionServer<T>::SharedPtr & action_server)
297 RCLCPP_INFO(get_logger(),
"Goal was canceled. Canceling planning action.");
307 typename nav2::SimpleActionServer<T>::SharedPtr & action_server,
308 typename std::shared_ptr<const typename T::Goal> goal)
317 typename std::shared_ptr<const typename T::Goal> goal,
318 geometry_msgs::msg::PoseStamped & start)
320 if (goal->use_start) {
322 }
else if (!costmap_ros_->getRobotPose(start)) {
330 geometry_msgs::msg::PoseStamped & curr_start,
331 geometry_msgs::msg::PoseStamped & curr_goal)
333 if (!costmap_ros_->transformPoseToGlobalFrame(curr_start, curr_start) ||
334 !costmap_ros_->transformPoseToGlobalFrame(curr_goal, curr_goal))
344 const geometry_msgs::msg::PoseStamped & goal,
345 const nav_msgs::msg::Path & path,
346 const std::string & planner_id)
348 if (path.poses.empty()) {
350 get_logger(),
"Planning algorithm %s failed to generate a valid"
351 " path to (%.2f, %.2f)", planner_id.c_str(),
352 goal.pose.position.x, goal.pose.position.y);
358 "Found valid path of size %zu to (%.2f, %.2f)",
359 path.poses.size(), goal.pose.position.x,
360 goal.pose.position.y);
367 std::lock_guard<std::mutex> lock(dynamic_params_lock_);
369 auto start_time = this->now();
372 auto goal = action_server_poses_->get_current_goal();
373 auto result = std::make_shared<ActionThroughPoses::Result>();
374 nav_msgs::msg::Path concat_path;
375 RCLCPP_INFO(get_logger(),
"Computing path through poses to goal.");
377 geometry_msgs::msg::PoseStamped curr_start, curr_goal;
380 if (isServerInactive<ActionThroughPoses>(action_server_poses_) ||
381 isCancelRequested<ActionThroughPoses>(action_server_poses_))
388 getPreemptedGoalIfRequested<ActionThroughPoses>(action_server_poses_, goal);
390 if (goal->goals.goals.empty()) {
395 geometry_msgs::msg::PoseStamped start;
396 if (!getStartPose<ActionThroughPoses>(goal, start)) {
400 auto cancel_checker = [
this]() {
401 return action_server_poses_->is_cancel_requested();
405 for (
unsigned int i = 0; i != goal->goals.goals.size(); i++) {
412 curr_start = concat_path.poses.back();
413 curr_start.header = concat_path.header;
415 curr_goal = goal->goals.goals[i];
423 nav_msgs::msg::Path curr_path =
getPlan(
424 curr_start, curr_goal, goal->planner_id,
427 if (!validatePath<ActionThroughPoses>(curr_goal, curr_path, goal->planner_id)) {
435 concat_path.poses.insert(
436 concat_path.poses.end(), curr_path.poses.begin(), curr_path.poses.end());
437 }
else if (curr_path.poses.size() > 1) {
439 concat_path.poses.insert(
440 concat_path.poses.end(), curr_path.poses.begin() + 1, curr_path.poses.end());
442 concat_path.header = curr_path.header;
446 result->path = concat_path;
449 auto cycle_duration = this->now() - start_time;
450 result->planning_time = cycle_duration;
452 if (max_planner_duration_ && cycle_duration.seconds() > max_planner_duration_) {
455 "Planner loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz",
456 1 / max_planner_duration_, 1 / cycle_duration.seconds());
459 action_server_poses_->succeeded_current(result);
461 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
462 result->error_code = ActionThroughPosesResult::INVALID_PLANNER;
463 action_server_poses_->terminate_current(result);
465 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
466 result->error_code = ActionThroughPosesResult::START_OCCUPIED;
467 action_server_poses_->terminate_current(result);
469 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
470 result->error_code = ActionThroughPosesResult::GOAL_OCCUPIED;
471 action_server_poses_->terminate_current(result);
473 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
474 result->error_code = ActionThroughPosesResult::NO_VALID_PATH;
475 action_server_poses_->terminate_current(result);
477 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
478 result->error_code = ActionThroughPosesResult::TIMEOUT;
479 action_server_poses_->terminate_current(result);
481 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
482 result->error_code = ActionThroughPosesResult::START_OUTSIDE_MAP;
483 action_server_poses_->terminate_current(result);
485 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
486 result->error_code = ActionThroughPosesResult::GOAL_OUTSIDE_MAP;
487 action_server_poses_->terminate_current(result);
489 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
490 result->error_code = ActionThroughPosesResult::TF_ERROR;
491 action_server_poses_->terminate_current(result);
493 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
494 result->error_code = ActionThroughPosesResult::NO_VIAPOINTS_GIVEN;
495 action_server_poses_->terminate_current(result);
497 result->error_msg =
"Goal was canceled. Canceling planning action.";
498 RCLCPP_INFO(get_logger(), result->error_msg.c_str());
499 action_server_poses_->terminate_all();
500 }
catch (std::exception & ex) {
501 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
502 result->error_code = ActionThroughPosesResult::UNKNOWN;
503 action_server_poses_->terminate_current(result);
510 std::lock_guard<std::mutex> lock(dynamic_params_lock_);
512 auto start_time = this->now();
515 auto goal = action_server_pose_->get_current_goal();
516 auto result = std::make_shared<ActionToPose::Result>();
517 RCLCPP_INFO(get_logger(),
"Computing path to goal.");
519 geometry_msgs::msg::PoseStamped start;
522 if (isServerInactive<ActionToPose>(action_server_pose_) ||
523 isCancelRequested<ActionToPose>(action_server_pose_))
530 getPreemptedGoalIfRequested<ActionToPose>(action_server_pose_, goal);
533 if (!getStartPose<ActionToPose>(goal, start)) {
538 geometry_msgs::msg::PoseStamped goal_pose = goal->goal;
543 auto cancel_checker = [
this]() {
544 return action_server_pose_->is_cancel_requested();
547 result->path =
getPlan(start, goal_pose, goal->planner_id, cancel_checker);
549 if (!validatePath<ActionThroughPoses>(goal_pose, result->path, goal->planner_id)) {
556 auto cycle_duration = this->now() - start_time;
557 result->planning_time = cycle_duration;
559 if (max_planner_duration_ && cycle_duration.seconds() > max_planner_duration_) {
562 "Planner loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz",
563 1 / max_planner_duration_, 1 / cycle_duration.seconds());
565 action_server_pose_->succeeded_current(result);
567 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
568 result->error_code = ActionToPoseResult::INVALID_PLANNER;
569 action_server_pose_->terminate_current(result);
571 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
572 result->error_code = ActionToPoseResult::START_OCCUPIED;
573 action_server_pose_->terminate_current(result);
575 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
576 result->error_code = ActionToPoseResult::GOAL_OCCUPIED;
577 action_server_pose_->terminate_current(result);
579 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
580 result->error_code = ActionToPoseResult::NO_VALID_PATH;
581 action_server_pose_->terminate_current(result);
583 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
584 result->error_code = ActionToPoseResult::TIMEOUT;
585 action_server_pose_->terminate_current(result);
587 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
588 result->error_code = ActionToPoseResult::START_OUTSIDE_MAP;
589 action_server_pose_->terminate_current(result);
591 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
592 result->error_code = ActionToPoseResult::GOAL_OUTSIDE_MAP;
593 action_server_pose_->terminate_current(result);
595 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
596 result->error_code = ActionToPoseResult::TF_ERROR;
597 action_server_pose_->terminate_current(result);
599 result->error_msg =
"Goal was canceled. Canceling planning action.";
600 RCLCPP_INFO(get_logger(), result->error_msg.c_str());
601 action_server_pose_->terminate_all();
602 }
catch (std::exception & ex) {
603 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
604 result->error_code = ActionToPoseResult::UNKNOWN;
605 action_server_pose_->terminate_current(result);
611 const geometry_msgs::msg::PoseStamped & start,
612 const geometry_msgs::msg::PoseStamped & goal,
613 const std::string & planner_id,
614 std::function<
bool()> cancel_checker)
617 get_logger(),
"Attempting to a find path from (%.2f, %.2f) to "
618 "(%.2f, %.2f).", start.pose.position.x, start.pose.position.y,
619 goal.pose.position.x, goal.pose.position.y);
621 if (planners_.find(planner_id) != planners_.end()) {
622 return planners_[planner_id]->createPlan(start, goal, cancel_checker);
624 if (planners_.size() == 1 && planner_id.empty()) {
626 get_logger(),
"No planners specified in action call. "
627 "Server will use only plugin %s in server."
628 " This warning will appear once.", planner_ids_concat_.c_str());
629 return planners_[planners_.begin()->first]->createPlan(start, goal, cancel_checker);
632 get_logger(),
"planner %s is not a valid planner. "
633 "Planner names are: %s", planner_id.c_str(),
634 planner_ids_concat_.c_str());
639 return nav_msgs::msg::Path();
645 auto msg = std::make_unique<nav_msgs::msg::Path>(path);
646 if (plan_publisher_->is_activated() && plan_publisher_->get_subscription_count() > 0) {
647 plan_publisher_->publish(std::move(msg));
652 const std::shared_ptr<rmw_request_id_t>,
653 const std::shared_ptr<nav2_msgs::srv::IsPathValid::Request> request,
654 std::shared_ptr<nav2_msgs::srv::IsPathValid::Response> response)
656 response->is_valid =
true;
658 if (request->path.poses.empty()) {
659 response->is_valid =
false;
663 geometry_msgs::msg::PoseStamped current_pose;
664 unsigned int closest_point_index = 0;
665 if (costmap_ros_->getRobotPose(current_pose)) {
666 float current_distance = std::numeric_limits<float>::max();
667 float closest_distance = current_distance;
668 geometry_msgs::msg::Point current_point = current_pose.pose.position;
669 for (
unsigned int i = 0; i < request->path.poses.size(); ++i) {
670 geometry_msgs::msg::Point path_point = request->path.poses[i].pose.position;
672 current_distance = nav2_util::geometry_utils::euclidean_distance(
676 if (current_distance < closest_distance) {
677 closest_point_index = i;
678 closest_distance = current_distance;
687 std::unique_lock<nav2_costmap_2d::Costmap2D::mutex_t> lock(*(costmap_->getMutex()));
691 bool use_radius = costmap_ros_->getUseRadius();
693 unsigned int cost = nav2_costmap_2d::FREE_SPACE;
694 for (
unsigned int i = closest_point_index; i < request->path.poses.size(); ++i) {
695 auto & position = request->path.poses[i].pose.position;
697 if (costmap_->
worldToMap(position.x, position.y, mx, my)) {
698 cost = costmap_->
getCost(mx, my);
700 cost = nav2_costmap_2d::LETHAL_OBSTACLE;
703 nav2_costmap_2d::Footprint footprint = costmap_ros_->getRobotFootprint();
704 auto theta = tf2::getYaw(request->path.poses[i].pose.orientation);
705 cost =
static_cast<unsigned int>(collision_checker_->footprintCostAtPose(
706 position.x, position.y, theta, footprint));
709 if (cost == nav2_costmap_2d::NO_INFORMATION && request->consider_unknown_as_obstacle) {
710 cost = nav2_costmap_2d::LETHAL_OBSTACLE;
711 }
else if (cost == nav2_costmap_2d::NO_INFORMATION) {
712 cost = nav2_costmap_2d::FREE_SPACE;
716 (cost >= request->max_cost || cost == nav2_costmap_2d::LETHAL_OBSTACLE ||
717 cost == nav2_costmap_2d::INSCRIBED_INFLATED_OBSTACLE))
719 response->is_valid =
false;
721 }
else if (cost == nav2_costmap_2d::LETHAL_OBSTACLE || cost >= request->max_cost) {
722 response->is_valid =
false;
729 rcl_interfaces::msg::SetParametersResult
732 std::lock_guard<std::mutex> lock(dynamic_params_lock_);
733 rcl_interfaces::msg::SetParametersResult result;
734 for (
auto parameter : parameters) {
735 const auto & param_type = parameter.get_type();
736 const auto & param_name = parameter.get_name();
737 if (param_name.find(
'.') != std::string::npos) {
741 if (param_type == ParameterType::PARAMETER_DOUBLE) {
742 if (param_name ==
"expected_planner_frequency") {
743 if (parameter.as_double() > 0) {
744 max_planner_duration_ = 1 / parameter.as_double();
748 "The expected planner frequency parameter is %.4f Hz. The value should to be greater"
749 " than 0.0 to turn on duration overrun warning messages", parameter.as_double());
750 max_planner_duration_ = 0.0;
756 result.successful =
true;
760 void PlannerServer::exceptionWarning(
761 const geometry_msgs::msg::PoseStamped & start,
762 const geometry_msgs::msg::PoseStamped & goal,
763 const std::string & planner_id,
764 const std::exception & ex,
765 std::string & error_msg)
767 std::stringstream ss;
768 ss << std::fixed << std::setprecision(2)
769 << planner_id <<
"plugin failed to plan from ("
770 << start.pose.position.x <<
", " << start.pose.position.y
772 << goal.pose.position.x <<
", " << goal.pose.position.y <<
")"
773 <<
": \"" << ex.what() <<
"\"";
775 error_msg = ss.str();
776 RCLCPP_WARN(get_logger(), error_msg.c_str());
781 #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.
void createBond()
Create bond connection to lifecycle manager.
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.
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.
unsigned char getCost(unsigned int mx, unsigned int my) const
Get the cost of a cell in the costmap.
bool worldToMap(double wx, double wy, unsigned int &mx, unsigned int &my) const
Convert from world coordinates to map coordinates.
unsigned int getSizeInCellsX() const
Accessor for the x size of the costmap in cells.
unsigned int getSizeInCellsY() const
Accessor for the y size of the costmap in cells.
An action server implements the behavior tree's ComputePathToPose interface and hosts various plugins...
nav2::CallbackReturn on_configure(const rclcpp_lifecycle::State &state) override
Configure member variables and initializes planner.
void publishPlan(const nav_msgs::msg::Path &path)
Publish a path for visualization purposes.
void computePlan()
The action server callback which calls planner to get the path ComputePathToPose.
nav2::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &state) override
Deactivate member variables.
bool isServerInactive(typename nav2::SimpleActionServer< T >::SharedPtr &action_server)
Check if an action server is valid / active.
void waitForCostmap()
Wait for costmap to be valid with updated sensor data or repopulate after a clearing recovery....
bool getStartPose(typename std::shared_ptr< const typename T::Goal > goal, geometry_msgs::msg::PoseStamped &start)
Get the starting pose from costmap or message, if valid.
~PlannerServer()
A destructor for nav2_planner::PlannerServer.
void isPathValid(const std::shared_ptr< rmw_request_id_t > request_header, const std::shared_ptr< nav2_msgs::srv::IsPathValid::Request > request, std::shared_ptr< nav2_msgs::srv::IsPathValid::Response > response)
The service callback to determine if the path is still valid.
nav_msgs::msg::Path getPlan(const geometry_msgs::msg::PoseStamped &start, const geometry_msgs::msg::PoseStamped &goal, const std::string &planner_id, std::function< bool()> cancel_checker)
Method to get plan from the desired plugin.
nav2::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &state) override
Called when in shutdown state.
void computePlanThroughPoses()
The action server callback which calls planner to get the path ComputePathThroughPoses.
bool isCancelRequested(typename nav2::SimpleActionServer< T >::SharedPtr &action_server)
Check if an action server has a cancellation request pending.
rcl_interfaces::msg::SetParametersResult dynamicParametersCallback(std::vector< rclcpp::Parameter > parameters)
Callback executed when a parameter change is detected.
nav2::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &state) override
Reset member variables.
void getPreemptedGoalIfRequested(typename nav2::SimpleActionServer< T >::SharedPtr &action_server, typename std::shared_ptr< const typename T::Goal > goal)
Check if an action server has a preemption request and replaces the goal with the new preemption goal...
bool validatePath(const geometry_msgs::msg::PoseStamped &curr_goal, const nav_msgs::msg::Path &path, const std::string &planner_id)
Validate that the path contains a meaningful path.
nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
Activate member variables.
bool transformPosesToGlobalFrame(geometry_msgs::msg::PoseStamped &curr_start, geometry_msgs::msg::PoseStamped &curr_goal)
Transform start and goal poses into the costmap global frame for path planning plugins to utilize.