15 #include "angles/angles.h"
16 #include "opennav_docking/docking_server.hpp"
17 #include "tf2_geometry_msgs/tf2_geometry_msgs.hpp"
18 #include "tf2/utils.hpp"
20 using namespace std::chrono_literals;
21 using rcl_interfaces::msg::ParameterType;
22 using std::placeholders::_1;
24 namespace opennav_docking
27 DockingServer::DockingServer(
const rclcpp::NodeOptions & options)
28 : nav2::LifecycleNode(
"docking_server",
"", options)
30 RCLCPP_INFO(get_logger(),
"Creating %s", get_name());
32 declare_parameter(
"controller_frequency", 50.0);
33 declare_parameter(
"initial_perception_timeout", 5.0);
34 declare_parameter(
"wait_charge_timeout", 5.0);
35 declare_parameter(
"dock_approach_timeout", 30.0);
36 declare_parameter(
"rotate_to_dock_timeout", 10.0);
37 declare_parameter(
"undock_linear_tolerance", 0.05);
38 declare_parameter(
"undock_angular_tolerance", 0.05);
39 declare_parameter(
"max_retries", 3);
40 declare_parameter(
"base_frame",
"base_link");
41 declare_parameter(
"fixed_frame",
"odom");
42 declare_parameter(
"dock_backwards", rclcpp::PARAMETER_BOOL);
43 declare_parameter(
"dock_prestaging_tolerance", 0.5);
44 declare_parameter(
"odom_topic",
"odom");
45 declare_parameter(
"odom_duration", 0.3);
46 declare_parameter(
"rotation_angular_tolerance", 0.05);
52 RCLCPP_INFO(get_logger(),
"Configuring %s", get_name());
55 get_parameter(
"controller_frequency", controller_frequency_);
56 get_parameter(
"initial_perception_timeout", initial_perception_timeout_);
57 get_parameter(
"wait_charge_timeout", wait_charge_timeout_);
58 get_parameter(
"dock_approach_timeout", dock_approach_timeout_);
59 get_parameter(
"rotate_to_dock_timeout", rotate_to_dock_timeout_);
60 get_parameter(
"undock_linear_tolerance", undock_linear_tolerance_);
61 get_parameter(
"undock_angular_tolerance", undock_angular_tolerance_);
62 get_parameter(
"max_retries", max_retries_);
63 get_parameter(
"base_frame", base_frame_);
64 get_parameter(
"fixed_frame", fixed_frame_);
65 get_parameter(
"dock_prestaging_tolerance", dock_prestaging_tolerance_);
66 get_parameter(
"rotation_angular_tolerance", rotation_angular_tolerance_);
68 RCLCPP_INFO(get_logger(),
"Controller frequency set to %.4fHz", controller_frequency_);
71 bool dock_backwards =
false;
73 if (get_parameter(
"dock_backwards", dock_backwards)) {
74 dock_backwards_ = dock_backwards;
75 RCLCPP_WARN(get_logger(),
"Parameter dock_backwards is deprecated. "
76 "Please use the dock_direction parameter in your dock plugin instead.");
78 }
catch (rclcpp::exceptions::ParameterUninitializedException & ex) {
81 vel_publisher_ = std::make_unique<nav2_util::TwistPublisher>(node,
"cmd_vel");
82 tf2_buffer_ = std::make_shared<tf2_ros::Buffer>(node->get_clock());
85 std::string odom_topic;
86 get_parameter(
"odom_topic", odom_topic);
88 get_parameter(
"odom_duration", odom_duration);
89 odom_sub_ = std::make_unique<nav2_util::OdomSmoother>(node, odom_duration, odom_topic);
92 docking_action_server_ = node->create_action_server<DockRobot>(
95 nullptr, std::chrono::milliseconds(500),
98 undocking_action_server_ = node->create_action_server<UndockRobot>(
101 nullptr, std::chrono::milliseconds(500),
105 mutex_ = std::make_shared<std::mutex>();
106 controller_ = std::make_unique<Controller>(node, tf2_buffer_, fixed_frame_, base_frame_);
107 navigator_ = std::make_unique<Navigator>(node);
108 dock_db_ = std::make_unique<DockDatabase>(mutex_);
109 if (!dock_db_->initialize(node, tf2_buffer_)) {
111 return nav2::CallbackReturn::FAILURE;
114 return nav2::CallbackReturn::SUCCESS;
120 RCLCPP_INFO(get_logger(),
"Activating %s", get_name());
124 tf2_listener_ = std::make_unique<tf2_ros::TransformListener>(*tf2_buffer_,
this,
true);
125 dock_db_->activate();
126 navigator_->activate();
127 vel_publisher_->on_activate();
128 docking_action_server_->activate();
129 undocking_action_server_->activate();
130 curr_dock_type_.clear();
133 dyn_params_handler_ = node->add_on_set_parameters_callback(
139 return nav2::CallbackReturn::SUCCESS;
145 RCLCPP_INFO(get_logger(),
"Deactivating %s", get_name());
147 docking_action_server_->deactivate();
148 undocking_action_server_->deactivate();
149 dock_db_->deactivate();
150 navigator_->deactivate();
151 vel_publisher_->on_deactivate();
153 remove_on_set_parameters_callback(dyn_params_handler_.get());
154 dyn_params_handler_.reset();
155 tf2_listener_.reset();
160 return nav2::CallbackReturn::SUCCESS;
166 RCLCPP_INFO(get_logger(),
"Cleaning up %s", get_name());
168 docking_action_server_.reset();
169 undocking_action_server_.reset();
172 curr_dock_type_.clear();
174 vel_publisher_.reset();
175 dock_backwards_.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::lock_guard<std::mutex> lock(*mutex_);
224 action_start_time_ = this->now();
225 rclcpp::Rate loop_rate(controller_frequency_);
227 auto goal = docking_action_server_->get_current_goal();
228 auto result = std::make_shared<DockRobot::Result>();
229 result->success =
false;
231 if (!docking_action_server_ || !docking_action_server_->is_server_active()) {
232 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
236 if (checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot")) {
237 docking_action_server_->terminate_all();
241 getPreemptedGoalIfRequested<DockRobot>(goal, docking_action_server_);
242 Dock * dock{
nullptr};
247 if (goal->use_dock_id) {
250 "Attempting to dock robot at %s.", goal->dock_id.c_str());
251 dock = dock_db_->findDock(goal->dock_id);
255 "Attempting to dock robot at position (%0.2f, %0.2f).",
256 goal->dock_pose.pose.position.x, goal->dock_pose.pose.position.y);
261 if (dock->plugin->isCharger() && (dock->plugin->isDocked() || dock->plugin->isCharging())) {
263 get_logger(),
"Robot is already docked and/or charging (if applicable), no need to dock");
264 result->success =
true;
265 docking_action_server_->succeeded_current(result);
271 const auto initial_staging_pose = dock->getStagingPose();
273 if (!goal->navigate_to_staging_pose ||
274 utils::l2Norm(robot_pose.pose, initial_staging_pose.pose) < dock_prestaging_tolerance_)
276 RCLCPP_INFO(get_logger(),
"Robot already within pre-staging pose tolerance for dock");
278 std::function<bool()> isPreempted = [
this]() {
279 return checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot") ||
280 checkAndWarnIfPreempted<DockRobot>(docking_action_server_,
"dock_robot");
283 navigator_->goToPose(
284 initial_staging_pose,
285 rclcpp::Duration::from_seconds(goal->max_staging_time),
287 RCLCPP_INFO(get_logger(),
"Successful navigation to staging pose");
291 auto dock_pose = utils::getDockPoseStamped(dock, rclcpp::Time(0));
292 tf2_buffer_->transform(dock_pose, dock_pose, fixed_frame_);
296 RCLCPP_INFO(get_logger(),
"Successful initial dock detection");
299 bool dock_backward = dock_backwards_.has_value() ?
300 dock_backwards_.value() :
301 (dock->plugin->getDockDirection() == opennav_docking_core::DockDirection::BACKWARD);
305 auto staging_pose = dock->getStagingPose();
306 if (dock->plugin->shouldRotateToDock()) {
307 staging_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(
308 tf2::getYaw(staging_pose.pose.orientation) + M_PI);
312 rclcpp::Time dock_contact_time;
313 while (rclcpp::ok()) {
316 if (dock->plugin->shouldRotateToDock()) {
323 get_logger(),
"Made contact with dock, waiting for charge to start (if applicable).");
326 if (dock->plugin->isCharger()) {
327 RCLCPP_INFO(get_logger(),
"Robot is charging!");
329 RCLCPP_INFO(get_logger(),
"Docking was successful!");
331 result->success =
true;
332 result->num_retries = num_retries_;
335 dock->plugin->stopDetectionProcess();
336 docking_action_server_->succeeded_current(result);
344 dock->plugin->stopDetectionProcess();
345 docking_action_server_->terminate_all(result);
348 if (++num_retries_ > max_retries_) {
349 RCLCPP_ERROR(get_logger(),
"Failed to dock, all retries have been used");
352 RCLCPP_WARN(get_logger(),
"Docking failed, will retry: %s", e.what());
360 dock->plugin->stopDetectionProcess();
361 docking_action_server_->terminate_all(result);
364 RCLCPP_INFO(get_logger(),
"Returned to staging pose, attempting docking again");
366 }
catch (
const tf2::TransformException & e) {
367 result->error_msg = std::string(
"Transform error: ") + e.what();
368 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
369 result->error_code = DockRobot::Result::UNKNOWN;
371 result->error_msg = e.what();
372 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
373 result->error_code = DockRobot::Result::DOCK_NOT_IN_DB;
375 result->error_msg = e.what();
376 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
377 result->error_code = DockRobot::Result::DOCK_NOT_VALID;
379 result->error_msg = e.what();
380 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
381 result->error_code = DockRobot::Result::FAILED_TO_STAGE;
383 result->error_msg = e.what();
384 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
385 result->error_code = DockRobot::Result::FAILED_TO_DETECT_DOCK;
387 result->error_msg = e.what();
388 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
389 result->error_code = DockRobot::Result::FAILED_TO_CONTROL;
391 result->error_msg = e.what();
392 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
393 result->error_code = DockRobot::Result::FAILED_TO_CHARGE;
395 result->error_msg = e.what();
396 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
397 result->error_code = DockRobot::Result::UNKNOWN;
398 }
catch (std::exception & e) {
399 result->error_code = DockRobot::Result::UNKNOWN;
400 result->error_msg = e.what();
401 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
406 result->num_retries = num_retries_;
408 dock->plugin->stopDetectionProcess();
409 docking_action_server_->terminate_current(result);
414 if (dock && successful) {
415 curr_dock_type_ = dock->type;
418 if (!use_dock_id && dock) {
426 auto dock =
new Dock();
427 dock->frame = goal->dock_pose.header.frame_id;
428 dock->pose = goal->dock_pose.pose;
429 dock->type = goal->dock_type;
430 dock->plugin = dock_db_->findDockPlugin(dock->type);
438 if (!dock->plugin->startDetectionProcess()) {
442 rclcpp::Rate loop_rate(controller_frequency_);
443 auto start = this->now();
444 auto timeout = rclcpp::Duration::from_seconds(initial_perception_timeout_);
445 while (!dock->plugin->getRefinedPose(dock_pose, dock->id)) {
446 if (this->now() - start > timeout) {
448 "Failed initial dock detection: Timeout exceeded");
451 if (checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot") ||
452 checkAndWarnIfPreempted<DockRobot>(docking_action_server_,
"dock_robot"))
463 const double dt = 1.0 / controller_frequency_;
464 auto target_pose = dock_pose;
465 target_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(
466 tf2::getYaw(target_pose.pose.orientation) + M_PI);
468 rclcpp::Rate loop_rate(controller_frequency_);
469 auto start = this->now();
470 auto timeout = rclcpp::Duration::from_seconds(rotate_to_dock_timeout_);
472 while (rclcpp::ok()) {
474 auto angular_distance_to_heading = angles::shortest_angular_distance(
475 tf2::getYaw(robot_pose.pose.orientation), tf2::getYaw(target_pose.pose.orientation));
476 if (fabs(angular_distance_to_heading) < rotation_angular_tolerance_) {
480 auto current_vel = std::make_unique<geometry_msgs::msg::TwistStamped>();
481 current_vel->twist.angular.z = odom_sub_->getRawTwist().angular.z;
483 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
484 command->header = robot_pose.header;
485 command->twist = controller_->computeRotateToHeadingCommand(
486 angular_distance_to_heading, current_vel->twist, dt);
488 vel_publisher_->publish(std::move(command));
490 if (this->now() - start > timeout) {
499 Dock * dock, geometry_msgs::msg::PoseStamped & dock_pose,
bool backward)
501 rclcpp::Rate loop_rate(controller_frequency_);
502 auto start = this->now();
503 auto timeout = rclcpp::Duration::from_seconds(dock_approach_timeout_);
505 while (rclcpp::ok()) {
509 if (dock->plugin->isDocked() || (dock->plugin->isCharger() && dock->plugin->isCharging())) {
514 if (checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot") ||
515 checkAndWarnIfPreempted<DockRobot>(docking_action_server_,
"dock_robot"))
521 if (!dock->plugin->getRefinedPose(dock_pose, dock->id) && !dock->plugin->shouldRotateToDock()) {
526 geometry_msgs::msg::PoseStamped target_pose = dock_pose;
527 target_pose.header.stamp = rclcpp::Time(0);
533 const double backward_projection = 0.25;
534 const double yaw = tf2::getYaw(target_pose.pose.orientation);
535 target_pose.pose.position.x += cos(yaw) * backward_projection;
536 target_pose.pose.position.y += sin(yaw) * backward_projection;
537 tf2_buffer_->transform(target_pose, target_pose, base_frame_);
542 target_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(
543 tf2::getYaw(target_pose.pose.orientation) + M_PI);
547 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
548 command->header.stamp = now();
549 if (!controller_->computeVelocityCommand(target_pose.pose, command->twist,
true, backward)) {
552 vel_publisher_->publish(std::move(command));
554 if (this->now() - start > timeout) {
556 "Timed out approaching dock; dock nor charging (if applicable) detected");
567 if (!dock->plugin->isCharger()) {
571 rclcpp::Rate loop_rate(controller_frequency_);
572 auto start = this->now();
573 auto timeout = rclcpp::Duration::from_seconds(wait_charge_timeout_);
574 while (rclcpp::ok()) {
577 if (dock->plugin->isCharging()) {
581 if (checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot") ||
582 checkAndWarnIfPreempted<DockRobot>(docking_action_server_,
"dock_robot"))
587 if (this->now() - start > timeout) {
597 const geometry_msgs::msg::PoseStamped & staging_pose,
bool backward)
599 rclcpp::Rate loop_rate(controller_frequency_);
600 auto start = this->now();
601 auto timeout = rclcpp::Duration::from_seconds(dock_approach_timeout_);
602 while (rclcpp::ok()) {
606 if (checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot") ||
607 checkAndWarnIfPreempted<DockRobot>(docking_action_server_,
"dock_robot"))
613 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
614 command->header.stamp = now();
616 command->twist, staging_pose, undock_linear_tolerance_, undock_angular_tolerance_,
false,
621 vel_publisher_->publish(std::move(command));
623 if (this->now() - start > timeout) {
633 geometry_msgs::msg::Twist & cmd,
const geometry_msgs::msg::PoseStamped & pose,
634 double linear_tolerance,
double angular_tolerance,
bool is_docking,
bool backward)
642 const double dist = std::hypot(
643 robot_pose.pose.position.x - pose.pose.position.x,
644 robot_pose.pose.position.y - pose.pose.position.y);
645 const double yaw = angles::shortest_angular_distance(
646 tf2::getYaw(robot_pose.pose.orientation), tf2::getYaw(pose.pose.orientation));
647 if (dist < linear_tolerance && abs(yaw) < angular_tolerance) {
652 geometry_msgs::msg::PoseStamped target_pose = pose;
653 target_pose.header.stamp = rclcpp::Time(0);
654 tf2_buffer_->transform(target_pose, target_pose, base_frame_);
657 if (!controller_->computeVelocityCommand(target_pose.pose, cmd, is_docking, backward)) {
667 std::lock_guard<std::mutex> lock(*mutex_);
668 action_start_time_ = this->now();
669 rclcpp::Rate loop_rate(controller_frequency_);
671 auto goal = undocking_action_server_->get_current_goal();
672 auto result = std::make_shared<UndockRobot::Result>();
673 result->success =
false;
675 if (!undocking_action_server_ || !undocking_action_server_->is_server_active()) {
676 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
680 if (checkAndWarnIfCancelled<UndockRobot>(undocking_action_server_,
"undock_robot")) {
681 undocking_action_server_->terminate_all(result);
685 getPreemptedGoalIfRequested<UndockRobot>(goal, undocking_action_server_);
686 auto max_duration = rclcpp::Duration::from_seconds(goal->max_undocking_time);
690 std::string dock_type = curr_dock_type_;
691 if (!goal->dock_type.empty()) {
692 dock_type = goal->dock_type;
695 ChargingDock::Ptr dock = dock_db_->findDockPlugin(dock_type);
701 "Attempting to undock robot of dock type %s.", dock->getName().c_str());
704 if (dock->isCharger() && (!dock->isDocked() && !dock->isCharging())) {
705 RCLCPP_INFO(get_logger(),
"Robot is not in the dock, no need to undock");
709 bool dock_backward = dock_backwards_.has_value() ?
710 dock_backwards_.value() :
711 (dock->getDockDirection() == opennav_docking_core::DockDirection::BACKWARD);
718 dock_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(
719 tf2::getYaw(dock_pose.pose.orientation) + M_PI);
723 geometry_msgs::msg::PoseStamped staging_pose =
724 dock->getStagingPose(dock_pose.pose, dock_pose.header.frame_id);
728 if (dock->shouldRotateToDock()) {
729 staging_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(
730 tf2::getYaw(staging_pose.pose.orientation) + M_PI);
734 rclcpp::Time loop_start = this->now();
735 while (rclcpp::ok()) {
737 auto timeout = rclcpp::Duration::from_seconds(goal->max_undocking_time);
738 if (this->now() - loop_start > timeout) {
743 if (checkAndWarnIfCancelled<UndockRobot>(undocking_action_server_,
"undock_robot") ||
744 checkAndWarnIfPreempted<UndockRobot>(undocking_action_server_,
"undock_robot"))
747 undocking_action_server_->terminate_all(result);
752 if (dock->isCharger() && !dock->disableCharging()) {
758 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
759 command->header.stamp = now();
762 command->twist, staging_pose, undock_linear_tolerance_, undock_angular_tolerance_,
false,
766 if (dock->shouldRotateToDock()) {
771 RCLCPP_INFO(get_logger(),
"Robot has reached staging pose");
772 vel_publisher_->publish(std::move(command));
773 if (!dock->isCharger() || dock->hasStoppedCharging()) {
774 RCLCPP_INFO(get_logger(),
"Robot has undocked!");
775 result->success =
true;
776 curr_dock_type_.clear();
778 undocking_action_server_->succeeded_current(result);
786 vel_publisher_->publish(std::move(command));
789 }
catch (
const tf2::TransformException & e) {
790 result->error_msg = std::string(
"Transform error: ") + e.what();
791 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
792 result->error_code = DockRobot::Result::UNKNOWN;
794 result->error_msg = e.what();
795 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
796 result->error_code = DockRobot::Result::DOCK_NOT_VALID;
798 result->error_msg = e.what();
799 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
800 result->error_code = DockRobot::Result::FAILED_TO_CONTROL;
802 result->error_msg = e.what();
803 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
804 result->error_code = DockRobot::Result::UNKNOWN;
805 }
catch (std::exception & e) {
806 result->error_msg = std::string(
"Internal error: ") + e.what();
807 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
808 result->error_code = DockRobot::Result::UNKNOWN;
812 undocking_action_server_->terminate_current(result);
817 geometry_msgs::msg::PoseStamped robot_pose;
818 robot_pose.header.frame_id = base_frame_;
819 robot_pose.header.stamp = rclcpp::Time(0);
820 tf2_buffer_->transform(robot_pose, robot_pose, frame);
826 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>();
827 cmd_vel->header.stamp = now();
828 vel_publisher_->publish(std::move(cmd_vel));
833 auto feedback = std::make_shared<DockRobot::Feedback>();
834 feedback->state = state;
835 feedback->docking_time = this->now() - action_start_time_;
836 feedback->num_retries = num_retries_;
837 docking_action_server_->publish_feedback(feedback);
840 rcl_interfaces::msg::SetParametersResult
843 std::lock_guard<std::mutex> lock(*mutex_);
845 rcl_interfaces::msg::SetParametersResult result;
846 for (
auto parameter : parameters) {
847 const auto & param_type = parameter.get_type();
848 const auto & param_name = parameter.get_name();
849 if (param_name.find(
'.') != std::string::npos) {
853 if (param_type == ParameterType::PARAMETER_DOUBLE) {
854 if (param_name ==
"controller_frequency") {
855 controller_frequency_ = parameter.as_double();
856 }
else if (param_name ==
"initial_perception_timeout") {
857 initial_perception_timeout_ = parameter.as_double();
858 }
else if (param_name ==
"wait_charge_timeout") {
859 wait_charge_timeout_ = parameter.as_double();
860 }
else if (param_name ==
"undock_linear_tolerance") {
861 undock_linear_tolerance_ = parameter.as_double();
862 }
else if (param_name ==
"undock_angular_tolerance") {
863 undock_angular_tolerance_ = parameter.as_double();
864 }
else if (param_name ==
"rotation_angular_tolerance") {
865 rotation_angular_tolerance_ = parameter.as_double();
867 }
else if (param_type == ParameterType::PARAMETER_STRING) {
868 if (param_name ==
"base_frame") {
869 base_frame_ = parameter.as_string();
870 }
else if (param_name ==
"fixed_frame") {
871 fixed_frame_ = parameter.as_string();
873 }
else if (param_type == ParameterType::PARAMETER_INTEGER) {
874 if (param_name ==
"max_retries") {
875 max_retries_ = parameter.as_int();
880 result.successful =
true;
886 #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.
An action server which implements charger docking node for AMRs.
rcl_interfaces::msg::SetParametersResult dynamicParametersCallback(std::vector< rclcpp::Parameter > parameters)
Callback executed when a parameter change is detected.
virtual geometry_msgs::msg::PoseStamped getRobotPoseInFrame(const std::string &frame)
Get the robot pose (aka base_frame pose) in another frame.
bool resetApproach(const geometry_msgs::msg::PoseStamped &staging_pose, bool backward)
Reset the robot for another approach by controlling back to staging pose.
void dockRobot()
Main action callback method to complete docking request.
nav2::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &state) override
Deactivate member variables.
nav2::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &state) override
Reset member variables.
bool approachDock(Dock *dock, geometry_msgs::msg::PoseStamped &dock_pose, bool backward)
Use control law and dock perception to approach the charge dock.
void doInitialPerception(Dock *dock, geometry_msgs::msg::PoseStamped &dock_pose)
Do initial perception, up to a timeout.
void publishDockingFeedback(uint16_t state)
Publish feedback from a docking action.
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.
bool checkAndWarnIfPreempted(typename nav2::SimpleActionServer< ActionT >::SharedPtr &action_server, const std::string &name)
Checks and logs warning if action preempted.
bool getCommandToPose(geometry_msgs::msg::Twist &cmd, const geometry_msgs::msg::PoseStamped &pose, double linear_tolerance, double angular_tolerance, bool is_docking, bool backward)
Run a single iteration of the control loop to approach a pose.
bool waitForCharge(Dock *dock)
Wait for charging to begin.
Dock * generateGoalDock(std::shared_ptr< const DockRobot::Goal > goal)
Generate a dock from action goal.
nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
Activate member variables.
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.
nav2::CallbackReturn on_configure(const rclcpp_lifecycle::State &state) override
Configure member variables.
void publishZeroVelocity()
Publish zero velocity at terminal condition.
void rotateToDock(const geometry_msgs::msg::PoseStamped &dock_pose)
Perform a pure rotation to dock orientation.
void undockRobot()
Main action callback method to complete undocking request.
void stashDockData(bool use_dock_id, Dock *dock, bool successful)
Called at the conclusion of docking actions. Saves relevant docking data for later undocking action.
Dock was not found in the provided dock database.
Dock plugin provided in the database or action was invalid.
Abstract docking exception.
Failed to start charging.
Failed to control into or out of the dock.
Failed to detect the charging dock.
Failed to navigate to the staging pose.