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 costmap_ros_->configure();
72 costmap_thread_ = std::make_unique<nav2::NodeThread>(costmap_ros_);
73 transform_tolerance_ = costmap_ros_->getTransformTolerance();
75 param_handler_ = std::make_unique<ParameterHandler>(
77 }
catch (
const std::exception & ex) {
78 RCLCPP_FATAL(get_logger(),
"%s", ex.what());
80 return nav2::CallbackReturn::FAILURE;
82 params_ = param_handler_->getParams();
84 for (
size_t i = 0; i != params_->progress_checker_ids.size(); i++) {
86 nav2_core::ProgressChecker::Ptr progress_checker =
87 progress_checker_loader_.createUniqueInstance(params_->progress_checker_types[i]);
89 get_logger(),
"Created progress_checker : %s of type %s",
90 params_->progress_checker_ids[i].c_str(), params_->progress_checker_types[i].c_str());
91 progress_checkers_.insert({params_->progress_checker_ids[i], progress_checker});
92 }
catch (
const std::exception & ex) {
95 "Failed to create progress_checker. Exception: %s", ex.what());
97 return nav2::CallbackReturn::FAILURE;
101 for (
size_t i = 0; i != params_->progress_checker_ids.size(); i++) {
102 progress_checker_ids_concat_ += params_->progress_checker_ids[i] + std::string(
" ");
104 if (progress_checker_ids_concat_.empty()) {
105 progress_checker_ids_concat_ =
"(none)";
110 "Controller Server has %s progress checkers available.", progress_checker_ids_concat_.c_str());
112 for (
size_t i = 0; i != params_->goal_checker_ids.size(); i++) {
114 nav2_core::GoalChecker::Ptr goal_checker =
115 goal_checker_loader_.createUniqueInstance(params_->goal_checker_types[i]);
117 get_logger(),
"Created goal checker : %s of type %s",
118 params_->goal_checker_ids[i].c_str(), params_->goal_checker_types[i].c_str());
119 goal_checkers_.insert({params_->goal_checker_ids[i], goal_checker});
120 }
catch (
const pluginlib::PluginlibException & ex) {
123 "Failed to create goal checker. Exception: %s", ex.what());
125 return nav2::CallbackReturn::FAILURE;
129 for (
size_t i = 0; i != params_->goal_checker_ids.size(); i++) {
130 goal_checker_ids_concat_ += params_->goal_checker_ids[i] + std::string(
" ");
135 "Controller Server has %s goal checkers available.", goal_checker_ids_concat_.c_str());
137 for (
size_t i = 0; i != params_->path_handler_ids.size(); i++) {
139 nav2_core::PathHandler::Ptr path_handler =
140 path_handler_loader_.createUniqueInstance(params_->path_handler_types[i]);
142 get_logger(),
"Created path handler : %s of type %s",
143 params_->path_handler_ids[i].c_str(), params_->path_handler_types[i].c_str());
144 path_handlers_.insert({params_->path_handler_ids[i], path_handler});
145 }
catch (
const pluginlib::PluginlibException & ex) {
148 "Failed to create path handler Exception: %s", ex.what());
150 return nav2::CallbackReturn::FAILURE;
154 for (
size_t i = 0; i != params_->path_handler_ids.size(); i++) {
155 path_handler_ids_concat_ += params_->path_handler_ids[i] + std::string(
" ");
160 "Controller Server has %s path handlers available.", path_handler_ids_concat_.c_str());
162 for (
size_t i = 0; i != params_->controller_ids.size(); i++) {
164 nav2_core::Controller::Ptr controller =
165 lp_loader_.createUniqueInstance(params_->controller_types[i]);
167 get_logger(),
"Created controller : %s of type %s",
168 params_->controller_ids[i].c_str(), params_->controller_types[i].c_str());
169 controller->configure(
170 node, params_->controller_ids[i],
171 costmap_ros_->getTfBuffer(), costmap_ros_);
172 controllers_.insert({params_->controller_ids[i], controller});
173 }
catch (
const pluginlib::PluginlibException & ex) {
176 "Failed to create controller. Exception: %s", ex.what());
178 return nav2::CallbackReturn::FAILURE;
182 for (
size_t i = 0; i != params_->controller_ids.size(); i++) {
183 controller_ids_concat_ += params_->controller_ids[i] + std::string(
" ");
188 "Controller Server has %s controllers available.", controller_ids_concat_.c_str());
190 odom_sub_ = std::make_unique<nav2_util::OdomSmoother>(node, params_->odom_duration,
191 params_->odom_topic);
192 vel_publisher_ = std::make_unique<nav2_util::TwistPublisher>(node,
"cmd_vel");
193 transformed_plan_pub_ = create_publisher<nav_msgs::msg::Path>(
"transformed_global_plan");
194 tracking_feedback_pub_ = create_publisher<nav2_msgs::msg::TrackingFeedback>(
"tracking_feedback");
199 action_server_ = create_action_server<Action>(
204 std::chrono::milliseconds(500),
205 true , params_->use_realtime_priority );
206 }
catch (
const std::runtime_error & e) {
207 RCLCPP_ERROR(get_logger(),
"Error creating action server! %s", e.what());
209 return nav2::CallbackReturn::FAILURE;
213 speed_limit_sub_ = create_subscription<nav2_msgs::msg::SpeedLimit>(
214 params_->speed_limit_topic,
215 std::bind(&ControllerServer::speedLimitCallback,
this, std::placeholders::_1));
217 return nav2::CallbackReturn::SUCCESS;
223 RCLCPP_INFO(get_logger(),
"Activating");
225 const auto costmap_ros_state = costmap_ros_->activate();
226 if (costmap_ros_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) {
227 return nav2::CallbackReturn::FAILURE;
229 ControllerMap::iterator it;
230 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
231 it->second->activate();
233 vel_publisher_->on_activate();
234 transformed_plan_pub_->on_activate();
235 tracking_feedback_pub_->on_activate();
236 action_server_->activate();
237 param_handler_->activate();
241 for (
auto & pc : progress_checkers_) {
242 pc.second->initialize(node, pc.first);
244 for (
auto & gc : goal_checkers_) {
245 gc.second->initialize(node, gc.first, costmap_ros_);
247 for (
auto & ph : path_handlers_) {
248 ph.second->initialize(
249 node, get_logger(), ph.first, costmap_ros_,
250 costmap_ros_->getTfBuffer());
256 return nav2::CallbackReturn::SUCCESS;
262 RCLCPP_INFO(get_logger(),
"Deactivating");
264 action_server_->deactivate();
265 ControllerMap::iterator it;
266 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
267 it->second->deactivate();
277 costmap_ros_->deactivate();
280 vel_publisher_->on_deactivate();
281 transformed_plan_pub_->on_deactivate();
282 tracking_feedback_pub_->on_deactivate();
283 param_handler_->deactivate();
288 return nav2::CallbackReturn::SUCCESS;
294 RCLCPP_INFO(get_logger(),
"Cleaning up");
297 ControllerMap::iterator it;
298 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
299 it->second->cleanup();
301 controllers_.clear();
303 goal_checkers_.clear();
304 progress_checkers_.clear();
305 path_handlers_.clear();
307 costmap_ros_->cleanup();
311 action_server_.reset();
313 costmap_thread_.reset();
314 vel_publisher_.reset();
315 transformed_plan_pub_.reset();
316 tracking_feedback_pub_.reset();
317 speed_limit_sub_.reset();
319 return nav2::CallbackReturn::SUCCESS;
325 RCLCPP_INFO(get_logger(),
"Shutting down");
326 return nav2::CallbackReturn::SUCCESS;
330 const std::string & c_name,
331 std::string & current_controller)
333 if (controllers_.find(c_name) == controllers_.end()) {
334 if (controllers_.size() == 1 && c_name.empty()) {
336 get_logger(),
"No controller was specified in action call."
337 " Server will use only plugin loaded %s. "
338 "This warning will appear once.", controller_ids_concat_.c_str());
339 current_controller = controllers_.begin()->first;
342 get_logger(),
"FollowPath called with controller name %s, "
343 "which does not exist. Available controllers are: %s.",
344 c_name.c_str(), controller_ids_concat_.c_str());
348 RCLCPP_DEBUG(get_logger(),
"Selected controller: %s.", c_name.c_str());
349 current_controller = c_name;
356 const std::string & c_name,
357 std::string & current_goal_checker)
359 if (goal_checkers_.find(c_name) == goal_checkers_.end()) {
360 if (goal_checkers_.size() == 1 && c_name.empty()) {
362 get_logger(),
"No goal checker was specified in parameter 'current_goal_checker'."
363 " Server will use only plugin loaded %s. "
364 "This warning will appear once.", goal_checker_ids_concat_.c_str());
365 current_goal_checker = goal_checkers_.begin()->first;
368 get_logger(),
"FollowPath called with goal_checker name %s in parameter"
369 " 'current_goal_checker', which does not exist. Available goal checkers are: %s.",
370 c_name.c_str(), goal_checker_ids_concat_.c_str());
374 RCLCPP_DEBUG(get_logger(),
"Selected goal checker: %s.", c_name.c_str());
375 current_goal_checker = c_name;
382 const std::string & c_name,
383 std::string & current_progress_checker)
385 if (progress_checkers_.size() == 0) {
386 if (c_name.empty()) {
389 "No progress checker configured and none requested. Progress checking will be bypassed.");
390 current_progress_checker =
"";
394 get_logger(),
"FollowPath called with progress_checker name %s in parameter"
395 " 'current_progress_checker', but no progress checkers are configured.",
401 if (progress_checkers_.find(c_name) == progress_checkers_.end()) {
402 if (progress_checkers_.size() == 1 && c_name.empty()) {
404 get_logger(),
"No progress checker was specified in parameter 'current_progress_checker'."
405 " Server will use only plugin loaded %s. "
406 "This warning will appear once.", progress_checker_ids_concat_.c_str());
407 current_progress_checker = progress_checkers_.begin()->first;
410 get_logger(),
"FollowPath called with progress_checker name %s in parameter"
411 " 'current_progress_checker', which does not exist. Available progress checkers are: %s.",
412 c_name.c_str(), progress_checker_ids_concat_.c_str());
416 RCLCPP_DEBUG(get_logger(),
"Selected progress checker: %s.", c_name.c_str());
417 current_progress_checker = c_name;
424 const std::string & c_name,
425 std::string & current_path_handler)
427 if (path_handlers_.find(c_name) == path_handlers_.end()) {
428 if (path_handlers_.size() == 1 && c_name.empty()) {
430 get_logger(),
"No path handler was specified in parameter 'current_path_handler'."
431 " Server will use only plugin loaded %s. "
432 "This warning will appear once.", path_handler_ids_concat_.c_str());
433 current_path_handler = path_handlers_.begin()->first;
436 get_logger(),
"FollowPath called with path_handler name %s in parameter"
437 " 'current_path_handler', which does not exist. Available path handlers are: %s.",
438 c_name.c_str(), path_handler_ids_concat_.c_str());
442 RCLCPP_DEBUG(get_logger(),
"Selected path handler: %s.", c_name.c_str());
443 current_path_handler = c_name;
451 std::string current_controller;
455 "Requested controller %s is not available.", goal->controller_id.c_str());
459 std::string current_goal_checker;
463 "Requested goal checker %s is not available.", goal->goal_checker_id.c_str());
467 std::string current_progress_checker;
471 "Requested progress checker %s is not available.", goal->progress_checker_id.c_str());
475 std::string current_path_handler;
479 "Requested path handler %s is not available.", goal->path_handler_id.c_str());
483 if (goal->path.poses.empty()) {
484 RCLCPP_WARN(get_logger(),
"Requested path to follow is empty.");
493 std::lock_guard<std::mutex> lock_reinit(param_handler_->getMutex());
495 RCLCPP_INFO(get_logger(),
"Received a goal, begin computing control effort.");
498 auto goal = action_server_->get_current_goal();
503 std::string c_name = goal->controller_id;
504 std::string current_controller;
506 current_controller_ = current_controller;
511 std::string gc_name = goal->goal_checker_id;
512 std::string current_goal_checker;
514 current_goal_checker_ = current_goal_checker;
519 std::string pc_name = goal->progress_checker_id;
520 std::string current_progress_checker;
522 current_progress_checker_ = current_progress_checker;
527 std::string ph_name = goal->path_handler_id;
528 std::string current_path_handler;
530 current_path_handler_ = current_path_handler;
536 if (!current_progress_checker_.empty()) {
537 progress_checkers_[current_progress_checker_]->reset();
540 last_valid_cmd_time_ = now();
541 nav2::Rate loop_rate(
this, params_->controller_frequency);
542 while (rclcpp::ok()) {
543 auto start_time = this->now();
545 if (action_server_ ==
nullptr || !action_server_->is_server_active()) {
546 RCLCPP_DEBUG(get_logger(),
"Action server unavailable or inactive. Stopping.");
550 if (action_server_->is_cancel_requested()) {
551 if (controllers_[current_controller_]->cancel()) {
552 RCLCPP_INFO(get_logger(),
"Cancellation was successful. Stopping the robot.");
553 action_server_->terminate_all();
557 RCLCPP_INFO_THROTTLE(
558 get_logger(), *get_clock(), 1000,
"Waiting for the controller to finish cancellation");
571 RCLCPP_INFO(get_logger(),
"Reached the goal!");
577 auto cycle_duration = this->now() - start_time;
578 if (!loop_rate.sleep()) {
581 "Control loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz."
583 params_->controller_frequency, 1 / cycle_duration.seconds(),
585 (
" Waited " + std::to_string(costmap_wait) +
"s for costmap update.").c_str() :
"");
590 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
592 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
593 result->error_code = Action::Result::INVALID_CONTROLLER;
594 result->error_msg = e.what();
595 action_server_->terminate_current(result);
598 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
600 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
601 result->error_code = Action::Result::TF_ERROR;
602 result->error_msg = e.what();
603 action_server_->terminate_current(result);
606 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
608 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
609 result->error_code = Action::Result::NO_VALID_CONTROL;
610 result->error_msg = e.what();
611 action_server_->terminate_current(result);
614 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
616 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
617 result->error_code = Action::Result::FAILED_TO_MAKE_PROGRESS;
618 result->error_msg = e.what();
619 action_server_->terminate_current(result);
622 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
624 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
625 result->error_code = Action::Result::PATIENCE_EXCEEDED;
626 result->error_msg = e.what();
627 action_server_->terminate_current(result);
630 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
632 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
633 result->error_code = Action::Result::INVALID_PATH;
634 result->error_msg = e.what();
635 action_server_->terminate_current(result);
638 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
640 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
641 result->error_code = Action::Result::CONTROLLER_TIMED_OUT;
642 result->error_msg = e.what();
643 action_server_->terminate_current(result);
646 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
648 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
649 result->error_code = Action::Result::UNKNOWN;
650 result->error_msg = e.what();
651 action_server_->terminate_current(result);
653 }
catch (std::exception & e) {
654 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
656 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
657 result->error_code = Action::Result::UNKNOWN;
658 result->error_msg = e.what();
659 action_server_->terminate_current(result);
663 RCLCPP_DEBUG(get_logger(),
"Controller succeeded, setting result");
668 action_server_->succeeded_current();
673 if (params_->costmap_update_timeout > rclcpp::Duration(0, 0)) {
674 auto waiting_start = now();
675 bool was_waiting = !costmap_ros_->isCurrent();
677 costmap_ros_->waitUntilCurrent(params_->costmap_update_timeout);
678 }
catch (
const std::runtime_error & ex) {
682 return (now() - waiting_start).seconds();
692 "Providing path to the controller %s", current_controller_.c_str());
693 if (path.poses.empty()) {
696 controllers_[current_controller_]->newPathReceived(path);
697 path_handlers_[current_path_handler_]->setPlan(path);
699 end_pose_ = path.poses.back();
700 end_pose_.header.frame_id = path.header.frame_id;
701 goal_checkers_[current_goal_checker_]->reset();
704 get_logger(),
"Path end point is (%.2f, %.2f)",
705 end_pose_.pose.position.x, end_pose_.pose.position.y);
708 current_path_ = path;
713 geometry_msgs::msg::PoseStamped pose;
719 end_pose_.header.stamp = pose.header.stamp;
720 if (!nav2_util::transformPoseInTargetFrame(
721 end_pose_, transformed_end_pose_, *costmap_ros_->getTfBuffer(),
722 costmap_ros_->getGlobalFrameID(), transform_tolerance_))
727 auto [closest_point, pruned_plan_end] =
728 path_handlers_[current_path_handler_]->findPlanSegment(pose);
729 transformed_global_plan_ =
730 path_handlers_[current_path_handler_]->transformLocalPlan(closest_point, pruned_plan_end);
732 auto path = std::make_unique<nav_msgs::msg::Path>(transformed_global_plan_);
733 if (transformed_plan_pub_->get_subscription_count() > 0) {
734 transformed_plan_pub_->publish(std::move(path));
740 geometry_msgs::msg::PoseStamped pose;
746 if (!current_progress_checker_.empty()) {
747 if (!progress_checkers_[current_progress_checker_]->check(pose)) {
754 geometry_msgs::msg::PoseStamped goal =
755 path_handlers_[current_path_handler_]->getTransformedGoal(pose.header.stamp);
757 geometry_msgs::msg::TwistStamped cmd_vel_2d;
761 controllers_[current_controller_]->computeVelocityCommands(
764 goal_checkers_[current_goal_checker_].get(),
765 transformed_global_plan_,
767 last_valid_cmd_time_ = now();
768 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
769 cmd_vel_2d.header.stamp = last_valid_cmd_time_;
773 if (params_->failure_tolerance > 0 || params_->failure_tolerance == -1.0) {
774 RCLCPP_WARN(this->get_logger(),
"%s", e.what());
775 cmd_vel_2d.twist.angular.x = 0;
776 cmd_vel_2d.twist.angular.y = 0;
777 cmd_vel_2d.twist.angular.z = 0;
778 cmd_vel_2d.twist.linear.x = 0;
779 cmd_vel_2d.twist.linear.y = 0;
780 cmd_vel_2d.twist.linear.z = 0;
781 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
782 cmd_vel_2d.header.stamp = now();
783 if ((now() - last_valid_cmd_time_).seconds() > params_->failure_tolerance &&
784 params_->failure_tolerance != -1.0)
793 RCLCPP_DEBUG(get_logger(),
"Publishing velocity at time %.2f", now().seconds());
796 nav2_msgs::msg::TrackingFeedback current_tracking_feedback;
798 if (current_path_.poses.size() >= 2) {
799 double current_distance_to_goal = nav2_util::geometry_utils::euclidean_distance(
800 pose, transformed_end_pose_);
803 geometry_msgs::msg::PoseStamped robot_pose_in_path_frame;
804 if (!nav2_util::transformPoseInTargetFrame(
805 pose, robot_pose_in_path_frame, *costmap_ros_->getTfBuffer(),
806 current_path_.header.frame_id, transform_tolerance_))
812 const auto path_search_result = nav2_util::distance_from_path(
813 current_path_, robot_pose_in_path_frame.pose, start_index_, params_->search_window);
816 double heading_tracking_error = 0.0;
817 if (path_search_result.closest_segment_index <
818 current_path_.poses.size() - 1)
820 const auto & path_segment_start =
821 current_path_.poses[path_search_result.closest_segment_index].pose;
822 const auto & path_segment_end =
823 current_path_.poses[path_search_result.closest_segment_index + 1].pose;
824 double path_yaw = std::atan2(
825 path_segment_end.position.y - path_segment_start.position.y,
826 path_segment_end.position.x - path_segment_start.position.x);
827 double robot_yaw = tf2::getYaw(robot_pose_in_path_frame.pose.orientation);
828 heading_tracking_error = angles::shortest_angular_distance(
829 robot_yaw, path_yaw);
833 auto tracking_feedback_msg = std::make_unique<nav2_msgs::msg::TrackingFeedback>();
834 tracking_feedback_msg->header = pose.header;
835 tracking_feedback_msg->position_tracking_error = path_search_result.distance;
836 tracking_feedback_msg->heading_tracking_error = heading_tracking_error;
837 tracking_feedback_msg->current_path_index = path_search_result.closest_segment_index;
838 tracking_feedback_msg->robot_pose = pose;
839 tracking_feedback_msg->distance_to_goal = current_distance_to_goal;
840 tracking_feedback_msg->speed = std::hypot(twist.linear.x, twist.linear.y);
841 start_index_ = path_search_result.closest_segment_index;
842 tracking_feedback_msg->remaining_path_length =
843 nav2_util::geometry_utils::calculate_path_length(current_path_, start_index_);
846 current_tracking_feedback = *tracking_feedback_msg;
847 if (tracking_feedback_pub_->get_subscription_count() > 0) {
848 tracking_feedback_pub_->publish(std::move(tracking_feedback_msg));
853 std::shared_ptr<Action::Feedback> feedback = std::make_shared<Action::Feedback>();
854 feedback->tracking_feedback = current_tracking_feedback;
855 action_server_->publish_feedback(feedback);
860 if (action_server_->is_preempt_requested()) {
861 RCLCPP_INFO(get_logger(),
"Passing new path to controller.");
862 auto goal = action_server_->accept_pending_goal();
863 std::string current_controller;
865 current_controller_ = current_controller;
867 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
868 result->error_code = Action::Result::INVALID_CONTROLLER;
869 result->error_msg =
"Terminating action, invalid controller " +
870 goal->controller_id +
" requested.";
871 action_server_->terminate_current(result);
874 std::string current_goal_checker;
876 current_goal_checker_ = current_goal_checker;
878 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
879 result->error_code = Action::Result::INVALID_CONTROLLER;
880 result->error_msg =
"Terminating action, invalid goal checker " +
881 goal->goal_checker_id +
" requested.";
882 action_server_->terminate_current(result);
885 std::string current_progress_checker;
887 if (current_progress_checker_ != current_progress_checker) {
889 get_logger(),
"Change of progress checker %s requested, resetting it",
890 goal->progress_checker_id.c_str());
891 current_progress_checker_ = current_progress_checker;
892 if (!current_progress_checker_.empty()) {
893 progress_checkers_[current_progress_checker_]->reset();
897 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
898 result->error_code = Action::Result::INVALID_CONTROLLER;
899 result->error_msg =
"Terminating action, invalid progress checker " +
900 goal->progress_checker_id +
" requested.";
901 action_server_->terminate_current(result);
904 std::string current_path_handler;
906 if (current_path_handler_ != current_path_handler) {
908 get_logger(),
"Change of path handler %s requested, resetting it",
909 goal->path_handler_id.c_str());
910 current_path_handler_ = current_path_handler;
913 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
914 result->error_code = Action::Result::INVALID_CONTROLLER;
915 result->error_msg =
"Terminating action, invalid path handler" +
916 goal->path_handler_id +
" requested.";
917 action_server_->terminate_current(result);
926 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>(velocity);
927 if (!nav2_util::validateTwist(cmd_vel->twist)) {
928 RCLCPP_ERROR(get_logger(),
"Velocity message contains NaNs or Infs! Ignoring as invalid!");
931 if (vel_publisher_->is_activated() && vel_publisher_->get_subscription_count() > 0) {
932 vel_publisher_->publish(std::move(cmd_vel));
938 geometry_msgs::msg::TwistStamped velocity;
939 velocity.twist.angular.x = 0;
940 velocity.twist.angular.y = 0;
941 velocity.twist.angular.z = 0;
942 velocity.twist.linear.x = 0;
943 velocity.twist.linear.y = 0;
944 velocity.twist.linear.z = 0;
945 velocity.header.frame_id = costmap_ros_->getBaseFrameID();
946 velocity.header.stamp = now();
952 if (params_->publish_zero_velocity || force_stop) {
957 for (
auto & controller : controllers_) {
958 controller.second->reset();
964 geometry_msgs::msg::PoseStamped pose;
972 return goal_checkers_[current_goal_checker_]->isGoalReached(
973 pose.pose, transformed_end_pose_.pose,
974 velocity, transformed_global_plan_);
979 geometry_msgs::msg::PoseStamped current_pose;
980 if (!costmap_ros_->getRobotPose(current_pose)) {
987 void ControllerServer::speedLimitCallback(
const nav2_msgs::msg::SpeedLimit::ConstSharedPtr & msg)
989 ControllerMap::iterator it;
990 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
991 it->second->setSpeedLimit(msg->speed_limit, msg->percentage);
997 #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.