22 #include "lifecycle_msgs/msg/state.hpp"
23 #include "nav2_core/controller_exceptions.hpp"
24 #include "nav2_ros_common/node_utils.hpp"
25 #include "nav2_ros_common/rate.hpp"
26 #include "nav2_util/geometry_utils.hpp"
27 #include "nav2_util/path_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;
33 using nav2_util::geometry_utils::euclidean_distance;
35 namespace nav2_controller
38 ControllerServer::ControllerServer(
const rclcpp::NodeOptions & options)
39 : nav2::LifecycleNode(
"controller_server",
"", options),
40 progress_checker_loader_(
"nav2_core",
"nav2_core::ProgressChecker"),
41 goal_checker_loader_(
"nav2_core",
"nav2_core::GoalChecker"),
42 lp_loader_(
"nav2_core",
"nav2_core::Controller"),
43 path_handler_loader_(
"nav2_core",
"nav2_core::PathHandler"),
46 RCLCPP_INFO(get_logger(),
"Creating controller server");
49 costmap_ros_ = std::make_shared<nav2_costmap_2d::Costmap2DROS>(
50 "local_costmap", std::string{get_namespace()},
51 get_parameter(
"use_sim_time").as_bool(), options);
56 progress_checkers_.clear();
57 goal_checkers_.clear();
59 path_handlers_.clear();
60 costmap_thread_.reset();
68 RCLCPP_INFO(get_logger(),
"Configuring controller interface");
70 if (costmap_ros_->configure().id() !=
71 lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
73 return nav2::CallbackReturn::FAILURE;
76 costmap_thread_ = std::make_unique<nav2::NodeThread>(costmap_ros_);
77 transform_tolerance_ = costmap_ros_->getTransformTolerance();
79 param_handler_ = std::make_unique<ParameterHandler>(
81 }
catch (
const std::exception & ex) {
82 RCLCPP_FATAL(get_logger(),
"%s", ex.what());
84 return nav2::CallbackReturn::FAILURE;
86 params_ = param_handler_->getParams();
88 for (
size_t i = 0; i != params_->progress_checker_ids.size(); i++) {
90 nav2_core::ProgressChecker::Ptr progress_checker =
91 progress_checker_loader_.createUniqueInstance(params_->progress_checker_types[i]);
93 get_logger(),
"Created progress_checker : %s of type %s",
94 params_->progress_checker_ids[i].c_str(), params_->progress_checker_types[i].c_str());
95 progress_checkers_.insert({params_->progress_checker_ids[i], progress_checker});
96 }
catch (
const std::exception & ex) {
99 "Failed to create progress_checker. Exception: %s", ex.what());
101 return nav2::CallbackReturn::FAILURE;
105 for (
size_t i = 0; i != params_->progress_checker_ids.size(); i++) {
106 progress_checker_ids_concat_ += params_->progress_checker_ids[i] + std::string(
" ");
108 if (progress_checker_ids_concat_.empty()) {
109 progress_checker_ids_concat_ =
"(none)";
114 "Controller Server has %s progress checkers available.", progress_checker_ids_concat_.c_str());
116 for (
size_t i = 0; i != params_->goal_checker_ids.size(); i++) {
118 nav2_core::GoalChecker::Ptr goal_checker =
119 goal_checker_loader_.createUniqueInstance(params_->goal_checker_types[i]);
121 get_logger(),
"Created goal checker : %s of type %s",
122 params_->goal_checker_ids[i].c_str(), params_->goal_checker_types[i].c_str());
123 goal_checkers_.insert({params_->goal_checker_ids[i], goal_checker});
124 }
catch (
const pluginlib::PluginlibException & ex) {
127 "Failed to create goal checker. Exception: %s", ex.what());
129 return nav2::CallbackReturn::FAILURE;
133 for (
size_t i = 0; i != params_->goal_checker_ids.size(); i++) {
134 goal_checker_ids_concat_ += params_->goal_checker_ids[i] + std::string(
" ");
139 "Controller Server has %s goal checkers available.", goal_checker_ids_concat_.c_str());
141 for (
size_t i = 0; i != params_->path_handler_ids.size(); i++) {
143 nav2_core::PathHandler::Ptr path_handler =
144 path_handler_loader_.createUniqueInstance(params_->path_handler_types[i]);
146 get_logger(),
"Created path handler : %s of type %s",
147 params_->path_handler_ids[i].c_str(), params_->path_handler_types[i].c_str());
148 path_handlers_.insert({params_->path_handler_ids[i], path_handler});
149 }
catch (
const pluginlib::PluginlibException & ex) {
152 "Failed to create path handler Exception: %s", ex.what());
154 return nav2::CallbackReturn::FAILURE;
158 for (
size_t i = 0; i != params_->path_handler_ids.size(); i++) {
159 path_handler_ids_concat_ += params_->path_handler_ids[i] + std::string(
" ");
164 "Controller Server has %s path handlers available.", path_handler_ids_concat_.c_str());
166 for (
size_t i = 0; i != params_->controller_ids.size(); i++) {
168 nav2_core::Controller::Ptr controller =
169 lp_loader_.createUniqueInstance(params_->controller_types[i]);
171 get_logger(),
"Created controller : %s of type %s",
172 params_->controller_ids[i].c_str(), params_->controller_types[i].c_str());
173 controller->configure(
174 node, params_->controller_ids[i],
175 costmap_ros_->getTfBuffer(), costmap_ros_);
176 controllers_.insert({params_->controller_ids[i], controller});
177 }
catch (
const pluginlib::PluginlibException & ex) {
180 "Failed to create controller. Exception: %s", ex.what());
182 return nav2::CallbackReturn::FAILURE;
186 for (
size_t i = 0; i != params_->controller_ids.size(); i++) {
187 controller_ids_concat_ += params_->controller_ids[i] + std::string(
" ");
192 "Controller Server has %s controllers available.", controller_ids_concat_.c_str());
194 odom_sub_ = std::make_unique<nav2_util::OdomSmoother>(node, params_->odom_duration,
195 params_->odom_topic);
196 vel_publisher_ = std::make_unique<nav2_util::TwistPublisher>(node,
"cmd_vel");
197 transformed_plan_pub_ = create_publisher<nav_msgs::msg::Path>(
"transformed_global_plan");
198 tracking_feedback_pub_ = create_publisher<nav2_msgs::msg::TrackingFeedback>(
"tracking_feedback");
203 action_server_ = create_action_server<Action>(
208 std::chrono::milliseconds(500),
209 true , params_->use_realtime_priority );
210 }
catch (
const std::runtime_error & e) {
211 RCLCPP_ERROR(get_logger(),
"Error creating action server! %s", e.what());
213 return nav2::CallbackReturn::FAILURE;
217 speed_limit_sub_ = create_subscription<nav2_msgs::msg::SpeedLimit>(
218 params_->speed_limit_topic,
219 std::bind(&ControllerServer::speedLimitCallback,
this, std::placeholders::_1));
221 return nav2::CallbackReturn::SUCCESS;
227 RCLCPP_INFO(get_logger(),
"Activating");
229 const auto costmap_ros_state = costmap_ros_->activate();
230 if (costmap_ros_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) {
231 return nav2::CallbackReturn::FAILURE;
233 ControllerMap::iterator it;
234 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
235 it->second->activate();
237 vel_publisher_->on_activate();
238 transformed_plan_pub_->on_activate();
239 tracking_feedback_pub_->on_activate();
240 action_server_->activate();
241 param_handler_->activate();
245 for (
auto & pc : progress_checkers_) {
246 pc.second->initialize(node, pc.first);
248 for (
auto & gc : goal_checkers_) {
249 gc.second->initialize(node, gc.first, costmap_ros_);
251 for (
auto & ph : path_handlers_) {
252 ph.second->initialize(
253 node, get_logger(), ph.first, costmap_ros_,
254 costmap_ros_->getTfBuffer());
260 return nav2::CallbackReturn::SUCCESS;
266 RCLCPP_INFO(get_logger(),
"Deactivating");
268 action_server_->deactivate();
269 ControllerMap::iterator it;
270 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
271 it->second->deactivate();
281 costmap_ros_->deactivate();
284 vel_publisher_->on_deactivate();
285 transformed_plan_pub_->on_deactivate();
286 tracking_feedback_pub_->on_deactivate();
287 param_handler_->deactivate();
292 return nav2::CallbackReturn::SUCCESS;
298 RCLCPP_INFO(get_logger(),
"Cleaning up");
301 ControllerMap::iterator it;
302 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
303 it->second->cleanup();
305 controllers_.clear();
307 goal_checkers_.clear();
308 progress_checkers_.clear();
309 path_handlers_.clear();
311 costmap_ros_->cleanup();
315 action_server_.reset();
317 costmap_thread_.reset();
318 vel_publisher_.reset();
319 transformed_plan_pub_.reset();
320 tracking_feedback_pub_.reset();
321 speed_limit_sub_.reset();
323 return nav2::CallbackReturn::SUCCESS;
329 RCLCPP_INFO(get_logger(),
"Shutting down");
330 return nav2::CallbackReturn::SUCCESS;
334 const std::string & c_name,
335 std::string & current_controller)
337 if (controllers_.find(c_name) == controllers_.end()) {
338 if (controllers_.size() == 1 && c_name.empty()) {
340 get_logger(),
"No controller was specified in action call."
341 " Server will use only plugin loaded %s. "
342 "This warning will appear once.", controller_ids_concat_.c_str());
343 current_controller = controllers_.begin()->first;
346 get_logger(),
"FollowPath called with controller name %s, "
347 "which does not exist. Available controllers are: %s.",
348 c_name.c_str(), controller_ids_concat_.c_str());
352 RCLCPP_DEBUG(get_logger(),
"Selected controller: %s.", c_name.c_str());
353 current_controller = c_name;
360 const std::string & c_name,
361 std::string & current_goal_checker)
363 if (goal_checkers_.find(c_name) == goal_checkers_.end()) {
364 if (goal_checkers_.size() == 1 && c_name.empty()) {
366 get_logger(),
"No goal checker was specified in parameter 'current_goal_checker'."
367 " Server will use only plugin loaded %s. "
368 "This warning will appear once.", goal_checker_ids_concat_.c_str());
369 current_goal_checker = goal_checkers_.begin()->first;
372 get_logger(),
"FollowPath called with goal_checker name %s in parameter"
373 " 'current_goal_checker', which does not exist. Available goal checkers are: %s.",
374 c_name.c_str(), goal_checker_ids_concat_.c_str());
378 RCLCPP_DEBUG(get_logger(),
"Selected goal checker: %s.", c_name.c_str());
379 current_goal_checker = c_name;
386 const std::string & c_name,
387 std::string & current_progress_checker)
389 if (progress_checkers_.size() == 0) {
390 if (c_name.empty()) {
393 "No progress checker configured and none requested. Progress checking will be bypassed.");
394 current_progress_checker =
"";
398 get_logger(),
"FollowPath called with progress_checker name %s in parameter"
399 " 'current_progress_checker', but no progress checkers are configured.",
405 if (progress_checkers_.find(c_name) == progress_checkers_.end()) {
406 if (progress_checkers_.size() == 1 && c_name.empty()) {
408 get_logger(),
"No progress checker was specified in parameter 'current_progress_checker'."
409 " Server will use only plugin loaded %s. "
410 "This warning will appear once.", progress_checker_ids_concat_.c_str());
411 current_progress_checker = progress_checkers_.begin()->first;
414 get_logger(),
"FollowPath called with progress_checker name %s in parameter"
415 " 'current_progress_checker', which does not exist. Available progress checkers are: %s.",
416 c_name.c_str(), progress_checker_ids_concat_.c_str());
420 RCLCPP_DEBUG(get_logger(),
"Selected progress checker: %s.", c_name.c_str());
421 current_progress_checker = c_name;
428 const std::string & c_name,
429 std::string & current_path_handler)
431 if (path_handlers_.find(c_name) == path_handlers_.end()) {
432 if (path_handlers_.size() == 1 && c_name.empty()) {
434 get_logger(),
"No path handler was specified in parameter 'current_path_handler'."
435 " Server will use only plugin loaded %s. "
436 "This warning will appear once.", path_handler_ids_concat_.c_str());
437 current_path_handler = path_handlers_.begin()->first;
440 get_logger(),
"FollowPath called with path_handler name %s in parameter"
441 " 'current_path_handler', which does not exist. Available path handlers are: %s.",
442 c_name.c_str(), path_handler_ids_concat_.c_str());
446 RCLCPP_DEBUG(get_logger(),
"Selected path handler: %s.", c_name.c_str());
447 current_path_handler = c_name;
455 std::string current_controller;
459 "Requested controller %s is not available.", goal->controller_id.c_str());
463 std::string current_goal_checker;
467 "Requested goal checker %s is not available.", goal->goal_checker_id.c_str());
471 std::string current_progress_checker;
475 "Requested progress checker %s is not available.", goal->progress_checker_id.c_str());
479 std::string current_path_handler;
483 "Requested path handler %s is not available.", goal->path_handler_id.c_str());
487 if (goal->path.poses.empty()) {
488 RCLCPP_WARN(get_logger(),
"Requested path to follow is empty.");
497 std::lock_guard<std::mutex> lock_reinit(param_handler_->getMutex());
499 RCLCPP_INFO(get_logger(),
"Received a goal, begin computing control effort.");
502 auto goal = action_server_->get_current_goal();
507 std::string c_name = goal->controller_id;
508 std::string current_controller;
510 current_controller_ = current_controller;
515 std::string gc_name = goal->goal_checker_id;
516 std::string current_goal_checker;
518 current_goal_checker_ = current_goal_checker;
523 std::string pc_name = goal->progress_checker_id;
524 std::string current_progress_checker;
526 current_progress_checker_ = current_progress_checker;
531 std::string ph_name = goal->path_handler_id;
532 std::string current_path_handler;
534 current_path_handler_ = current_path_handler;
540 if (!current_progress_checker_.empty()) {
541 progress_checkers_[current_progress_checker_]->reset();
544 last_valid_cmd_time_ = now();
545 nav2::Rate loop_rate(
this, params_->controller_frequency);
546 while (rclcpp::ok()) {
547 auto start_time = this->now();
549 if (action_server_ ==
nullptr || !action_server_->is_server_active()) {
550 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
554 if (action_server_->is_cancel_requested()) {
555 if (controllers_[current_controller_]->cancel()) {
556 RCLCPP_INFO(get_logger(),
"Cancellation was successful. Stopping the robot.");
557 action_server_->terminate_all();
561 RCLCPP_INFO_THROTTLE(
562 get_logger(), *get_clock(), 1000,
"Waiting for the controller to finish cancellation");
575 RCLCPP_INFO(get_logger(),
"Reached the goal!");
581 auto cycle_duration = this->now() - start_time;
582 if (!loop_rate.sleep()) {
585 "Control loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz."
587 params_->controller_frequency, 1 / cycle_duration.seconds(),
589 (
" Waited " + std::to_string(costmap_wait) +
"s for costmap update.").c_str() :
"");
594 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
596 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
597 result->error_code = Action::Result::INVALID_CONTROLLER;
598 result->error_msg = e.what();
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::TF_ERROR;
606 result->error_msg = e.what();
607 action_server_->terminate_current(result);
610 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
612 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
613 result->error_code = Action::Result::NO_VALID_CONTROL;
614 result->error_msg = e.what();
615 action_server_->terminate_current(result);
618 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
620 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
621 result->error_code = Action::Result::FAILED_TO_MAKE_PROGRESS;
622 result->error_msg = e.what();
623 action_server_->terminate_current(result);
626 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
628 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
629 result->error_code = Action::Result::PATIENCE_EXCEEDED;
630 result->error_msg = e.what();
631 action_server_->terminate_current(result);
634 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
636 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
637 result->error_code = Action::Result::INVALID_PATH;
638 result->error_msg = e.what();
639 action_server_->terminate_current(result);
642 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
644 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
645 result->error_code = Action::Result::CONTROLLER_TIMED_OUT;
646 result->error_msg = e.what();
647 action_server_->terminate_current(result);
650 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
652 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
653 result->error_code = Action::Result::UNKNOWN;
654 result->error_msg = e.what();
655 action_server_->terminate_current(result);
657 }
catch (std::exception & e) {
658 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
660 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
661 result->error_code = Action::Result::UNKNOWN;
662 result->error_msg = e.what();
663 action_server_->terminate_current(result);
667 RCLCPP_DEBUG(get_logger(),
"Controller succeeded, setting result");
672 action_server_->succeeded_current();
677 if (params_->costmap_update_timeout > rclcpp::Duration(0, 0)) {
678 auto waiting_start = now();
679 bool was_waiting = !costmap_ros_->isCurrent();
681 costmap_ros_->waitUntilCurrent(params_->costmap_update_timeout);
682 }
catch (
const std::runtime_error & ex) {
686 return (now() - waiting_start).seconds();
696 "Providing path to the controller %s", current_controller_.c_str());
697 if (path.poses.empty()) {
700 controllers_[current_controller_]->newPathReceived(path);
701 path_handlers_[current_path_handler_]->setPlan(path);
703 end_pose_ = path.poses.back();
704 end_pose_.header.frame_id = path.header.frame_id;
705 goal_checkers_[current_goal_checker_]->reset();
708 get_logger(),
"Path end point is (%.2f, %.2f)",
709 end_pose_.pose.position.x, end_pose_.pose.position.y);
712 current_path_ = path;
717 geometry_msgs::msg::PoseStamped pose;
723 end_pose_.header.stamp = pose.header.stamp;
724 if (!nav2_util::transformPoseInTargetFrame(
725 end_pose_, transformed_end_pose_, *costmap_ros_->getTfBuffer(),
726 costmap_ros_->getGlobalFrameID(), transform_tolerance_))
731 auto [closest_point, pruned_plan_end] =
732 path_handlers_[current_path_handler_]->findPlanSegment(pose);
733 transformed_global_plan_ =
734 path_handlers_[current_path_handler_]->transformLocalPlan(closest_point, pruned_plan_end);
736 auto path = std::make_unique<nav_msgs::msg::Path>(transformed_global_plan_);
737 if (transformed_plan_pub_->get_subscription_count() > 0) {
738 transformed_plan_pub_->publish(std::move(path));
744 geometry_msgs::msg::PoseStamped pose;
750 if (!current_progress_checker_.empty()) {
751 if (!progress_checkers_[current_progress_checker_]->check(pose)) {
758 geometry_msgs::msg::PoseStamped goal =
759 path_handlers_[current_path_handler_]->getTransformedGoal(pose.header.stamp);
761 geometry_msgs::msg::TwistStamped cmd_vel_2d;
765 controllers_[current_controller_]->computeVelocityCommands(
768 goal_checkers_[current_goal_checker_].get(),
769 transformed_global_plan_,
771 last_valid_cmd_time_ = now();
772 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
773 cmd_vel_2d.header.stamp = last_valid_cmd_time_;
777 if (params_->failure_tolerance > 0 || params_->failure_tolerance == -1.0) {
778 RCLCPP_WARN(this->get_logger(),
"%s", e.what());
779 cmd_vel_2d.twist.angular.x = 0;
780 cmd_vel_2d.twist.angular.y = 0;
781 cmd_vel_2d.twist.angular.z = 0;
782 cmd_vel_2d.twist.linear.x = 0;
783 cmd_vel_2d.twist.linear.y = 0;
784 cmd_vel_2d.twist.linear.z = 0;
785 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
786 cmd_vel_2d.header.stamp = now();
787 if ((now() - last_valid_cmd_time_).seconds() > params_->failure_tolerance &&
788 params_->failure_tolerance != -1.0)
797 RCLCPP_DEBUG(get_logger(),
"Publishing velocity at time %.2f", now().seconds());
800 nav2_msgs::msg::TrackingFeedback current_tracking_feedback;
802 if (current_path_.poses.size() >= 2) {
803 double current_distance_to_goal = nav2_util::geometry_utils::euclidean_distance(
804 pose, transformed_end_pose_);
807 geometry_msgs::msg::PoseStamped robot_pose_in_path_frame;
808 if (!nav2_util::transformPoseInTargetFrame(
809 pose, robot_pose_in_path_frame, *costmap_ros_->getTfBuffer(),
810 current_path_.header.frame_id, transform_tolerance_))
816 const auto path_search_result = nav2_util::distance_from_path(
817 current_path_, robot_pose_in_path_frame.pose, start_index_, params_->search_window);
820 double heading_tracking_error = 0.0;
821 if (path_search_result.closest_segment_index <
822 current_path_.poses.size() - 1)
824 const auto & path_segment_start =
825 current_path_.poses[path_search_result.closest_segment_index].pose;
826 const auto & path_segment_end =
827 current_path_.poses[path_search_result.closest_segment_index + 1].pose;
828 double path_yaw = std::atan2(
829 path_segment_end.position.y - path_segment_start.position.y,
830 path_segment_end.position.x - path_segment_start.position.x);
831 double robot_yaw = tf2::getYaw(robot_pose_in_path_frame.pose.orientation);
832 heading_tracking_error = angles::shortest_angular_distance(
833 robot_yaw, path_yaw);
837 auto tracking_feedback_msg = std::make_unique<nav2_msgs::msg::TrackingFeedback>();
838 tracking_feedback_msg->header = pose.header;
839 tracking_feedback_msg->position_tracking_error = path_search_result.distance;
840 tracking_feedback_msg->heading_tracking_error = heading_tracking_error;
841 tracking_feedback_msg->current_path_index = path_search_result.closest_segment_index;
842 tracking_feedback_msg->robot_pose = pose;
843 tracking_feedback_msg->distance_to_goal = current_distance_to_goal;
844 tracking_feedback_msg->speed = std::hypot(twist.linear.x, twist.linear.y);
845 start_index_ = path_search_result.closest_segment_index;
846 tracking_feedback_msg->remaining_path_length =
847 nav2_util::geometry_utils::calculate_path_length(current_path_, start_index_);
850 current_tracking_feedback = *tracking_feedback_msg;
851 if (tracking_feedback_pub_->get_subscription_count() > 0) {
852 tracking_feedback_pub_->publish(std::move(tracking_feedback_msg));
857 std::shared_ptr<Action::Feedback> feedback = std::make_shared<Action::Feedback>();
858 feedback->tracking_feedback = current_tracking_feedback;
859 action_server_->publish_feedback(feedback);
864 if (action_server_->is_preempt_requested()) {
865 RCLCPP_INFO(get_logger(),
"Passing new path to controller.");
866 auto goal = action_server_->accept_pending_goal();
867 std::string current_controller;
869 current_controller_ = current_controller;
871 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
872 result->error_code = Action::Result::INVALID_CONTROLLER;
873 result->error_msg =
"Terminating action, invalid controller " +
874 goal->controller_id +
" requested.";
875 action_server_->terminate_current(result);
878 std::string current_goal_checker;
880 current_goal_checker_ = current_goal_checker;
882 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
883 result->error_code = Action::Result::INVALID_CONTROLLER;
884 result->error_msg =
"Terminating action, invalid goal checker " +
885 goal->goal_checker_id +
" requested.";
886 action_server_->terminate_current(result);
889 std::string current_progress_checker;
891 if (current_progress_checker_ != current_progress_checker) {
893 get_logger(),
"Change of progress checker %s requested, resetting it",
894 goal->progress_checker_id.c_str());
895 current_progress_checker_ = current_progress_checker;
896 if (!current_progress_checker_.empty()) {
897 progress_checkers_[current_progress_checker_]->reset();
901 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
902 result->error_code = Action::Result::INVALID_CONTROLLER;
903 result->error_msg =
"Terminating action, invalid progress checker " +
904 goal->progress_checker_id +
" requested.";
905 action_server_->terminate_current(result);
908 std::string current_path_handler;
910 if (current_path_handler_ != current_path_handler) {
912 get_logger(),
"Change of path handler %s requested, resetting it",
913 goal->path_handler_id.c_str());
914 current_path_handler_ = current_path_handler;
917 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
918 result->error_code = Action::Result::INVALID_CONTROLLER;
919 result->error_msg =
"Terminating action, invalid path handler" +
920 goal->path_handler_id +
" requested.";
921 action_server_->terminate_current(result);
930 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>(velocity);
931 if (!nav2_util::validateTwist(cmd_vel->twist)) {
932 RCLCPP_ERROR(get_logger(),
"Velocity message contains NaNs or Infs! Ignoring as invalid!");
935 if (vel_publisher_->is_activated() && vel_publisher_->get_subscription_count() > 0) {
936 vel_publisher_->publish(std::move(cmd_vel));
942 geometry_msgs::msg::TwistStamped velocity;
943 velocity.twist.angular.x = 0;
944 velocity.twist.angular.y = 0;
945 velocity.twist.angular.z = 0;
946 velocity.twist.linear.x = 0;
947 velocity.twist.linear.y = 0;
948 velocity.twist.linear.z = 0;
949 velocity.header.frame_id = costmap_ros_->getBaseFrameID();
950 velocity.header.stamp = now();
956 if (params_->publish_zero_velocity || force_stop) {
961 for (
auto & controller : controllers_) {
962 controller.second->reset();
968 geometry_msgs::msg::PoseStamped pose;
976 return goal_checkers_[current_goal_checker_]->isGoalReached(
977 pose.pose, transformed_end_pose_.pose,
978 velocity, transformed_global_plan_);
983 geometry_msgs::msg::PoseStamped current_pose;
984 if (!costmap_ros_->getRobotPose(current_pose)) {
991 void ControllerServer::speedLimitCallback(
const nav2_msgs::msg::SpeedLimit::ConstSharedPtr & msg)
993 ControllerMap::iterator it;
994 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
995 it->second->setSpeedLimit(msg->speed_limit, msg->percentage);
1001 #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.
A sim-time-aware rate for Nav2 loops.
This class hosts variety of plugins of different algorithms to complete control tasks from the expose...
nav2::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &state) override
Calls clean up states and resets member variables.
double waitForCostmap()
Wait for costmap to become current, with timeout.
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 in costmap's frame.
void onGoalExit(bool force_stop)
Called on goal exit.
nav2::CallbackReturn on_configure(const rclcpp_lifecycle::State &state) override
Configures controller parameters and member variables.
void computeControl()
FollowPath action server callback. Handles action server updates and spins server until goal is reach...
bool isGoalReached()
Checks if goal is reached.
geometry_msgs::msg::Twist getThresholdedTwist(const geometry_msgs::msg::Twist &twist)
get the thresholded Twist
~ControllerServer()
Destructor for nav2_controller::ControllerServer.
nav2::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &state) override
Deactivates member variables.
bool findGoalCheckerId(const std::string &c_name, std::string &name)
Find the valid goal checker ID name for the specified parameter.
void updateGlobalPath()
Calls setPlannerPath method with an updated path received from action server.
bool goalReceived(std::shared_ptr< const Action::Goal > goal)
Goal received callback to validate a new goal before acceptance.
void setPlannerPath(const nav_msgs::msg::Path &path)
Assigns path to controller.
void transformedPlanAndGoal()
Refreshes transformed_global_plan_ and transformed_end_pose_ for the current cycle.
nav2::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &state) override
Called when in Shutdown state.
nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
Activates member variables.
void publishZeroVelocity()
Calls velocity publisher to publish zero velocity.
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.
bool findPathHandlerId(const std::string &c_name, std::string &name)
Find the valid path handler ID name for the specified parameter.
void computeAndPublishVelocity()
Calculates velocity and publishes to "cmd_vel" topic.