16 #include "angles/angles.h"
17 #include "opennav_docking_core/docking_exceptions.hpp"
18 #include "opennav_following/following_server.hpp"
19 #include "nav2_util/geometry_utils.hpp"
20 #include "nav2_util/robot_utils.hpp"
21 #include "tf2_geometry_msgs/tf2_geometry_msgs.hpp"
22 #include "tf2/utils.hpp"
24 using namespace std::chrono_literals;
25 using rcl_interfaces::msg::ParameterType;
26 using std::placeholders::_1;
28 namespace opennav_following
31 FollowingServer::FollowingServer(
const rclcpp::NodeOptions & options)
32 : nav2::LifecycleNode(
"following_server",
"", options)
34 RCLCPP_INFO(get_logger(),
"Creating %s", get_name());
36 declare_parameter(
"controller_frequency", 50.0);
37 declare_parameter(
"detection_timeout", 2.0);
38 declare_parameter(
"rotate_to_object_timeout", 10.0);
39 declare_parameter(
"static_object_timeout", -1.0);
40 declare_parameter(
"linear_tolerance", 0.15);
41 declare_parameter(
"angular_tolerance", 0.15);
42 declare_parameter(
"max_retries", 3);
43 declare_parameter(
"base_frame",
"base_link");
44 declare_parameter(
"fixed_frame",
"odom");
45 declare_parameter(
"filter_coef", 0.1);
46 declare_parameter(
"desired_distance", 1.0);
47 declare_parameter(
"skip_orientation",
true);
48 declare_parameter(
"search_by_rotating",
false);
49 declare_parameter(
"search_angle", M_PI_2);
50 declare_parameter(
"odom_topic",
"odom");
51 declare_parameter(
"odom_duration", 0.3);
52 declare_parameter(
"transform_tolerance", 0.1);
58 RCLCPP_INFO(get_logger(),
"Configuring %s", get_name());
61 get_parameter(
"controller_frequency", controller_frequency_);
62 get_parameter(
"detection_timeout", detection_timeout_);
63 get_parameter(
"rotate_to_object_timeout", rotate_to_object_timeout_);
64 get_parameter(
"static_object_timeout", static_object_timeout_);
65 get_parameter(
"linear_tolerance", linear_tolerance_);
66 get_parameter(
"angular_tolerance", angular_tolerance_);
67 get_parameter(
"max_retries", max_retries_);
68 get_parameter(
"base_frame", base_frame_);
69 get_parameter(
"fixed_frame", fixed_frame_);
70 get_parameter(
"desired_distance", desired_distance_);
71 get_parameter(
"skip_orientation", skip_orientation_);
72 get_parameter(
"search_by_rotating", search_by_rotating_);
73 get_parameter(
"search_angle", search_angle_);
74 get_parameter(
"transform_tolerance", transform_tolerance_);
75 RCLCPP_INFO(get_logger(),
"Controller frequency set to %.4fHz", controller_frequency_);
77 vel_publisher_ = std::make_unique<nav2_util::TwistPublisher>(node,
"cmd_vel");
78 tf2_buffer_ = std::make_shared<tf2_ros::Buffer>(node->get_clock());
81 std::string odom_topic;
82 get_parameter(
"odom_topic", odom_topic);
84 get_parameter(
"odom_duration", odom_duration);
85 odom_sub_ = std::make_unique<nav2_util::OdomSmoother>(node, odom_duration, odom_topic);
88 following_action_server_ = node->create_action_server<FollowObject>(
91 nullptr, std::chrono::milliseconds(500),
97 declare_parameter(
"controller.use_collision_detection",
false);
99 std::make_unique<opennav_docking::Controller>(node, tf2_buffer_, fixed_frame_, base_frame_);
101 auto get_use_collision_detection =
false;
102 get_parameter(
"controller.use_collision_detection", get_use_collision_detection);
103 if (get_use_collision_detection) {
104 RCLCPP_ERROR(get_logger(),
105 "Collision detection is not supported in the following server. Please disable "
106 "the controller.use_collision_detection parameter.");
107 return nav2::CallbackReturn::FAILURE;
112 get_parameter(
"filter_coef", filter_coef);
113 filter_ = std::make_unique<opennav_docking::PoseFilter>(filter_coef, detection_timeout_);
116 filtered_dynamic_pose_pub_ =
117 create_publisher<geometry_msgs::msg::PoseStamped>(
"filtered_dynamic_pose");
120 static_timer_initialized_ =
false;
121 static_object_start_time_ = rclcpp::Time(0);
123 return nav2::CallbackReturn::SUCCESS;
129 RCLCPP_INFO(get_logger(),
"Activating %s", get_name());
133 tf2_listener_ = std::make_unique<tf2_ros::TransformListener>(*tf2_buffer_,
this,
true);
134 vel_publisher_->on_activate();
135 filtered_dynamic_pose_pub_->on_activate();
136 following_action_server_->activate();
139 dyn_params_handler_ = node->add_on_set_parameters_callback(
145 return nav2::CallbackReturn::SUCCESS;
151 RCLCPP_INFO(get_logger(),
"Deactivating %s", get_name());
153 following_action_server_->deactivate();
154 vel_publisher_->on_deactivate();
155 filtered_dynamic_pose_pub_->on_deactivate();
157 remove_on_set_parameters_callback(dyn_params_handler_.get());
158 dyn_params_handler_.reset();
159 tf2_listener_.reset();
164 return nav2::CallbackReturn::SUCCESS;
170 RCLCPP_INFO(get_logger(),
"Cleaning up %s", get_name());
172 following_action_server_.reset();
174 vel_publisher_.reset();
175 filtered_dynamic_pose_pub_.reset();
177 return nav2::CallbackReturn::SUCCESS;
183 RCLCPP_INFO(get_logger(),
"Shutting down %s", get_name());
184 return nav2::CallbackReturn::SUCCESS;
187 template<
typename ActionT>
189 typename std::shared_ptr<const typename ActionT::Goal> goal,
190 const typename nav2::SimpleActionServer<ActionT>::SharedPtr & action_server)
197 template<
typename ActionT>
199 typename nav2::SimpleActionServer<ActionT>::SharedPtr & action_server,
200 const std::string & name)
203 RCLCPP_WARN(get_logger(),
"Goal was cancelled. Cancelling %s action", name.c_str());
209 template<
typename ActionT>
211 typename nav2::SimpleActionServer<ActionT>::SharedPtr & action_server,
212 const std::string & name)
215 RCLCPP_WARN(get_logger(),
"Goal was preempted. Cancelling %s action", name.c_str());
223 std::unique_lock<std::mutex> lock(dynamic_params_lock_);
224 action_start_time_ = this->now();
225 rclcpp::Rate loop_rate(controller_frequency_);
227 auto goal = following_action_server_->get_current_goal();
228 auto result = std::make_shared<FollowObject::Result>();
230 if (!following_action_server_ || !following_action_server_->is_server_active()) {
231 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
235 if (checkAndWarnIfCancelled<FollowObject>(following_action_server_,
"follow_object")) {
236 following_action_server_->terminate_all();
240 getPreemptedGoalIfRequested<FollowObject>(goal, following_action_server_);
242 static_timer_initialized_ =
false;
245 detected_dynamic_pose_.header.stamp = rclcpp::Time(0);
248 auto pose_topic = goal->pose_topic;
249 auto target_frame = goal->tracked_frame;
250 if (target_frame.empty()) {
251 if (pose_topic.empty()) {
252 RCLCPP_ERROR(get_logger(),
253 "Both pose topic and target frame are empty. Cannot follow object.");
254 result->error_code = FollowObject::Result::FAILED_TO_DETECT_OBJECT;
255 result->error_msg =
"No pose topic or target frame provided.";
256 following_action_server_->terminate_all(result);
260 RCLCPP_INFO(get_logger(),
"Subscribing to pose topic: %s", pose_topic.c_str());
261 dynamic_pose_sub_ = create_subscription<geometry_msgs::msg::PoseStamped>(
263 [
this](
const geometry_msgs::msg::PoseStamped::SharedPtr pose) {
264 detected_dynamic_pose_ = *pose;
270 RCLCPP_INFO(get_logger(),
"Following frame: %s instead of pose", target_frame.c_str());
274 geometry_msgs::msg::PoseStamped object_pose;
275 rclcpp::Duration max_duration = goal->max_duration;
276 while (rclcpp::ok()) {
279 if (this->now() - action_start_time_ > max_duration && max_duration.seconds() > 0.0) {
280 RCLCPP_INFO(get_logger(),
"Exceeded max duration. Stopping.");
281 result->total_elapsed_time = this->now() - action_start_time_;
282 result->num_retries = num_retries_;
284 following_action_server_->succeeded_current(result);
285 dynamic_pose_sub_.reset();
292 if (!static_timer_initialized_) {
293 static_object_start_time_ = this->now();
294 static_timer_initialized_ =
true;
298 RCLCPP_INFO_THROTTLE(
299 get_logger(), *get_clock(), 1000,
300 "Reached object. Stopping until goal is moved again.");
305 if (static_object_timeout_ > 0.0) {
306 auto static_duration = this->now() - static_object_start_time_;
307 if (static_duration.seconds() > static_object_timeout_) {
308 RCLCPP_INFO(get_logger(),
309 "Object has been static for %.2f seconds (timeout: %.2f), stopping.",
310 static_duration.seconds(), static_object_timeout_);
311 result->total_elapsed_time = this->now() - action_start_time_;
312 result->num_retries = num_retries_;
314 following_action_server_->succeeded_current(result);
320 static_timer_initialized_ =
false;
321 result->total_elapsed_time = this->now() - action_start_time_;
323 following_action_server_->terminate_all(result);
324 dynamic_pose_sub_.reset();
328 if (++num_retries_ > max_retries_) {
329 RCLCPP_ERROR(get_logger(),
"Failed to follow, all retries have been used");
332 RCLCPP_WARN(get_logger(),
"Following failed, will retry: %s", e.what());
335 if (search_by_rotating_) {
336 RCLCPP_INFO(get_logger(),
"Rotating to find object again");
340 following_action_server_->terminate_all(result);
344 RCLCPP_INFO(get_logger(),
"Using last known heading to find object again");
349 }
catch (
const tf2::TransformException & e) {
350 result->error_msg = std::string(
"Transform error: ") + e.what();
351 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
352 result->error_code = FollowObject::Result::TF_ERROR;
354 result->error_msg = e.what();
355 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
356 result->error_code = FollowObject::Result::FAILED_TO_DETECT_OBJECT;
358 result->error_msg = e.what();
359 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
360 result->error_code = FollowObject::Result::FAILED_TO_CONTROL;
362 result->error_msg = e.what();
363 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
364 result->error_code = FollowObject::Result::UNKNOWN;
365 }
catch (std::exception & e) {
366 result->error_msg = e.what();
367 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
368 result->error_code = FollowObject::Result::UNKNOWN;
372 result->total_elapsed_time = this->now() - action_start_time_;
373 result->num_retries = num_retries_;
375 following_action_server_->terminate_current(result);
376 dynamic_pose_sub_.reset();
380 geometry_msgs::msg::PoseStamped & object_pose,
const std::string & target_frame)
382 rclcpp::Rate loop_rate(controller_frequency_);
383 while (rclcpp::ok()) {
385 iteration_start_time_ = this->now();
390 if (checkAndWarnIfCancelled<FollowObject>(following_action_server_,
"follow_object") ||
391 checkAndWarnIfPreempted<FollowObject>(following_action_server_,
"follow_object"))
410 const double backward_projection = 0.25;
411 const double effective_distance = desired_distance_ - backward_projection;
416 tf2_buffer_->transform(
417 target_pose, target_pose, base_frame_, tf2::durationFromSec(transform_tolerance_));
418 }
catch (
const tf2::TransformException & ex) {
419 RCLCPP_WARN(get_logger(),
"Failed to transform target pose: %s", ex.what());
424 geometry_msgs::msg::PoseStamped robot_pose;
425 if (!nav2_util::getCurrentPose(
426 robot_pose, *tf2_buffer_, target_pose.header.frame_id, base_frame_, transform_tolerance_,
427 iteration_start_time_))
429 RCLCPP_WARN(get_logger(),
"Failed to get current robot pose");
434 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
435 command->header.stamp = now();
436 if (!controller_->computeVelocityCommand(target_pose.pose, command->twist,
true,
false)) {
439 vel_publisher_->publish(std::move(command));
447 geometry_msgs::msg::PoseStamped & object_pose,
const std::string & target_frame)
449 const double dt = 1.0 / controller_frequency_;
452 geometry_msgs::msg::PoseStamped robot_pose;
453 if (!nav2_util::getCurrentPose(
454 robot_pose, *tf2_buffer_, object_pose.header.frame_id, base_frame_, transform_tolerance_,
455 iteration_start_time_))
457 RCLCPP_WARN(get_logger(),
"Failed to get current robot pose");
460 double initial_yaw = tf2::getYaw(robot_pose.pose.orientation);
463 std::vector<double> angles = {initial_yaw + search_angle_, initial_yaw - search_angle_};
465 rclcpp::Rate loop_rate(controller_frequency_);
466 auto start = this->now();
467 auto timeout = rclcpp::Duration::from_seconds(rotate_to_object_timeout_);
470 for (
const double & target_angle : angles) {
472 auto target_pose = object_pose;
473 target_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(target_angle);
476 while (rclcpp::ok()) {
478 iteration_start_time_ = this->now();
483 if (checkAndWarnIfCancelled<FollowObject>(following_action_server_,
"follow_object") ||
484 checkAndWarnIfPreempted<FollowObject>(following_action_server_,
"follow_object"))
490 if (!nav2_util::getCurrentPose(
491 robot_pose, *tf2_buffer_, object_pose.header.frame_id, base_frame_, transform_tolerance_,
492 iteration_start_time_))
494 RCLCPP_WARN(get_logger(),
"Failed to get current robot pose");
498 double angular_distance_to_heading = angles::shortest_angular_distance(
499 tf2::getYaw(robot_pose.pose.orientation), target_angle);
502 if (fabs(angular_distance_to_heading) < angular_tolerance_) {
515 geometry_msgs::msg::Twist current_vel;
516 current_vel.angular.z = odom_sub_->getRawTwist().angular.z;
518 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
519 command->header = robot_pose.header;
520 command->twist = controller_->computeRotateToHeadingCommand(
521 angular_distance_to_heading, current_vel, dt);
523 vel_publisher_->publish(std::move(command));
525 if (this->now() - start > timeout) {
539 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>();
540 cmd_vel->header.frame_id = base_frame_;
541 cmd_vel->header.stamp = now();
542 vel_publisher_->publish(std::move(cmd_vel));
547 auto feedback = std::make_shared<FollowObject::Feedback>();
548 feedback->state = state;
549 feedback->following_time = iteration_start_time_ - action_start_time_;
550 feedback->num_retries = num_retries_;
551 following_action_server_->publish_feedback(feedback);
557 geometry_msgs::msg::PoseStamped detected = detected_dynamic_pose_;
560 if (detected.header.stamp == rclcpp::Time(0)) {
561 auto start = this->now();
562 auto timeout = rclcpp::Duration::from_seconds(detection_timeout_);
563 rclcpp::Rate wait_rate(controller_frequency_);
564 while (this->now() - start < timeout) {
566 if (detected_dynamic_pose_.header.stamp != rclcpp::Time(0)) {
567 detected = detected_dynamic_pose_;
572 if (detected.header.stamp == rclcpp::Time(0)) {
573 RCLCPP_WARN(this->get_logger(),
"No detection received within timeout period");
579 auto timeout = rclcpp::Duration::from_seconds(detection_timeout_);
580 if (this->now() - detected.header.stamp > timeout) {
581 RCLCPP_WARN(this->get_logger(),
"Lost detection or did not detect: timeout exceeded");
586 if (detected.header.frame_id != fixed_frame_) {
588 tf2_buffer_->transform(
589 detected, detected, fixed_frame_, tf2::durationFromSec(transform_tolerance_));
590 }
catch (
const tf2::TransformException & ex) {
591 RCLCPP_WARN(this->get_logger(),
"Failed to transform detected object pose");
600 if (skip_orientation_) {
601 geometry_msgs::msg::PoseStamped robot_pose;
602 if (!nav2_util::getCurrentPose(
603 robot_pose, *tf2_buffer_, detected.header.frame_id, base_frame_, transform_tolerance_,
604 iteration_start_time_))
606 RCLCPP_WARN(get_logger(),
"Failed to get current robot pose");
609 double dx = detected.pose.position.x - robot_pose.pose.position.x;
610 double dy = detected.pose.position.y - robot_pose.pose.position.y;
611 double angle_to_target = std::atan2(dy, dx);
612 detected.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(angle_to_target);
616 auto pose_filtered = filter_->update(detected);
617 filtered_dynamic_pose_pub_->publish(pose_filtered);
619 pose = pose_filtered;
624 geometry_msgs::msg::PoseStamped & pose,
const std::string & frame_id)
628 auto transform = tf2_buffer_->lookupTransform(
629 fixed_frame_, frame_id, iteration_start_time_, tf2::durationFromSec(transform_tolerance_));
632 pose.header.frame_id = fixed_frame_;
633 pose.header.stamp = transform.header.stamp;
634 pose.pose.position.x = transform.transform.translation.x;
635 pose.pose.position.y = transform.transform.translation.y;
636 pose.pose.position.z = transform.transform.translation.z;
637 pose.pose.orientation = transform.transform.rotation;
638 }
catch (
const tf2::TransformException & ex) {
639 RCLCPP_WARN(get_logger(),
640 "Failed to get transform for frame %s: %s", frame_id.c_str(), ex.what());
645 auto filtered_pose = filter_->update(pose);
646 filtered_dynamic_pose_pub_->publish(filtered_pose);
648 pose = filtered_pose;
653 geometry_msgs::msg::PoseStamped & pose,
const std::string & frame_id)
656 if (!frame_id.empty()) {
659 "Failed to get pose in target frame: " + frame_id);
671 const geometry_msgs::msg::PoseStamped & pose,
double distance)
673 geometry_msgs::msg::PoseStamped robot_pose;
674 if (!nav2_util::getCurrentPose(
675 robot_pose, *tf2_buffer_, pose.header.frame_id, base_frame_, transform_tolerance_,
676 iteration_start_time_))
678 RCLCPP_WARN(get_logger(),
"Failed to get current robot pose");
682 double dx = pose.pose.position.x - robot_pose.pose.position.x;
683 double dy = pose.pose.position.y - robot_pose.pose.position.y;
684 const double dist = std::hypot(dx, dy);
685 geometry_msgs::msg::PoseStamped forward_pose = pose;
686 forward_pose.pose.position.x -= distance * (dx / dist);
687 forward_pose.pose.position.y -= distance * (dy / dist);
693 geometry_msgs::msg::PoseStamped robot_pose;
694 if (!nav2_util::getCurrentPose(
695 robot_pose, *tf2_buffer_, goal_pose.header.frame_id, base_frame_, transform_tolerance_,
696 iteration_start_time_))
698 RCLCPP_WARN(get_logger(),
"Failed to get current robot pose");
701 const double dist = std::hypot(
702 robot_pose.pose.position.x - goal_pose.pose.position.x,
703 robot_pose.pose.position.y - goal_pose.pose.position.y);
704 const double yaw = angles::shortest_angular_distance(
705 tf2::getYaw(robot_pose.pose.orientation), tf2::getYaw(goal_pose.pose.orientation));
706 return dist < linear_tolerance_ && abs(yaw) < angular_tolerance_;
709 rcl_interfaces::msg::SetParametersResult
712 std::lock_guard<std::mutex> lock(dynamic_params_lock_);
714 rcl_interfaces::msg::SetParametersResult result;
715 for (
auto parameter : parameters) {
716 const auto & type = parameter.get_type();
717 const auto & name = parameter.get_name();
719 if (type == ParameterType::PARAMETER_DOUBLE) {
720 if (name ==
"controller_frequency") {
721 controller_frequency_ = parameter.as_double();
722 }
else if (name ==
"detection_timeout") {
723 detection_timeout_ = parameter.as_double();
724 }
else if (name ==
"rotate_to_object_timeout") {
725 rotate_to_object_timeout_ = parameter.as_double();
726 }
else if (name ==
"static_object_timeout") {
727 static_object_timeout_ = parameter.as_double();
728 }
else if (name ==
"linear_tolerance") {
729 linear_tolerance_ = parameter.as_double();
730 }
else if (name ==
"angular_tolerance") {
731 angular_tolerance_ = parameter.as_double();
732 }
else if (name ==
"desired_distance") {
733 desired_distance_ = parameter.as_double();
734 }
else if (name ==
"transform_tolerance") {
735 transform_tolerance_ = parameter.as_double();
736 }
else if (name ==
"search_angle") {
737 search_angle_ = parameter.as_double();
739 }
else if (type == ParameterType::PARAMETER_STRING) {
740 if (name ==
"base_frame") {
741 base_frame_ = parameter.as_string();
742 }
else if (name ==
"fixed_frame") {
743 fixed_frame_ = parameter.as_string();
745 }
else if (type == ParameterType::PARAMETER_BOOL) {
746 if (name ==
"skip_orientation") {
747 skip_orientation_ = parameter.as_bool();
748 }
else if (name ==
"search_by_rotating") {
749 search_by_rotating_ = parameter.as_bool();
754 result.successful =
true;
760 #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.
bool is_preempt_requested() const
Whether the action server has been asked to be preempted with a new goal.
const std::shared_ptr< const typename ActionT::Goal > accept_pending_goal()
Accept pending goals.
A QoS profile for standard reliable topics with a history of 10 messages.
Abstract docking exception.
Failed to control into or out of the dock.
Failed to detect the charging dock.
An action server which implements a dynamic following behavior.
bool checkAndWarnIfCancelled(typename nav2::SimpleActionServer< ActionT >::SharedPtr &action_server, const std::string &name)
Checks and logs warning if action canceled.
nav2::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &state) override
Called when in shutdown state.
void followObject()
Main action callback method to complete following request.
virtual bool getFramePose(geometry_msgs::msg::PoseStamped &pose, const std::string &frame_id)
Get the pose of a specific frame in the fixed frame.
virtual bool approachObject(geometry_msgs::msg::PoseStamped &object_pose, const std::string &target_frame=std::string(""))
Use control law and perception to approach the object.
virtual bool getTrackingPose(geometry_msgs::msg::PoseStamped &pose, const std::string &frame_id)
Get the tracking pose based on the current tracking mode.
void publishFollowingFeedback(uint16_t state)
Publish feedback from a following action.
geometry_msgs::msg::PoseStamped getPoseAtDistance(const geometry_msgs::msg::PoseStamped &pose, double distance)
Get the pose at a distance in front of the input pose.
virtual bool getRefinedPose(geometry_msgs::msg::PoseStamped &pose)
Method to obtain the refined dynamic pose.
nav2::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &state) override
Deactivate member variables.
void publishZeroVelocity()
Publish zero velocity at terminal condition.
void getPreemptedGoalIfRequested(typename std::shared_ptr< const typename ActionT::Goal > goal, const typename nav2::SimpleActionServer< ActionT >::SharedPtr &action_server)
Gets a preempted goal if immediately requested.
bool isGoalReached(const geometry_msgs::msg::PoseStamped &goal_pose)
Check if the goal has been reached.
rcl_interfaces::msg::SetParametersResult dynamicParametersCallback(std::vector< rclcpp::Parameter > parameters)
Callback executed when a parameter change is detected.
virtual bool rotateToObject(geometry_msgs::msg::PoseStamped &object_pose, const std::string &target_frame=std::string(""))
Rotate the robot to find the object again.
bool checkAndWarnIfPreempted(typename nav2::SimpleActionServer< ActionT >::SharedPtr &action_server, const std::string &name)
Checks and logs warning if action preempted.
nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
Activate member variables.
nav2::CallbackReturn on_configure(const rclcpp_lifecycle::State &state) override
Configure member variables.
nav2::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &state) override
Reset member variables.