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)) {
432 concat_path.poses.insert(
433 concat_path.poses.end(), curr_path.poses.begin(), curr_path.poses.end());
434 concat_path.header = curr_path.header;
438 result->path = concat_path;
441 auto cycle_duration = this->now() - start_time;
442 result->planning_time = cycle_duration;
444 if (max_planner_duration_ && cycle_duration.seconds() > max_planner_duration_) {
447 "Planner loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz",
448 1 / max_planner_duration_, 1 / cycle_duration.seconds());
451 action_server_poses_->succeeded_current(result);
453 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
454 result->error_code = ActionThroughPosesResult::INVALID_PLANNER;
455 action_server_poses_->terminate_current(result);
457 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
458 result->error_code = ActionThroughPosesResult::START_OCCUPIED;
459 action_server_poses_->terminate_current(result);
461 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
462 result->error_code = ActionThroughPosesResult::GOAL_OCCUPIED;
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::NO_VALID_PATH;
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::TIMEOUT;
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::START_OUTSIDE_MAP;
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::GOAL_OUTSIDE_MAP;
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::TF_ERROR;
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::NO_VIAPOINTS_GIVEN;
487 action_server_poses_->terminate_current(result);
489 result->error_msg =
"Goal was canceled. Canceling planning action.";
490 RCLCPP_INFO(get_logger(), result->error_msg.c_str());
491 action_server_poses_->terminate_all();
492 }
catch (std::exception & ex) {
493 exceptionWarning(curr_start, curr_goal, goal->planner_id, ex, result->error_msg);
494 result->error_code = ActionThroughPosesResult::UNKNOWN;
495 action_server_poses_->terminate_current(result);
502 std::lock_guard<std::mutex> lock(dynamic_params_lock_);
504 auto start_time = this->now();
507 auto goal = action_server_pose_->get_current_goal();
508 auto result = std::make_shared<ActionToPose::Result>();
509 RCLCPP_INFO(get_logger(),
"Computing path to goal.");
511 geometry_msgs::msg::PoseStamped start;
514 if (isServerInactive<ActionToPose>(action_server_pose_) ||
515 isCancelRequested<ActionToPose>(action_server_pose_))
522 getPreemptedGoalIfRequested<ActionToPose>(action_server_pose_, goal);
525 if (!getStartPose<ActionToPose>(goal, start)) {
530 geometry_msgs::msg::PoseStamped goal_pose = goal->goal;
535 auto cancel_checker = [
this]() {
536 return action_server_pose_->is_cancel_requested();
539 result->path =
getPlan(start, goal_pose, goal->planner_id, cancel_checker);
541 if (!validatePath<ActionThroughPoses>(goal_pose, result->path, goal->planner_id)) {
548 auto cycle_duration = this->now() - start_time;
549 result->planning_time = cycle_duration;
551 if (max_planner_duration_ && cycle_duration.seconds() > max_planner_duration_) {
554 "Planner loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz",
555 1 / max_planner_duration_, 1 / cycle_duration.seconds());
557 action_server_pose_->succeeded_current(result);
559 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
560 result->error_code = ActionToPoseResult::INVALID_PLANNER;
561 action_server_pose_->terminate_current(result);
563 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
564 result->error_code = ActionToPoseResult::START_OCCUPIED;
565 action_server_pose_->terminate_current(result);
567 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
568 result->error_code = ActionToPoseResult::GOAL_OCCUPIED;
569 action_server_pose_->terminate_current(result);
571 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
572 result->error_code = ActionToPoseResult::NO_VALID_PATH;
573 action_server_pose_->terminate_current(result);
575 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
576 result->error_code = ActionToPoseResult::TIMEOUT;
577 action_server_pose_->terminate_current(result);
579 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
580 result->error_code = ActionToPoseResult::START_OUTSIDE_MAP;
581 action_server_pose_->terminate_current(result);
583 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
584 result->error_code = ActionToPoseResult::GOAL_OUTSIDE_MAP;
585 action_server_pose_->terminate_current(result);
587 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
588 result->error_code = ActionToPoseResult::TF_ERROR;
589 action_server_pose_->terminate_current(result);
591 result->error_msg =
"Goal was canceled. Canceling planning action.";
592 RCLCPP_INFO(get_logger(), result->error_msg.c_str());
593 action_server_pose_->terminate_all();
594 }
catch (std::exception & ex) {
595 exceptionWarning(start, goal->goal, goal->planner_id, ex, result->error_msg);
596 result->error_code = ActionToPoseResult::UNKNOWN;
597 action_server_pose_->terminate_current(result);
603 const geometry_msgs::msg::PoseStamped & start,
604 const geometry_msgs::msg::PoseStamped & goal,
605 const std::string & planner_id,
606 std::function<
bool()> cancel_checker)
609 get_logger(),
"Attempting to a find path from (%.2f, %.2f) to "
610 "(%.2f, %.2f).", start.pose.position.x, start.pose.position.y,
611 goal.pose.position.x, goal.pose.position.y);
613 if (planners_.find(planner_id) != planners_.end()) {
614 return planners_[planner_id]->createPlan(start, goal, cancel_checker);
616 if (planners_.size() == 1 && planner_id.empty()) {
618 get_logger(),
"No planners specified in action call. "
619 "Server will use only plugin %s in server."
620 " This warning will appear once.", planner_ids_concat_.c_str());
621 return planners_[planners_.begin()->first]->createPlan(start, goal, cancel_checker);
624 get_logger(),
"planner %s is not a valid planner. "
625 "Planner names are: %s", planner_id.c_str(),
626 planner_ids_concat_.c_str());
631 return nav_msgs::msg::Path();
637 auto msg = std::make_unique<nav_msgs::msg::Path>(path);
638 if (plan_publisher_->is_activated() && plan_publisher_->get_subscription_count() > 0) {
639 plan_publisher_->publish(std::move(msg));
644 const std::shared_ptr<rmw_request_id_t>,
645 const std::shared_ptr<nav2_msgs::srv::IsPathValid::Request> request,
646 std::shared_ptr<nav2_msgs::srv::IsPathValid::Response> response)
648 response->is_valid =
true;
650 if (request->path.poses.empty()) {
651 response->is_valid =
false;
655 geometry_msgs::msg::PoseStamped current_pose;
656 unsigned int closest_point_index = 0;
657 if (costmap_ros_->getRobotPose(current_pose)) {
658 float current_distance = std::numeric_limits<float>::max();
659 float closest_distance = current_distance;
660 geometry_msgs::msg::Point current_point = current_pose.pose.position;
661 for (
unsigned int i = 0; i < request->path.poses.size(); ++i) {
662 geometry_msgs::msg::Point path_point = request->path.poses[i].pose.position;
664 current_distance = nav2_util::geometry_utils::euclidean_distance(
668 if (current_distance < closest_distance) {
669 closest_point_index = i;
670 closest_distance = current_distance;
679 std::unique_lock<nav2_costmap_2d::Costmap2D::mutex_t> lock(*(costmap_->getMutex()));
683 bool use_radius = costmap_ros_->getUseRadius();
685 unsigned int cost = nav2_costmap_2d::FREE_SPACE;
686 for (
unsigned int i = closest_point_index; i < request->path.poses.size(); ++i) {
687 auto & position = request->path.poses[i].pose.position;
689 if (costmap_->
worldToMap(position.x, position.y, mx, my)) {
690 cost = costmap_->
getCost(mx, my);
692 cost = nav2_costmap_2d::LETHAL_OBSTACLE;
695 nav2_costmap_2d::Footprint footprint = costmap_ros_->getRobotFootprint();
696 auto theta = tf2::getYaw(request->path.poses[i].pose.orientation);
697 cost =
static_cast<unsigned int>(collision_checker_->footprintCostAtPose(
698 position.x, position.y, theta, footprint));
701 if (cost == nav2_costmap_2d::NO_INFORMATION && request->consider_unknown_as_obstacle) {
702 cost = nav2_costmap_2d::LETHAL_OBSTACLE;
703 }
else if (cost == nav2_costmap_2d::NO_INFORMATION) {
704 cost = nav2_costmap_2d::FREE_SPACE;
708 (cost >= request->max_cost || cost == nav2_costmap_2d::LETHAL_OBSTACLE ||
709 cost == nav2_costmap_2d::INSCRIBED_INFLATED_OBSTACLE))
711 response->is_valid =
false;
713 }
else if (cost == nav2_costmap_2d::LETHAL_OBSTACLE || cost >= request->max_cost) {
714 response->is_valid =
false;
721 rcl_interfaces::msg::SetParametersResult
724 std::lock_guard<std::mutex> lock(dynamic_params_lock_);
725 rcl_interfaces::msg::SetParametersResult result;
726 for (
auto parameter : parameters) {
727 const auto & param_type = parameter.get_type();
728 const auto & param_name = parameter.get_name();
729 if (param_name.find(
'.') != std::string::npos) {
733 if (param_type == ParameterType::PARAMETER_DOUBLE) {
734 if (param_name ==
"expected_planner_frequency") {
735 if (parameter.as_double() > 0) {
736 max_planner_duration_ = 1 / parameter.as_double();
740 "The expected planner frequency parameter is %.4f Hz. The value should to be greater"
741 " than 0.0 to turn on duration overrun warning messages", parameter.as_double());
742 max_planner_duration_ = 0.0;
748 result.successful =
true;
752 void PlannerServer::exceptionWarning(
753 const geometry_msgs::msg::PoseStamped & start,
754 const geometry_msgs::msg::PoseStamped & goal,
755 const std::string & planner_id,
756 const std::exception & ex,
757 std::string & error_msg)
759 std::stringstream ss;
760 ss << std::fixed << std::setprecision(2)
761 << planner_id <<
"plugin failed to plan from ("
762 << start.pose.position.x <<
", " << start.pose.position.y
764 << goal.pose.position.x <<
", " << goal.pose.position.y <<
")"
765 <<
": \"" << ex.what() <<
"\"";
767 error_msg = ss.str();
768 RCLCPP_WARN(get_logger(), error_msg.c_str());
773 #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.