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_util/robot_utils.hpp"
29 #include "nav2_controller/controller_server.hpp"
31 using namespace std::chrono_literals;
32 using rcl_interfaces::msg::ParameterType;
33 using std::placeholders::_1;
34 using nav2_util::geometry_utils::euclidean_distance;
36 namespace nav2_controller
39 ControllerServer::ControllerServer(
const rclcpp::NodeOptions & options)
40 : nav2::LifecycleNode(
"controller_server",
"", options),
41 progress_checker_loader_(
"nav2_core",
"nav2_core::ProgressChecker"),
42 goal_checker_loader_(
"nav2_core",
"nav2_core::GoalChecker"),
43 lp_loader_(
"nav2_core",
"nav2_core::Controller"),
44 path_handler_loader_(
"nav2_core",
"nav2_core::PathHandler"),
47 RCLCPP_INFO(get_logger(),
"Creating controller server");
50 costmap_ros_ = std::make_shared<nav2_costmap_2d::Costmap2DROS>(
51 "local_costmap", std::string{get_namespace()},
52 get_parameter(
"use_sim_time").as_bool(), options);
57 progress_checkers_.clear();
58 goal_checkers_.clear();
60 path_handlers_.clear();
61 costmap_thread_.reset();
69 RCLCPP_INFO(get_logger(),
"Configuring controller interface");
71 if (costmap_ros_->configure().id() !=
72 lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
74 return nav2::CallbackReturn::FAILURE;
77 costmap_thread_ = std::make_unique<nav2::NodeThread>(costmap_ros_);
78 transform_tolerance_ = costmap_ros_->getTransformTolerance();
80 param_handler_ = std::make_unique<ParameterHandler>(
82 }
catch (
const std::exception & ex) {
83 RCLCPP_FATAL(get_logger(),
"%s", ex.what());
85 return nav2::CallbackReturn::FAILURE;
87 params_ = param_handler_->getParams();
89 for (
size_t i = 0; i != params_->progress_checker_ids.size(); i++) {
91 nav2_core::ProgressChecker::Ptr progress_checker =
92 progress_checker_loader_.createUniqueInstance(params_->progress_checker_types[i]);
94 get_logger(),
"Created progress_checker : %s of type %s",
95 params_->progress_checker_ids[i].c_str(), params_->progress_checker_types[i].c_str());
96 progress_checkers_.insert({params_->progress_checker_ids[i], progress_checker});
97 }
catch (
const std::exception & ex) {
100 "Failed to create progress_checker. Exception: %s", ex.what());
102 return nav2::CallbackReturn::FAILURE;
106 for (
size_t i = 0; i != params_->progress_checker_ids.size(); i++) {
107 progress_checker_ids_concat_ += params_->progress_checker_ids[i] + std::string(
" ");
109 if (progress_checker_ids_concat_.empty()) {
110 progress_checker_ids_concat_ =
"(none)";
115 "Controller Server has %s progress checkers available.", progress_checker_ids_concat_.c_str());
117 for (
size_t i = 0; i != params_->goal_checker_ids.size(); i++) {
119 nav2_core::GoalChecker::Ptr goal_checker =
120 goal_checker_loader_.createUniqueInstance(params_->goal_checker_types[i]);
122 get_logger(),
"Created goal checker : %s of type %s",
123 params_->goal_checker_ids[i].c_str(), params_->goal_checker_types[i].c_str());
124 goal_checkers_.insert({params_->goal_checker_ids[i], goal_checker});
125 }
catch (
const pluginlib::PluginlibException & ex) {
128 "Failed to create goal checker. Exception: %s", ex.what());
130 return nav2::CallbackReturn::FAILURE;
134 for (
size_t i = 0; i != params_->goal_checker_ids.size(); i++) {
135 goal_checker_ids_concat_ += params_->goal_checker_ids[i] + std::string(
" ");
140 "Controller Server has %s goal checkers available.", goal_checker_ids_concat_.c_str());
142 for (
size_t i = 0; i != params_->path_handler_ids.size(); i++) {
144 nav2_core::PathHandler::Ptr path_handler =
145 path_handler_loader_.createUniqueInstance(params_->path_handler_types[i]);
147 get_logger(),
"Created path handler : %s of type %s",
148 params_->path_handler_ids[i].c_str(), params_->path_handler_types[i].c_str());
149 path_handlers_.insert({params_->path_handler_ids[i], path_handler});
150 }
catch (
const pluginlib::PluginlibException & ex) {
153 "Failed to create path handler Exception: %s", ex.what());
155 return nav2::CallbackReturn::FAILURE;
159 for (
size_t i = 0; i != params_->path_handler_ids.size(); i++) {
160 path_handler_ids_concat_ += params_->path_handler_ids[i] + std::string(
" ");
165 "Controller Server has %s path handlers available.", path_handler_ids_concat_.c_str());
167 for (
size_t i = 0; i != params_->controller_ids.size(); i++) {
169 nav2_core::Controller::Ptr controller =
170 lp_loader_.createUniqueInstance(params_->controller_types[i]);
172 get_logger(),
"Created controller : %s of type %s",
173 params_->controller_ids[i].c_str(), params_->controller_types[i].c_str());
174 controller->configure(
175 node, params_->controller_ids[i],
176 costmap_ros_->getTfBuffer(), costmap_ros_);
177 controllers_.insert({params_->controller_ids[i], controller});
178 }
catch (
const pluginlib::PluginlibException & ex) {
181 "Failed to create controller. Exception: %s", ex.what());
183 return nav2::CallbackReturn::FAILURE;
187 for (
size_t i = 0; i != params_->controller_ids.size(); i++) {
188 controller_ids_concat_ += params_->controller_ids[i] + std::string(
" ");
193 "Controller Server has %s controllers available.", controller_ids_concat_.c_str());
195 odom_sub_ = std::make_unique<nav2_util::OdomSmoother>(node, params_->odom_duration,
196 params_->odom_topic);
197 vel_publisher_ = std::make_unique<nav2_util::TwistPublisher>(node,
"cmd_vel");
198 transformed_plan_pub_ = create_publisher<nav_msgs::msg::Path>(
"transformed_global_plan");
199 tracking_feedback_pub_ = create_publisher<nav2_msgs::msg::TrackingFeedback>(
"tracking_feedback");
204 action_server_ = create_action_server<Action>(
209 std::chrono::milliseconds(500),
210 true , params_->use_realtime_priority );
211 }
catch (
const std::runtime_error & e) {
212 RCLCPP_ERROR(get_logger(),
"Error creating action server! %s", e.what());
214 return nav2::CallbackReturn::FAILURE;
218 speed_limit_sub_ = create_subscription<nav2_msgs::msg::SpeedLimit>(
219 params_->speed_limit_topic,
220 std::bind(&ControllerServer::speedLimitCallback,
this, std::placeholders::_1));
222 return nav2::CallbackReturn::SUCCESS;
228 RCLCPP_INFO(get_logger(),
"Activating");
230 const auto costmap_ros_state = costmap_ros_->activate();
231 if (costmap_ros_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) {
232 return nav2::CallbackReturn::FAILURE;
234 ControllerMap::iterator it;
235 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
236 it->second->activate();
238 vel_publisher_->on_activate();
239 transformed_plan_pub_->on_activate();
240 tracking_feedback_pub_->on_activate();
241 action_server_->activate();
242 param_handler_->activate();
246 for (
auto & pc : progress_checkers_) {
247 pc.second->initialize(node, pc.first);
249 for (
auto & gc : goal_checkers_) {
250 gc.second->initialize(node, gc.first, costmap_ros_);
252 for (
auto & ph : path_handlers_) {
253 ph.second->initialize(
254 node, get_logger(), ph.first, costmap_ros_,
255 costmap_ros_->getTfBuffer());
261 return nav2::CallbackReturn::SUCCESS;
267 RCLCPP_INFO(get_logger(),
"Deactivating");
269 action_server_->deactivate();
270 ControllerMap::iterator it;
271 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
272 it->second->deactivate();
282 costmap_ros_->deactivate();
285 vel_publisher_->on_deactivate();
286 transformed_plan_pub_->on_deactivate();
287 tracking_feedback_pub_->on_deactivate();
288 param_handler_->deactivate();
293 return nav2::CallbackReturn::SUCCESS;
299 RCLCPP_INFO(get_logger(),
"Cleaning up");
302 ControllerMap::iterator it;
303 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
304 it->second->cleanup();
306 controllers_.clear();
308 goal_checkers_.clear();
309 progress_checkers_.clear();
310 path_handlers_.clear();
312 costmap_ros_->cleanup();
316 action_server_.reset();
318 costmap_thread_.reset();
319 vel_publisher_.reset();
320 transformed_plan_pub_.reset();
321 tracking_feedback_pub_.reset();
322 speed_limit_sub_.reset();
324 return nav2::CallbackReturn::SUCCESS;
330 RCLCPP_INFO(get_logger(),
"Shutting down");
331 return nav2::CallbackReturn::SUCCESS;
335 const std::string & c_name,
336 std::string & current_controller)
338 if (controllers_.find(c_name) == controllers_.end()) {
339 if (controllers_.size() == 1 && c_name.empty()) {
341 get_logger(),
"No controller was specified in action call."
342 " Server will use only plugin loaded %s. "
343 "This warning will appear once.", controller_ids_concat_.c_str());
344 current_controller = controllers_.begin()->first;
347 get_logger(),
"FollowPath called with controller name %s, "
348 "which does not exist. Available controllers are: %s.",
349 c_name.c_str(), controller_ids_concat_.c_str());
353 RCLCPP_DEBUG(get_logger(),
"Selected controller: %s.", c_name.c_str());
354 current_controller = c_name;
361 const std::string & c_name,
362 std::string & current_goal_checker)
364 if (goal_checkers_.find(c_name) == goal_checkers_.end()) {
365 if (goal_checkers_.size() == 1 && c_name.empty()) {
367 get_logger(),
"No goal checker was specified in parameter 'current_goal_checker'."
368 " Server will use only plugin loaded %s. "
369 "This warning will appear once.", goal_checker_ids_concat_.c_str());
370 current_goal_checker = goal_checkers_.begin()->first;
373 get_logger(),
"FollowPath called with goal_checker name %s in parameter"
374 " 'current_goal_checker', which does not exist. Available goal checkers are: %s.",
375 c_name.c_str(), goal_checker_ids_concat_.c_str());
379 RCLCPP_DEBUG(get_logger(),
"Selected goal checker: %s.", c_name.c_str());
380 current_goal_checker = c_name;
387 const std::string & c_name,
388 std::string & current_progress_checker)
390 if (progress_checkers_.size() == 0) {
391 if (c_name.empty()) {
394 "No progress checker configured and none requested. Progress checking will be bypassed.");
395 current_progress_checker =
"";
399 get_logger(),
"FollowPath called with progress_checker name %s in parameter"
400 " 'current_progress_checker', but no progress checkers are configured.",
406 if (progress_checkers_.find(c_name) == progress_checkers_.end()) {
407 if (progress_checkers_.size() == 1 && c_name.empty()) {
409 get_logger(),
"No progress checker was specified in parameter 'current_progress_checker'."
410 " Server will use only plugin loaded %s. "
411 "This warning will appear once.", progress_checker_ids_concat_.c_str());
412 current_progress_checker = progress_checkers_.begin()->first;
415 get_logger(),
"FollowPath called with progress_checker name %s in parameter"
416 " 'current_progress_checker', which does not exist. Available progress checkers are: %s.",
417 c_name.c_str(), progress_checker_ids_concat_.c_str());
421 RCLCPP_DEBUG(get_logger(),
"Selected progress checker: %s.", c_name.c_str());
422 current_progress_checker = c_name;
429 const std::string & c_name,
430 std::string & current_path_handler)
432 if (path_handlers_.find(c_name) == path_handlers_.end()) {
433 if (path_handlers_.size() == 1 && c_name.empty()) {
435 get_logger(),
"No path handler was specified in parameter 'current_path_handler'."
436 " Server will use only plugin loaded %s. "
437 "This warning will appear once.", path_handler_ids_concat_.c_str());
438 current_path_handler = path_handlers_.begin()->first;
441 get_logger(),
"FollowPath called with path_handler name %s in parameter"
442 " 'current_path_handler', which does not exist. Available path handlers are: %s.",
443 c_name.c_str(), path_handler_ids_concat_.c_str());
447 RCLCPP_DEBUG(get_logger(),
"Selected path handler: %s.", c_name.c_str());
448 current_path_handler = c_name;
456 std::string current_controller;
460 "Requested controller %s is not available.", goal->controller_id.c_str());
464 std::string current_goal_checker;
468 "Requested goal checker %s is not available.", goal->goal_checker_id.c_str());
472 std::string current_progress_checker;
476 "Requested progress checker %s is not available.", goal->progress_checker_id.c_str());
480 std::string current_path_handler;
484 "Requested path handler %s is not available.", goal->path_handler_id.c_str());
488 if (goal->path.poses.empty()) {
489 RCLCPP_WARN(get_logger(),
"Requested path to follow is empty.");
498 std::lock_guard<std::mutex> lock_reinit(param_handler_->getMutex());
500 RCLCPP_INFO(get_logger(),
"Received a goal, begin computing control effort.");
503 auto goal = action_server_->get_current_goal();
508 std::string c_name = goal->controller_id;
509 std::string current_controller;
511 current_controller_ = current_controller;
516 std::string gc_name = goal->goal_checker_id;
517 std::string current_goal_checker;
519 current_goal_checker_ = current_goal_checker;
524 std::string pc_name = goal->progress_checker_id;
525 std::string current_progress_checker;
527 current_progress_checker_ = current_progress_checker;
532 std::string ph_name = goal->path_handler_id;
533 std::string current_path_handler;
535 current_path_handler_ = current_path_handler;
541 if (!current_progress_checker_.empty()) {
542 progress_checkers_[current_progress_checker_]->reset();
545 last_valid_cmd_time_ = now();
546 nav2::Rate loop_rate(
this, params_->controller_frequency);
547 while (rclcpp::ok()) {
548 auto start_time = this->now();
550 if (action_server_ ==
nullptr || !action_server_->is_server_active()) {
551 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
555 if (action_server_->is_cancel_requested()) {
556 if (controllers_[current_controller_]->cancel()) {
557 RCLCPP_INFO(get_logger(),
"Cancellation was successful. Stopping the robot.");
558 action_server_->terminate_all();
562 RCLCPP_INFO_THROTTLE(
563 get_logger(), *get_clock(), 1000,
"Waiting for the controller to finish cancellation");
580 RCLCPP_INFO(get_logger(),
"Reached the goal!");
586 auto cycle_duration = this->now() - start_time;
587 if (!loop_rate.sleep()) {
590 "Control loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz."
592 params_->controller_frequency, 1 / cycle_duration.seconds(),
594 (
" Waited " + std::to_string(costmap_wait) +
"s for costmap update.").c_str() :
"");
599 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
601 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
602 result->error_code = Action::Result::INVALID_CONTROLLER;
603 result->error_msg = e.what();
604 action_server_->terminate_current(result);
607 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
609 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
610 result->error_code = Action::Result::TF_ERROR;
611 result->error_msg = e.what();
612 action_server_->terminate_current(result);
615 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
617 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
618 result->error_code = Action::Result::NO_VALID_CONTROL;
619 result->error_msg = e.what();
620 action_server_->terminate_current(result);
623 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
625 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
626 result->error_code = Action::Result::FAILED_TO_MAKE_PROGRESS;
627 result->error_msg = e.what();
628 action_server_->terminate_current(result);
631 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
633 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
634 result->error_code = Action::Result::PATIENCE_EXCEEDED;
635 result->error_msg = e.what();
636 action_server_->terminate_current(result);
639 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
641 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
642 result->error_code = Action::Result::INVALID_PATH;
643 result->error_msg = e.what();
644 action_server_->terminate_current(result);
647 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
649 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
650 result->error_code = Action::Result::CONTROLLER_TIMED_OUT;
651 result->error_msg = e.what();
652 action_server_->terminate_current(result);
655 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
657 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
658 result->error_code = Action::Result::UNKNOWN;
659 result->error_msg = e.what();
660 action_server_->terminate_current(result);
662 }
catch (std::exception & e) {
663 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
665 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
666 result->error_code = Action::Result::UNKNOWN;
667 result->error_msg = e.what();
668 action_server_->terminate_current(result);
672 RCLCPP_DEBUG(get_logger(),
"Controller succeeded, setting result");
677 action_server_->succeeded_current();
682 if (params_->costmap_update_timeout > rclcpp::Duration(0, 0)) {
683 auto waiting_start = now();
684 bool was_waiting = !costmap_ros_->isCurrent();
686 costmap_ros_->waitUntilCurrent(params_->costmap_update_timeout);
687 }
catch (
const std::runtime_error & ex) {
691 return (now() - waiting_start).seconds();
701 "Providing path to the controller %s", current_controller_.c_str());
702 if (path.poses.empty()) {
705 controllers_[current_controller_]->newPathReceived(path);
706 path_handlers_[current_path_handler_]->setPlan(path);
708 end_pose_ = path.poses.back();
709 end_pose_.header.frame_id = path.header.frame_id;
710 goal_checkers_[current_goal_checker_]->reset();
713 get_logger(),
"Path end point is (%.2f, %.2f)",
714 end_pose_.pose.position.x, end_pose_.pose.position.y);
717 current_path_ = path;
721 const geometry_msgs::msg::PoseStamped & current_robot_pose)
723 end_pose_.header.stamp = current_robot_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(current_robot_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));
743 const geometry_msgs::msg::PoseStamped & current_robot_pose)
745 if (!current_progress_checker_.empty()) {
746 if (!progress_checkers_[current_progress_checker_]->check(current_robot_pose)) {
753 geometry_msgs::msg::PoseStamped goal =
754 path_handlers_[current_path_handler_]->getTransformedGoal(current_robot_pose.header.stamp);
756 geometry_msgs::msg::TwistStamped cmd_vel_2d;
760 controllers_[current_controller_]->computeVelocityCommands(
763 goal_checkers_[current_goal_checker_].get(),
764 transformed_global_plan_,
766 last_valid_cmd_time_ = now();
767 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
768 cmd_vel_2d.header.stamp = last_valid_cmd_time_;
772 if (params_->failure_tolerance > 0 || params_->failure_tolerance == -1.0) {
773 RCLCPP_WARN(this->get_logger(),
"%s", e.what());
774 cmd_vel_2d.twist.angular.x = 0;
775 cmd_vel_2d.twist.angular.y = 0;
776 cmd_vel_2d.twist.angular.z = 0;
777 cmd_vel_2d.twist.linear.x = 0;
778 cmd_vel_2d.twist.linear.y = 0;
779 cmd_vel_2d.twist.linear.z = 0;
780 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
781 cmd_vel_2d.header.stamp = now();
782 if ((now() - last_valid_cmd_time_).seconds() > params_->failure_tolerance &&
783 params_->failure_tolerance != -1.0)
792 RCLCPP_DEBUG(get_logger(),
"Publishing velocity at time %.2f", now().seconds());
795 nav2_msgs::msg::TrackingFeedback current_tracking_feedback;
797 if (current_path_.poses.size() >= 2) {
798 double current_distance_to_goal = nav2_util::geometry_utils::euclidean_distance(
799 current_robot_pose, transformed_end_pose_);
802 geometry_msgs::msg::PoseStamped robot_pose_in_path_frame;
803 if (!nav2_util::transformPoseInTargetFrame(
804 current_robot_pose, robot_pose_in_path_frame, *costmap_ros_->getTfBuffer(),
805 current_path_.header.frame_id, transform_tolerance_))
811 const auto path_search_result = nav2_util::distance_from_path(
812 current_path_, robot_pose_in_path_frame.pose, start_index_, params_->search_window);
815 double heading_tracking_error = 0.0;
816 if (path_search_result.closest_segment_index <
817 current_path_.poses.size() - 1)
819 const auto & path_segment_start =
820 current_path_.poses[path_search_result.closest_segment_index].pose;
821 const auto & path_segment_end =
822 current_path_.poses[path_search_result.closest_segment_index + 1].pose;
823 double path_yaw = std::atan2(
824 path_segment_end.position.y - path_segment_start.position.y,
825 path_segment_end.position.x - path_segment_start.position.x);
826 double robot_yaw = tf2::getYaw(robot_pose_in_path_frame.pose.orientation);
827 heading_tracking_error = angles::shortest_angular_distance(
828 robot_yaw, path_yaw);
832 auto tracking_feedback_msg = std::make_unique<nav2_msgs::msg::TrackingFeedback>();
833 tracking_feedback_msg->header = current_robot_pose.header;
834 tracking_feedback_msg->position_tracking_error = path_search_result.distance;
835 tracking_feedback_msg->heading_tracking_error = heading_tracking_error;
836 tracking_feedback_msg->current_path_index = path_search_result.closest_segment_index;
837 tracking_feedback_msg->robot_pose = current_robot_pose;
838 tracking_feedback_msg->distance_to_goal = current_distance_to_goal;
839 tracking_feedback_msg->speed = std::hypot(twist.linear.x, twist.linear.y);
840 start_index_ = path_search_result.closest_segment_index;
841 tracking_feedback_msg->remaining_path_length =
842 nav2_util::geometry_utils::calculate_path_length(current_path_, start_index_);
845 current_tracking_feedback = *tracking_feedback_msg;
846 if (tracking_feedback_pub_->get_subscription_count() > 0) {
847 tracking_feedback_pub_->publish(std::move(tracking_feedback_msg));
852 std::shared_ptr<Action::Feedback> feedback = std::make_shared<Action::Feedback>();
853 feedback->tracking_feedback = current_tracking_feedback;
854 action_server_->publish_feedback(feedback);
859 if (action_server_->is_preempt_requested()) {
860 RCLCPP_INFO(get_logger(),
"Passing new path to controller.");
861 auto goal = action_server_->accept_pending_goal();
862 std::string current_controller;
864 current_controller_ = current_controller;
866 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
867 result->error_code = Action::Result::INVALID_CONTROLLER;
868 result->error_msg =
"Terminating action, invalid controller " +
869 goal->controller_id +
" requested.";
870 action_server_->terminate_current(result);
873 std::string current_goal_checker;
875 current_goal_checker_ = current_goal_checker;
877 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
878 result->error_code = Action::Result::INVALID_CONTROLLER;
879 result->error_msg =
"Terminating action, invalid goal checker " +
880 goal->goal_checker_id +
" requested.";
881 action_server_->terminate_current(result);
884 std::string current_progress_checker;
886 if (current_progress_checker_ != current_progress_checker) {
888 get_logger(),
"Change of progress checker %s requested, resetting it",
889 goal->progress_checker_id.c_str());
890 current_progress_checker_ = current_progress_checker;
891 if (!current_progress_checker_.empty()) {
892 progress_checkers_[current_progress_checker_]->reset();
896 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
897 result->error_code = Action::Result::INVALID_CONTROLLER;
898 result->error_msg =
"Terminating action, invalid progress checker " +
899 goal->progress_checker_id +
" requested.";
900 action_server_->terminate_current(result);
903 std::string current_path_handler;
905 if (current_path_handler_ != current_path_handler) {
907 get_logger(),
"Change of path handler %s requested, resetting it",
908 goal->path_handler_id.c_str());
909 current_path_handler_ = current_path_handler;
912 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
913 result->error_code = Action::Result::INVALID_CONTROLLER;
914 result->error_msg =
"Terminating action, invalid path handler" +
915 goal->path_handler_id +
" requested.";
916 action_server_->terminate_current(result);
925 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>(velocity);
926 if (!nav2_util::validateTwist(cmd_vel->twist)) {
927 RCLCPP_ERROR(get_logger(),
"Velocity message contains NaNs or Infs! Ignoring as invalid!");
930 if (vel_publisher_->is_activated() && vel_publisher_->get_subscription_count() > 0) {
931 vel_publisher_->publish(std::move(cmd_vel));
937 geometry_msgs::msg::TwistStamped velocity;
938 velocity.twist.angular.x = 0;
939 velocity.twist.angular.y = 0;
940 velocity.twist.angular.z = 0;
941 velocity.twist.linear.x = 0;
942 velocity.twist.linear.y = 0;
943 velocity.twist.linear.z = 0;
944 velocity.header.frame_id = costmap_ros_->getBaseFrameID();
945 velocity.header.stamp = now();
951 if (params_->publish_zero_velocity || force_stop) {
956 for (
auto & controller : controllers_) {
957 controller.second->reset();
965 return goal_checkers_[current_goal_checker_]->isGoalReached(
966 current_robot_pose.pose, transformed_end_pose_.pose,
967 velocity, transformed_global_plan_);
972 geometry_msgs::msg::PoseStamped pose;
973 if (!nav2_util::getFreshPose(
974 *costmap_ros_->getTfBuffer(), costmap_ros_->getGlobalFrameID(),
975 costmap_ros_->getBaseFrameID(), now(),
976 params_->transform_staleness_threshold, pose))
979 "Failed to obtain robot pose in frame '" + costmap_ros_->getGlobalFrameID() +
980 "' for base frame '" + costmap_ros_->getBaseFrameID() +
"'");
985 void ControllerServer::speedLimitCallback(
const nav2_msgs::msg::SpeedLimit::ConstSharedPtr & msg)
987 ControllerMap::iterator it;
988 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
989 it->second->setSpeedLimit(msg->speed_limit, msg->percentage);
995 #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.
bool isGoalReached(const geometry_msgs::msg::PoseStamped ¤t_robot_pose)
Checks if goal is reached.
void publishVelocity(const geometry_msgs::msg::TwistStamped &velocity)
Calls velocity publisher to publish the velocity on "cmd_vel" topic.
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...
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.
nav2::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &state) override
Called when in Shutdown state.
void transformedPlanAndGoal(const geometry_msgs::msg::PoseStamped ¤t_robot_pose)
Refreshes transformed_global_plan_ and transformed_end_pose_ for the current cycle.
nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
Activates member variables.
void publishZeroVelocity()
Calls velocity publisher to publish zero velocity.
geometry_msgs::msg::PoseStamped getCurrentRobotPose()
Obtain the current pose of the robot in the costmap frame.
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(const geometry_msgs::msg::PoseStamped ¤t_robot_pose)
Calculates velocity and publishes to "cmd_vel" topic.