22 #include "lifecycle_msgs/msg/state.hpp"
23 #include "nav2_core/controller_exceptions.hpp"
24 #include "nav_2d_utils/conversions.hpp"
25 #include "nav_2d_utils/tf_help.hpp"
26 #include "nav2_util/node_utils.hpp"
27 #include "nav2_util/geometry_utils.hpp"
28 #include "nav2_controller/controller_server.hpp"
30 using namespace std::chrono_literals;
31 using rcl_interfaces::msg::ParameterType;
32 using std::placeholders::_1;
34 namespace nav2_controller
37 ControllerServer::ControllerServer(
const rclcpp::NodeOptions & options)
38 : nav2_util::LifecycleNode(
"controller_server",
"", options),
39 progress_checker_loader_(
"nav2_core",
"nav2_core::ProgressChecker"),
40 default_progress_checker_ids_{
"progress_checker"},
41 default_progress_checker_types_{
"nav2_controller::SimpleProgressChecker"},
42 goal_checker_loader_(
"nav2_core",
"nav2_core::GoalChecker"),
43 default_goal_checker_ids_{
"goal_checker"},
44 default_goal_checker_types_{
"nav2_controller::SimpleGoalChecker"},
45 lp_loader_(
"nav2_core",
"nav2_core::Controller"),
46 default_ids_{
"FollowPath"},
47 default_types_{
"dwb_core::DWBLocalPlanner"},
48 costmap_update_timeout_(300ms)
50 RCLCPP_INFO(get_logger(),
"Creating controller server");
52 declare_parameter(
"controller_frequency", 20.0);
54 declare_parameter(
"action_server_result_timeout", 10.0);
56 declare_parameter(
"progress_checker_plugins", default_progress_checker_ids_);
57 declare_parameter(
"goal_checker_plugins", default_goal_checker_ids_);
58 declare_parameter(
"controller_plugins", default_ids_);
59 declare_parameter(
"min_x_velocity_threshold", rclcpp::ParameterValue(0.0001));
60 declare_parameter(
"min_y_velocity_threshold", rclcpp::ParameterValue(0.0001));
61 declare_parameter(
"min_theta_velocity_threshold", rclcpp::ParameterValue(0.0001));
63 declare_parameter(
"speed_limit_topic", rclcpp::ParameterValue(
"speed_limit"));
65 declare_parameter(
"failure_tolerance", rclcpp::ParameterValue(0.0));
66 declare_parameter(
"use_realtime_priority", rclcpp::ParameterValue(
false));
67 declare_parameter(
"publish_zero_velocity", rclcpp::ParameterValue(
true));
68 declare_parameter(
"costmap_update_timeout", 0.30);
71 costmap_ros_ = std::make_shared<nav2_costmap_2d::Costmap2DROS>(
72 "local_costmap", std::string{get_namespace()},
"local_costmap",
73 get_parameter(
"use_sim_time").as_bool());
78 progress_checkers_.clear();
79 goal_checkers_.clear();
81 costmap_thread_.reset();
84 nav2_util::CallbackReturn
89 RCLCPP_INFO(get_logger(),
"Configuring controller interface");
91 RCLCPP_INFO(get_logger(),
"getting progress checker plugins..");
92 get_parameter(
"progress_checker_plugins", progress_checker_ids_);
93 if (progress_checker_ids_ == default_progress_checker_ids_) {
94 for (
size_t i = 0; i < default_progress_checker_ids_.size(); ++i) {
95 nav2_util::declare_parameter_if_not_declared(
96 node, default_progress_checker_ids_[i] +
".plugin",
97 rclcpp::ParameterValue(default_progress_checker_types_[i]));
101 RCLCPP_INFO(get_logger(),
"getting goal checker plugins..");
102 get_parameter(
"goal_checker_plugins", goal_checker_ids_);
103 if (goal_checker_ids_ == default_goal_checker_ids_) {
104 for (
size_t i = 0; i < default_goal_checker_ids_.size(); ++i) {
105 nav2_util::declare_parameter_if_not_declared(
106 node, default_goal_checker_ids_[i] +
".plugin",
107 rclcpp::ParameterValue(default_goal_checker_types_[i]));
111 get_parameter(
"controller_plugins", controller_ids_);
112 if (controller_ids_ == default_ids_) {
113 for (
size_t i = 0; i < default_ids_.size(); ++i) {
114 nav2_util::declare_parameter_if_not_declared(
115 node, default_ids_[i] +
".plugin",
116 rclcpp::ParameterValue(default_types_[i]));
120 controller_types_.resize(controller_ids_.size());
121 goal_checker_types_.resize(goal_checker_ids_.size());
122 progress_checker_types_.resize(progress_checker_ids_.size());
124 get_parameter(
"controller_frequency", controller_frequency_);
125 get_parameter(
"min_x_velocity_threshold", min_x_velocity_threshold_);
126 get_parameter(
"min_y_velocity_threshold", min_y_velocity_threshold_);
127 get_parameter(
"min_theta_velocity_threshold", min_theta_velocity_threshold_);
128 RCLCPP_INFO(get_logger(),
"Controller frequency set to %.4fHz", controller_frequency_);
130 std::string speed_limit_topic;
131 get_parameter(
"speed_limit_topic", speed_limit_topic);
132 get_parameter(
"failure_tolerance", failure_tolerance_);
133 get_parameter(
"use_realtime_priority", use_realtime_priority_);
135 costmap_ros_->configure();
137 costmap_thread_ = std::make_unique<nav2_util::NodeThread>(costmap_ros_);
139 for (
size_t i = 0; i != progress_checker_ids_.size(); i++) {
141 progress_checker_types_[i] = nav2_util::get_plugin_type_param(
142 node, progress_checker_ids_[i]);
143 nav2_core::ProgressChecker::Ptr progress_checker =
144 progress_checker_loader_.createUniqueInstance(progress_checker_types_[i]);
146 get_logger(),
"Created progress_checker : %s of type %s",
147 progress_checker_ids_[i].c_str(), progress_checker_types_[i].c_str());
148 progress_checker->initialize(node, progress_checker_ids_[i]);
149 progress_checkers_.insert({progress_checker_ids_[i], progress_checker});
150 }
catch (
const std::exception & ex) {
153 "Failed to create progress_checker. Exception: %s", ex.what());
155 return nav2_util::CallbackReturn::FAILURE;
159 for (
size_t i = 0; i != progress_checker_ids_.size(); i++) {
160 progress_checker_ids_concat_ += progress_checker_ids_[i] + std::string(
" ");
162 if (progress_checker_ids_concat_.empty()) {
163 progress_checker_ids_concat_ =
"(none)";
168 "Controller Server has %s progress checkers available.", progress_checker_ids_concat_.c_str());
170 for (
size_t i = 0; i != goal_checker_ids_.size(); i++) {
172 goal_checker_types_[i] = nav2_util::get_plugin_type_param(node, goal_checker_ids_[i]);
173 nav2_core::GoalChecker::Ptr goal_checker =
174 goal_checker_loader_.createUniqueInstance(goal_checker_types_[i]);
176 get_logger(),
"Created goal checker : %s of type %s",
177 goal_checker_ids_[i].c_str(), goal_checker_types_[i].c_str());
178 goal_checker->initialize(node, goal_checker_ids_[i], costmap_ros_);
179 goal_checkers_.insert({goal_checker_ids_[i], goal_checker});
180 }
catch (
const pluginlib::PluginlibException & ex) {
183 "Failed to create goal checker. Exception: %s", ex.what());
185 return nav2_util::CallbackReturn::FAILURE;
189 for (
size_t i = 0; i != goal_checker_ids_.size(); i++) {
190 goal_checker_ids_concat_ += goal_checker_ids_[i] + std::string(
" ");
195 "Controller Server has %s goal checkers available.", goal_checker_ids_concat_.c_str());
197 for (
size_t i = 0; i != controller_ids_.size(); i++) {
199 controller_types_[i] = nav2_util::get_plugin_type_param(node, controller_ids_[i]);
200 nav2_core::Controller::Ptr controller =
201 lp_loader_.createUniqueInstance(controller_types_[i]);
203 get_logger(),
"Created controller : %s of type %s",
204 controller_ids_[i].c_str(), controller_types_[i].c_str());
205 controller->configure(
206 node, controller_ids_[i],
207 costmap_ros_->getTfBuffer(), costmap_ros_);
208 controllers_.insert({controller_ids_[i], controller});
209 }
catch (
const pluginlib::PluginlibException & ex) {
212 "Failed to create controller. Exception: %s", ex.what());
214 return nav2_util::CallbackReturn::FAILURE;
218 for (
size_t i = 0; i != controller_ids_.size(); i++) {
219 controller_ids_concat_ += controller_ids_[i] + std::string(
" ");
224 "Controller Server has %s controllers available.", controller_ids_concat_.c_str());
226 odom_sub_ = std::make_unique<nav_2d_utils::OdomSubscriber>(node);
227 vel_publisher_ = std::make_unique<nav2_util::TwistPublisher>(node,
"cmd_vel", 1);
229 double action_server_result_timeout;
230 get_parameter(
"action_server_result_timeout", action_server_result_timeout);
231 rcl_action_server_options_t server_options = rcl_action_server_get_default_options();
232 server_options.result_timeout.nanoseconds = RCL_S_TO_NS(action_server_result_timeout);
234 double costmap_update_timeout_dbl;
235 get_parameter(
"costmap_update_timeout", costmap_update_timeout_dbl);
236 costmap_update_timeout_ = rclcpp::Duration::from_seconds(costmap_update_timeout_dbl);
241 action_server_ = std::make_unique<ActionServer>(
246 std::chrono::milliseconds(500),
247 true , server_options, use_realtime_priority_ );
248 }
catch (
const std::runtime_error & e) {
249 RCLCPP_ERROR(get_logger(),
"Error creating action server! %s", e.what());
251 return nav2_util::CallbackReturn::FAILURE;
255 speed_limit_sub_ = create_subscription<nav2_msgs::msg::SpeedLimit>(
256 speed_limit_topic, rclcpp::QoS(10),
257 std::bind(&ControllerServer::speedLimitCallback,
this, std::placeholders::_1));
259 return nav2_util::CallbackReturn::SUCCESS;
262 nav2_util::CallbackReturn
265 RCLCPP_INFO(get_logger(),
"Activating");
267 const auto costmap_ros_state = costmap_ros_->activate();
268 if (costmap_ros_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) {
269 return nav2_util::CallbackReturn::FAILURE;
271 ControllerMap::iterator it;
272 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
273 it->second->activate();
275 vel_publisher_->on_activate();
276 action_server_->activate();
280 dyn_params_handler_ = node->add_on_set_parameters_callback(
286 return nav2_util::CallbackReturn::SUCCESS;
289 nav2_util::CallbackReturn
292 RCLCPP_INFO(get_logger(),
"Deactivating");
294 action_server_->deactivate();
295 ControllerMap::iterator it;
296 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
297 it->second->deactivate();
307 costmap_ros_->deactivate();
310 geometry_msgs::msg::TwistStamped velocity;
311 velocity.twist.angular.x = 0;
312 velocity.twist.angular.y = 0;
313 velocity.twist.angular.z = 0;
314 velocity.twist.linear.x = 0;
315 velocity.twist.linear.y = 0;
316 velocity.twist.linear.z = 0;
317 velocity.header.frame_id = costmap_ros_->getBaseFrameID();
318 velocity.header.stamp = now();
321 vel_publisher_->on_deactivate();
323 remove_on_set_parameters_callback(dyn_params_handler_.get());
324 dyn_params_handler_.reset();
329 return nav2_util::CallbackReturn::SUCCESS;
332 nav2_util::CallbackReturn
335 RCLCPP_INFO(get_logger(),
"Cleaning up");
338 ControllerMap::iterator it;
339 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
340 it->second->cleanup();
342 controllers_.clear();
344 goal_checkers_.clear();
345 progress_checkers_.clear();
347 costmap_ros_->cleanup();
351 action_server_.reset();
353 costmap_thread_.reset();
354 vel_publisher_.reset();
355 speed_limit_sub_.reset();
357 return nav2_util::CallbackReturn::SUCCESS;
360 nav2_util::CallbackReturn
363 RCLCPP_INFO(get_logger(),
"Shutting down");
364 return nav2_util::CallbackReturn::SUCCESS;
368 const std::string & c_name,
369 std::string & current_controller)
371 if (controllers_.find(c_name) == controllers_.end()) {
372 if (controllers_.size() == 1 && c_name.empty()) {
374 get_logger(),
"No controller was specified in action call."
375 " Server will use only plugin loaded %s. "
376 "This warning will appear once.", controller_ids_concat_.c_str());
377 current_controller = controllers_.begin()->first;
380 get_logger(),
"FollowPath called with controller name %s, "
381 "which does not exist. Available controllers are: %s.",
382 c_name.c_str(), controller_ids_concat_.c_str());
386 RCLCPP_DEBUG(get_logger(),
"Selected controller: %s.", c_name.c_str());
387 current_controller = c_name;
394 const std::string & c_name,
395 std::string & current_goal_checker)
397 if (goal_checkers_.find(c_name) == goal_checkers_.end()) {
398 if (goal_checkers_.size() == 1 && c_name.empty()) {
400 get_logger(),
"No goal checker was specified in parameter 'current_goal_checker'."
401 " Server will use only plugin loaded %s. "
402 "This warning will appear once.", goal_checker_ids_concat_.c_str());
403 current_goal_checker = goal_checkers_.begin()->first;
406 get_logger(),
"FollowPath called with goal_checker name %s in parameter"
407 " 'current_goal_checker', which does not exist. Available goal checkers are: %s.",
408 c_name.c_str(), goal_checker_ids_concat_.c_str());
412 RCLCPP_DEBUG(get_logger(),
"Selected goal checker: %s.", c_name.c_str());
413 current_goal_checker = c_name;
420 const std::string & c_name,
421 std::string & current_progress_checker)
423 if (progress_checkers_.size() == 0) {
424 if (c_name.empty()) {
427 "No progress checker configured and none requested. Progress checking will be bypassed.");
428 current_progress_checker =
"";
432 get_logger(),
"FollowPath called with progress_checker name %s in parameter"
433 " 'current_progress_checker', but no progress checkers are configured.",
439 if (progress_checkers_.find(c_name) == progress_checkers_.end()) {
440 if (progress_checkers_.size() == 1 && c_name.empty()) {
442 get_logger(),
"No progress checker was specified in parameter 'current_progress_checker'."
443 " Server will use only plugin loaded %s. "
444 "This warning will appear once.", progress_checker_ids_concat_.c_str());
445 current_progress_checker = progress_checkers_.begin()->first;
448 get_logger(),
"FollowPath called with progress_checker name %s in parameter"
449 " 'current_progress_checker', which does not exist. Available progress checkers are: %s.",
450 c_name.c_str(), progress_checker_ids_concat_.c_str());
454 RCLCPP_DEBUG(get_logger(),
"Selected progress checker: %s.", c_name.c_str());
455 current_progress_checker = c_name;
463 std::lock_guard<std::mutex> lock(dynamic_params_lock_);
465 RCLCPP_INFO(get_logger(),
"Received a goal, begin computing control effort.");
468 auto goal = action_server_->get_current_goal();
473 std::string c_name = goal->controller_id;
474 std::string current_controller;
476 current_controller_ = current_controller;
481 std::string gc_name = goal->goal_checker_id;
482 std::string current_goal_checker;
484 current_goal_checker_ = current_goal_checker;
489 std::string pc_name = goal->progress_checker_id;
490 std::string current_progress_checker;
492 current_progress_checker_ = current_progress_checker;
498 if (!current_progress_checker_.empty()) {
499 progress_checkers_[current_progress_checker_]->reset();
502 last_valid_cmd_time_ = now();
503 rclcpp::WallRate loop_rate(controller_frequency_);
504 while (rclcpp::ok()) {
505 auto start_time = this->now();
507 if (action_server_ ==
nullptr || !action_server_->is_server_active()) {
508 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
512 if (action_server_->is_cancel_requested()) {
513 if (controllers_[current_controller_]->cancel()) {
514 RCLCPP_INFO(get_logger(),
"Cancellation was successful. Stopping the robot.");
515 action_server_->terminate_all();
519 RCLCPP_INFO_THROTTLE(
520 get_logger(), *get_clock(), 1000,
"Waiting for the controller to finish cancellation");
526 auto waiting_start = now();
527 while (!costmap_ros_->isCurrent()) {
528 if (now() - waiting_start > costmap_update_timeout_) {
537 RCLCPP_INFO(get_logger(),
"Reached the goal!");
543 auto cycle_duration = this->now() - start_time;
544 if (!loop_rate.sleep()) {
547 "Control loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz.",
548 controller_frequency_, 1 / cycle_duration.seconds());
553 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
555 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
556 result->error_code = Action::Result::INVALID_CONTROLLER;
557 action_server_->terminate_current(result);
560 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
562 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
563 result->error_code = Action::Result::TF_ERROR;
564 action_server_->terminate_current(result);
567 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
569 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
570 result->error_code = Action::Result::NO_VALID_CONTROL;
571 action_server_->terminate_current(result);
574 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
576 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
577 result->error_code = Action::Result::FAILED_TO_MAKE_PROGRESS;
578 action_server_->terminate_current(result);
581 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
583 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
584 result->error_code = Action::Result::PATIENCE_EXCEEDED;
585 action_server_->terminate_current(result);
588 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
590 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
591 result->error_code = Action::Result::INVALID_PATH;
592 action_server_->terminate_current(result);
595 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
597 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
598 result->error_code = Action::Result::CONTROLLER_TIMED_OUT;
599 action_server_->terminate_current(result);
602 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
604 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
605 result->error_code = Action::Result::UNKNOWN;
606 action_server_->terminate_current(result);
608 }
catch (std::exception & e) {
609 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
611 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
612 result->error_code = Action::Result::UNKNOWN;
613 action_server_->terminate_current(result);
617 RCLCPP_DEBUG(get_logger(),
"Controller succeeded, setting result");
622 action_server_->succeeded_current();
629 "Providing path to the controller %s", current_controller_.c_str());
630 if (path.poses.empty()) {
633 controllers_[current_controller_]->setPlan(path);
635 end_pose_ = path.poses.back();
636 end_pose_.header.frame_id = path.header.frame_id;
637 goal_checkers_[current_goal_checker_]->reset();
640 get_logger(),
"Path end point is (%.2f, %.2f)",
641 end_pose_.pose.position.x, end_pose_.pose.position.y);
643 current_path_ = path;
648 geometry_msgs::msg::PoseStamped pose;
654 if (!current_progress_checker_.empty()) {
655 if (!progress_checkers_[current_progress_checker_]->check(pose)) {
662 geometry_msgs::msg::TwistStamped cmd_vel_2d;
666 controllers_[current_controller_]->computeVelocityCommands(
668 nav_2d_utils::twist2Dto3D(twist),
669 goal_checkers_[current_goal_checker_].get());
670 last_valid_cmd_time_ = now();
671 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
672 cmd_vel_2d.header.stamp = last_valid_cmd_time_;
676 if (failure_tolerance_ > 0 || failure_tolerance_ == -1.0) {
677 RCLCPP_WARN(this->get_logger(),
"%s", e.what());
678 cmd_vel_2d.twist.angular.x = 0;
679 cmd_vel_2d.twist.angular.y = 0;
680 cmd_vel_2d.twist.angular.z = 0;
681 cmd_vel_2d.twist.linear.x = 0;
682 cmd_vel_2d.twist.linear.y = 0;
683 cmd_vel_2d.twist.linear.z = 0;
684 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
685 cmd_vel_2d.header.stamp = now();
686 if ((now() - last_valid_cmd_time_).seconds() > failure_tolerance_ &&
687 failure_tolerance_ != -1.0)
696 std::shared_ptr<Action::Feedback> feedback = std::make_shared<Action::Feedback>();
697 feedback->speed = std::hypot(cmd_vel_2d.twist.linear.x, cmd_vel_2d.twist.linear.y);
700 nav_msgs::msg::Path & current_path = current_path_;
701 auto find_closest_pose_idx =
702 [&pose, ¤t_path]() {
703 size_t closest_pose_idx = 0;
704 double curr_min_dist = std::numeric_limits<double>::max();
705 for (
size_t curr_idx = 0; curr_idx < current_path.poses.size(); ++curr_idx) {
706 double curr_dist = nav2_util::geometry_utils::euclidean_distance(
707 pose, current_path.poses[curr_idx]);
708 if (curr_dist < curr_min_dist) {
709 curr_min_dist = curr_dist;
710 closest_pose_idx = curr_idx;
713 return closest_pose_idx;
716 feedback->distance_to_goal =
717 nav2_util::geometry_utils::calculate_path_length(current_path_, find_closest_pose_idx());
718 action_server_->publish_feedback(feedback);
720 RCLCPP_DEBUG(get_logger(),
"Publishing velocity at time %.2f", now().seconds());
726 if (action_server_->is_preempt_requested()) {
727 RCLCPP_INFO(get_logger(),
"Passing new path to controller.");
728 auto goal = action_server_->accept_pending_goal();
729 std::string current_controller;
731 current_controller_ = current_controller;
734 get_logger(),
"Terminating action, invalid controller %s requested.",
735 goal->controller_id.c_str());
736 action_server_->terminate_current();
739 std::string current_goal_checker;
741 current_goal_checker_ = current_goal_checker;
744 get_logger(),
"Terminating action, invalid goal checker %s requested.",
745 goal->goal_checker_id.c_str());
746 action_server_->terminate_current();
749 std::string current_progress_checker;
751 if (current_progress_checker_ != current_progress_checker) {
753 get_logger(),
"Change of progress checker %s requested, resetting it",
754 goal->progress_checker_id.c_str());
755 current_progress_checker_ = current_progress_checker;
756 if (!current_progress_checker_.empty()) {
757 progress_checkers_[current_progress_checker_]->reset();
762 get_logger(),
"Terminating action, invalid progress checker %s requested.",
763 goal->progress_checker_id.c_str());
764 action_server_->terminate_current();
773 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>(velocity);
774 if (vel_publisher_->is_activated() && vel_publisher_->get_subscription_count() > 0) {
775 vel_publisher_->publish(std::move(cmd_vel));
781 if (get_parameter(
"publish_zero_velocity").as_bool()) {
782 geometry_msgs::msg::TwistStamped velocity;
783 velocity.twist.angular.x = 0;
784 velocity.twist.angular.y = 0;
785 velocity.twist.angular.z = 0;
786 velocity.twist.linear.x = 0;
787 velocity.twist.linear.y = 0;
788 velocity.twist.linear.z = 0;
789 velocity.header.frame_id = costmap_ros_->getBaseFrameID();
790 velocity.header.stamp = now();
795 ControllerMap::iterator it;
796 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
803 geometry_msgs::msg::PoseStamped pose;
810 geometry_msgs::msg::Twist velocity = nav_2d_utils::twist2Dto3D(twist);
812 geometry_msgs::msg::PoseStamped transformed_end_pose;
813 rclcpp::Duration tolerance(rclcpp::Duration::from_seconds(costmap_ros_->getTransformTolerance()));
814 if(!nav_2d_utils::transformPose(
815 costmap_ros_->getTfBuffer(), costmap_ros_->getGlobalFrameID(),
816 end_pose_, transformed_end_pose, tolerance))
821 return goal_checkers_[current_goal_checker_]->isGoalReached(
822 pose.pose, transformed_end_pose.pose,
828 geometry_msgs::msg::PoseStamped current_pose;
829 if (!costmap_ros_->getRobotPose(current_pose)) {
836 void ControllerServer::speedLimitCallback(
const nav2_msgs::msg::SpeedLimit::SharedPtr msg)
838 ControllerMap::iterator it;
839 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
840 it->second->setSpeedLimit(msg->speed_limit, msg->percentage);
844 rcl_interfaces::msg::SetParametersResult
847 rcl_interfaces::msg::SetParametersResult result;
849 for (
auto parameter : parameters) {
850 const auto & type = parameter.get_type();
851 const auto & name = parameter.get_name();
855 if (name.find(
'.') != std::string::npos) {
859 if (!dynamic_params_lock_.try_lock()) {
862 "Unable to dynamically change Parameters while the controller is currently running");
863 result.successful =
false;
865 "Unable to dynamically change Parameters while the controller is currently running";
869 if (type == ParameterType::PARAMETER_DOUBLE) {
870 if (name ==
"controller_frequency") {
871 controller_frequency_ = parameter.as_double();
872 }
else if (name ==
"min_x_velocity_threshold") {
873 min_x_velocity_threshold_ = parameter.as_double();
874 }
else if (name ==
"min_y_velocity_threshold") {
875 min_y_velocity_threshold_ = parameter.as_double();
876 }
else if (name ==
"min_theta_velocity_threshold") {
877 min_theta_velocity_threshold_ = parameter.as_double();
878 }
else if (name ==
"failure_tolerance") {
879 failure_tolerance_ = parameter.as_double();
883 dynamic_params_lock_.unlock();
886 result.successful =
true;
892 #include "rclcpp_components/register_node_macro.hpp"
This class hosts variety of plugins of different algorithms to complete control tasks from the expose...
rcl_interfaces::msg::SetParametersResult dynamicParametersCallback(std::vector< rclcpp::Parameter > parameters)
Callback executed when a parameter change is detected.
void publishVelocity(const geometry_msgs::msg::TwistStamped &velocity)
Calls velocity publisher to publish the velocity on "cmd_vel" topic.
bool getRobotPose(geometry_msgs::msg::PoseStamped &pose)
Obtain current pose of the robot.
nav_2d_msgs::msg::Twist2D getThresholdedTwist(const nav_2d_msgs::msg::Twist2D &twist)
get the thresholded Twist
void computeControl()
FollowPath action server callback. Handles action server updates and spins server until goal is reach...
bool isGoalReached()
Checks if goal is reached.
nav2_util::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &state) override
Deactivates member variables.
~ControllerServer()
Destructor for nav2_controller::ControllerServer.
nav2_util::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
Activates member variables.
bool findGoalCheckerId(const std::string &c_name, std::string &name)
Find the valid goal checker ID name for the specified parameter.
nav2_util::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &state) override
Calls clean up states and resets member variables.
void updateGlobalPath()
Calls setPlannerPath method with an updated path received from action server.
void setPlannerPath(const nav_msgs::msg::Path &path)
Assigns path to controller.
void publishZeroVelocity()
Calls velocity publisher to publish zero velocity.
nav2_util::CallbackReturn on_configure(const rclcpp_lifecycle::State &state) override
Configures controller parameters and member variables.
nav2_util::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &state) override
Called when in Shutdown state.
bool findControllerId(const std::string &c_name, std::string &name)
Find the valid controller ID name for the given request.
bool findProgressCheckerId(const std::string &c_name, std::string &name)
Find the valid progress checker ID name for the specified parameter.
void computeAndPublishVelocity()
Calculates velocity and publishes to "cmd_vel" topic.
std::shared_ptr< nav2_util::LifecycleNode > shared_from_this()
Get a shared pointer of this.
void createBond()
Create bond connection to lifecycle manager.
void destroyBond()
Destroy bond connection to lifecycle manager.