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).");
325 if (dock->plugin->isCharger()) {
326 RCLCPP_INFO(get_logger(),
"Robot is charging!");
328 RCLCPP_INFO(get_logger(),
"Docking was successful!");
330 result->success =
true;
331 result->num_retries = num_retries_;
334 docking_action_server_->succeeded_current(result);
342 docking_action_server_->terminate_all(result);
345 if (++num_retries_ > max_retries_) {
346 RCLCPP_ERROR(get_logger(),
"Failed to dock, all retries have been used");
349 RCLCPP_WARN(get_logger(),
"Docking failed, will retry: %s", e.what());
357 docking_action_server_->terminate_all(result);
360 RCLCPP_INFO(get_logger(),
"Returned to staging pose, attempting docking again");
362 }
catch (
const tf2::TransformException & e) {
363 result->error_msg = std::string(
"Transform error: ") + e.what();
364 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
365 result->error_code = DockRobot::Result::UNKNOWN;
367 result->error_msg = e.what();
368 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
369 result->error_code = DockRobot::Result::DOCK_NOT_IN_DB;
371 result->error_msg = e.what();
372 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
373 result->error_code = DockRobot::Result::DOCK_NOT_VALID;
375 result->error_msg = e.what();
376 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
377 result->error_code = DockRobot::Result::FAILED_TO_STAGE;
379 result->error_msg = e.what();
380 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
381 result->error_code = DockRobot::Result::FAILED_TO_DETECT_DOCK;
383 result->error_msg = e.what();
384 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
385 result->error_code = DockRobot::Result::FAILED_TO_CONTROL;
387 result->error_msg = e.what();
388 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
389 result->error_code = DockRobot::Result::FAILED_TO_CHARGE;
391 result->error_msg = e.what();
392 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
393 result->error_code = DockRobot::Result::UNKNOWN;
394 }
catch (std::exception & e) {
395 result->error_code = DockRobot::Result::UNKNOWN;
396 result->error_msg = e.what();
397 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
402 result->num_retries = num_retries_;
404 docking_action_server_->terminate_current(result);
409 if (dock && successful) {
410 curr_dock_type_ = dock->type;
413 if (!use_dock_id && dock) {
421 auto dock =
new Dock();
422 dock->frame = goal->dock_pose.header.frame_id;
423 dock->pose = goal->dock_pose.pose;
424 dock->type = goal->dock_type;
425 dock->plugin = dock_db_->findDockPlugin(dock->type);
432 rclcpp::Rate loop_rate(controller_frequency_);
433 auto start = this->now();
434 auto timeout = rclcpp::Duration::from_seconds(initial_perception_timeout_);
435 while (!dock->plugin->getRefinedPose(dock_pose, dock->id)) {
436 if (this->now() - start > timeout) {
440 if (checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot") ||
441 checkAndWarnIfPreempted<DockRobot>(docking_action_server_,
"dock_robot"))
452 const double dt = 1.0 / controller_frequency_;
453 auto target_pose = dock_pose;
454 target_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(
455 tf2::getYaw(target_pose.pose.orientation) + M_PI);
457 rclcpp::Rate loop_rate(controller_frequency_);
458 auto start = this->now();
459 auto timeout = rclcpp::Duration::from_seconds(rotate_to_dock_timeout_);
461 while (rclcpp::ok()) {
463 auto angular_distance_to_heading = angles::shortest_angular_distance(
464 tf2::getYaw(robot_pose.pose.orientation), tf2::getYaw(target_pose.pose.orientation));
465 if (fabs(angular_distance_to_heading) < rotation_angular_tolerance_) {
469 auto current_vel = std::make_unique<geometry_msgs::msg::TwistStamped>();
470 current_vel->twist.angular.z = odom_sub_->getRawTwist().angular.z;
472 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
473 command->header = robot_pose.header;
474 command->twist = controller_->computeRotateToHeadingCommand(
475 angular_distance_to_heading, current_vel->twist, dt);
477 vel_publisher_->publish(std::move(command));
479 if (this->now() - start > timeout) {
488 Dock * dock, geometry_msgs::msg::PoseStamped & dock_pose,
bool backward)
490 rclcpp::Rate loop_rate(controller_frequency_);
491 auto start = this->now();
492 auto timeout = rclcpp::Duration::from_seconds(dock_approach_timeout_);
494 while (rclcpp::ok()) {
498 if (dock->plugin->isDocked() || (dock->plugin->isCharger() && dock->plugin->isCharging())) {
503 if (checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot") ||
504 checkAndWarnIfPreempted<DockRobot>(docking_action_server_,
"dock_robot"))
510 if (!dock->plugin->getRefinedPose(dock_pose, dock->id) && !dock->plugin->shouldRotateToDock()) {
515 geometry_msgs::msg::PoseStamped target_pose = dock_pose;
516 target_pose.header.stamp = rclcpp::Time(0);
522 const double backward_projection = 0.25;
523 const double yaw = tf2::getYaw(target_pose.pose.orientation);
524 target_pose.pose.position.x += cos(yaw) * backward_projection;
525 target_pose.pose.position.y += sin(yaw) * backward_projection;
526 tf2_buffer_->transform(target_pose, target_pose, base_frame_);
531 target_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(
532 tf2::getYaw(target_pose.pose.orientation) + M_PI);
536 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
537 command->header.stamp = now();
538 if (!controller_->computeVelocityCommand(target_pose.pose, command->twist,
true, backward)) {
541 vel_publisher_->publish(std::move(command));
543 if (this->now() - start > timeout) {
545 "Timed out approaching dock; dock nor charging (if applicable) detected");
556 if (!dock->plugin->isCharger()) {
560 rclcpp::Rate loop_rate(controller_frequency_);
561 auto start = this->now();
562 auto timeout = rclcpp::Duration::from_seconds(wait_charge_timeout_);
563 while (rclcpp::ok()) {
566 if (dock->plugin->isCharging()) {
570 if (checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot") ||
571 checkAndWarnIfPreempted<DockRobot>(docking_action_server_,
"dock_robot"))
576 if (this->now() - start > timeout) {
586 const geometry_msgs::msg::PoseStamped & staging_pose,
bool backward)
588 rclcpp::Rate loop_rate(controller_frequency_);
589 auto start = this->now();
590 auto timeout = rclcpp::Duration::from_seconds(dock_approach_timeout_);
591 while (rclcpp::ok()) {
595 if (checkAndWarnIfCancelled<DockRobot>(docking_action_server_,
"dock_robot") ||
596 checkAndWarnIfPreempted<DockRobot>(docking_action_server_,
"dock_robot"))
602 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
603 command->header.stamp = now();
605 command->twist, staging_pose, undock_linear_tolerance_, undock_angular_tolerance_,
false,
610 vel_publisher_->publish(std::move(command));
612 if (this->now() - start > timeout) {
622 geometry_msgs::msg::Twist & cmd,
const geometry_msgs::msg::PoseStamped & pose,
623 double linear_tolerance,
double angular_tolerance,
bool is_docking,
bool backward)
631 const double dist = std::hypot(
632 robot_pose.pose.position.x - pose.pose.position.x,
633 robot_pose.pose.position.y - pose.pose.position.y);
634 const double yaw = angles::shortest_angular_distance(
635 tf2::getYaw(robot_pose.pose.orientation), tf2::getYaw(pose.pose.orientation));
636 if (dist < linear_tolerance && abs(yaw) < angular_tolerance) {
641 geometry_msgs::msg::PoseStamped target_pose = pose;
642 target_pose.header.stamp = rclcpp::Time(0);
643 tf2_buffer_->transform(target_pose, target_pose, base_frame_);
646 if (!controller_->computeVelocityCommand(target_pose.pose, cmd, is_docking, backward)) {
656 std::lock_guard<std::mutex> lock(*mutex_);
657 action_start_time_ = this->now();
658 rclcpp::Rate loop_rate(controller_frequency_);
660 auto goal = undocking_action_server_->get_current_goal();
661 auto result = std::make_shared<UndockRobot::Result>();
662 result->success =
false;
664 if (!undocking_action_server_ || !undocking_action_server_->is_server_active()) {
665 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
669 if (checkAndWarnIfCancelled<UndockRobot>(undocking_action_server_,
"undock_robot")) {
670 undocking_action_server_->terminate_all(result);
674 getPreemptedGoalIfRequested<UndockRobot>(goal, undocking_action_server_);
675 auto max_duration = rclcpp::Duration::from_seconds(goal->max_undocking_time);
679 std::string dock_type = curr_dock_type_;
680 if (!goal->dock_type.empty()) {
681 dock_type = goal->dock_type;
684 ChargingDock::Ptr dock = dock_db_->findDockPlugin(dock_type);
690 "Attempting to undock robot of dock type %s.", dock->getName().c_str());
693 if (dock->isCharger() && (!dock->isDocked() && !dock->isCharging())) {
694 RCLCPP_INFO(get_logger(),
"Robot is not in the dock, no need to undock");
698 bool dock_backward = dock_backwards_.has_value() ?
699 dock_backwards_.value() :
700 (dock->getDockDirection() == opennav_docking_core::DockDirection::BACKWARD);
707 dock_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(
708 tf2::getYaw(dock_pose.pose.orientation) + M_PI);
712 geometry_msgs::msg::PoseStamped staging_pose =
713 dock->getStagingPose(dock_pose.pose, dock_pose.header.frame_id);
717 if (dock->shouldRotateToDock()) {
718 staging_pose.pose.orientation = nav2_util::geometry_utils::orientationAroundZAxis(
719 tf2::getYaw(staging_pose.pose.orientation) + M_PI);
723 rclcpp::Time loop_start = this->now();
724 while (rclcpp::ok()) {
726 auto timeout = rclcpp::Duration::from_seconds(goal->max_undocking_time);
727 if (this->now() - loop_start > timeout) {
732 if (checkAndWarnIfCancelled<UndockRobot>(undocking_action_server_,
"undock_robot") ||
733 checkAndWarnIfPreempted<UndockRobot>(undocking_action_server_,
"undock_robot"))
736 undocking_action_server_->terminate_all(result);
741 if (dock->isCharger() && !dock->disableCharging()) {
747 auto command = std::make_unique<geometry_msgs::msg::TwistStamped>();
748 command->header.stamp = now();
751 command->twist, staging_pose, undock_linear_tolerance_, undock_angular_tolerance_,
false,
755 if (dock->shouldRotateToDock()) {
760 RCLCPP_INFO(get_logger(),
"Robot has reached staging pose");
761 vel_publisher_->publish(std::move(command));
762 if (!dock->isCharger() || dock->hasStoppedCharging()) {
763 RCLCPP_INFO(get_logger(),
"Robot has undocked!");
764 result->success =
true;
765 curr_dock_type_.clear();
767 undocking_action_server_->succeeded_current(result);
775 vel_publisher_->publish(std::move(command));
778 }
catch (
const tf2::TransformException & e) {
779 result->error_msg = std::string(
"Transform error: ") + e.what();
780 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
781 result->error_code = DockRobot::Result::UNKNOWN;
783 result->error_msg = e.what();
784 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
785 result->error_code = DockRobot::Result::DOCK_NOT_VALID;
787 result->error_msg = e.what();
788 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
789 result->error_code = DockRobot::Result::FAILED_TO_CONTROL;
791 result->error_msg = e.what();
792 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
793 result->error_code = DockRobot::Result::UNKNOWN;
794 }
catch (std::exception & e) {
795 result->error_msg = std::string(
"Internal error: ") + e.what();
796 RCLCPP_ERROR(get_logger(), result->error_msg.c_str());
797 result->error_code = DockRobot::Result::UNKNOWN;
801 undocking_action_server_->terminate_current(result);
806 geometry_msgs::msg::PoseStamped robot_pose;
807 robot_pose.header.frame_id = base_frame_;
808 robot_pose.header.stamp = rclcpp::Time(0);
809 tf2_buffer_->transform(robot_pose, robot_pose, frame);
815 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>();
816 cmd_vel->header.stamp = now();
817 vel_publisher_->publish(std::move(cmd_vel));
822 auto feedback = std::make_shared<DockRobot::Feedback>();
823 feedback->state = state;
824 feedback->docking_time = this->now() - action_start_time_;
825 feedback->num_retries = num_retries_;
826 docking_action_server_->publish_feedback(feedback);
829 rcl_interfaces::msg::SetParametersResult
832 std::lock_guard<std::mutex> lock(*mutex_);
834 rcl_interfaces::msg::SetParametersResult result;
835 for (
auto parameter : parameters) {
836 const auto & param_type = parameter.get_type();
837 const auto & param_name = parameter.get_name();
838 if (param_name.find(
'.') != std::string::npos) {
842 if (param_type == ParameterType::PARAMETER_DOUBLE) {
843 if (param_name ==
"controller_frequency") {
844 controller_frequency_ = parameter.as_double();
845 }
else if (param_name ==
"initial_perception_timeout") {
846 initial_perception_timeout_ = parameter.as_double();
847 }
else if (param_name ==
"wait_charge_timeout") {
848 wait_charge_timeout_ = parameter.as_double();
849 }
else if (param_name ==
"undock_linear_tolerance") {
850 undock_linear_tolerance_ = parameter.as_double();
851 }
else if (param_name ==
"undock_angular_tolerance") {
852 undock_angular_tolerance_ = parameter.as_double();
853 }
else if (param_name ==
"rotation_angular_tolerance") {
854 rotation_angular_tolerance_ = parameter.as_double();
856 }
else if (param_type == ParameterType::PARAMETER_STRING) {
857 if (param_name ==
"base_frame") {
858 base_frame_ = parameter.as_string();
859 }
else if (param_name ==
"fixed_frame") {
860 fixed_frame_ = parameter.as_string();
862 }
else if (param_type == ParameterType::PARAMETER_INTEGER) {
863 if (param_name ==
"max_retries") {
864 max_retries_ = parameter.as_int();
869 result.successful =
true;
875 #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.