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");
568 RCLCPP_INFO(get_logger(),
"Reached the goal!");
574 auto cycle_duration = this->now() - start_time;
575 if (!loop_rate.sleep()) {
578 "Control loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz."
580 params_->controller_frequency, 1 / cycle_duration.seconds(),
582 (
" Waited " + std::to_string(costmap_wait) +
"s for costmap update.").c_str() :
"");
587 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
589 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
590 result->error_code = Action::Result::INVALID_CONTROLLER;
591 result->error_msg = e.what();
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::TF_ERROR;
599 result->error_msg = e.what();
600 action_server_->terminate_current(result);
603 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
605 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
606 result->error_code = Action::Result::NO_VALID_CONTROL;
607 result->error_msg = e.what();
608 action_server_->terminate_current(result);
611 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
613 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
614 result->error_code = Action::Result::FAILED_TO_MAKE_PROGRESS;
615 result->error_msg = e.what();
616 action_server_->terminate_current(result);
619 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
621 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
622 result->error_code = Action::Result::PATIENCE_EXCEEDED;
623 result->error_msg = e.what();
624 action_server_->terminate_current(result);
627 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
629 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
630 result->error_code = Action::Result::INVALID_PATH;
631 result->error_msg = e.what();
632 action_server_->terminate_current(result);
635 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
637 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
638 result->error_code = Action::Result::CONTROLLER_TIMED_OUT;
639 result->error_msg = e.what();
640 action_server_->terminate_current(result);
643 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
645 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
646 result->error_code = Action::Result::UNKNOWN;
647 result->error_msg = e.what();
648 action_server_->terminate_current(result);
650 }
catch (std::exception & e) {
651 RCLCPP_ERROR(this->get_logger(),
"%s", e.what());
653 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
654 result->error_code = Action::Result::UNKNOWN;
655 result->error_msg = e.what();
656 action_server_->terminate_current(result);
660 RCLCPP_DEBUG(get_logger(),
"Controller succeeded, setting result");
665 action_server_->succeeded_current();
670 if (params_->costmap_update_timeout > rclcpp::Duration(0, 0)) {
671 auto waiting_start = now();
672 bool was_waiting = !costmap_ros_->isCurrent();
674 costmap_ros_->waitUntilCurrent(params_->costmap_update_timeout);
675 }
catch (
const std::runtime_error & ex) {
679 return (now() - waiting_start).seconds();
689 "Providing path to the controller %s", current_controller_.c_str());
690 if (path.poses.empty()) {
693 controllers_[current_controller_]->newPathReceived(path);
694 path_handlers_[current_path_handler_]->setPlan(path);
696 end_pose_ = path.poses.back();
697 end_pose_.header.frame_id = path.header.frame_id;
698 goal_checkers_[current_goal_checker_]->reset();
701 get_logger(),
"Path end point is (%.2f, %.2f)",
702 end_pose_.pose.position.x, end_pose_.pose.position.y);
705 current_path_ = path;
710 geometry_msgs::msg::PoseStamped pose;
716 if (!current_progress_checker_.empty()) {
717 if (!progress_checkers_[current_progress_checker_]->check(pose)) {
724 geometry_msgs::msg::PoseStamped goal =
725 path_handlers_[current_path_handler_]->getTransformedGoal(pose.header.stamp);
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);
731 auto path = std::make_unique<nav_msgs::msg::Path>(transformed_global_plan_);
732 if (transformed_plan_pub_->get_subscription_count() > 0) {
733 transformed_plan_pub_->publish(std::move(path));
736 geometry_msgs::msg::TwistStamped cmd_vel_2d;
740 controllers_[current_controller_]->computeVelocityCommands(
743 goal_checkers_[current_goal_checker_].get(),
744 transformed_global_plan_,
746 last_valid_cmd_time_ = now();
747 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
748 cmd_vel_2d.header.stamp = last_valid_cmd_time_;
752 if (params_->failure_tolerance > 0 || params_->failure_tolerance == -1.0) {
753 RCLCPP_WARN(this->get_logger(),
"%s", e.what());
754 cmd_vel_2d.twist.angular.x = 0;
755 cmd_vel_2d.twist.angular.y = 0;
756 cmd_vel_2d.twist.angular.z = 0;
757 cmd_vel_2d.twist.linear.x = 0;
758 cmd_vel_2d.twist.linear.y = 0;
759 cmd_vel_2d.twist.linear.z = 0;
760 cmd_vel_2d.header.frame_id = costmap_ros_->getBaseFrameID();
761 cmd_vel_2d.header.stamp = now();
762 if ((now() - last_valid_cmd_time_).seconds() > params_->failure_tolerance &&
763 params_->failure_tolerance != -1.0)
772 RCLCPP_DEBUG(get_logger(),
"Publishing velocity at time %.2f", now().seconds());
775 nav2_msgs::msg::TrackingFeedback current_tracking_feedback;
777 if (current_path_.poses.size() >= 2) {
778 double current_distance_to_goal = nav2_util::geometry_utils::euclidean_distance(
779 pose, transformed_end_pose_);
782 geometry_msgs::msg::PoseStamped robot_pose_in_path_frame;
783 if (!nav2_util::transformPoseInTargetFrame(
784 pose, robot_pose_in_path_frame, *costmap_ros_->getTfBuffer(),
785 current_path_.header.frame_id, transform_tolerance_))
791 const auto path_search_result = nav2_util::distance_from_path(
792 current_path_, robot_pose_in_path_frame.pose, start_index_, params_->search_window);
795 double heading_tracking_error = 0.0;
796 if (path_search_result.closest_segment_index <
797 current_path_.poses.size() - 1)
799 const auto & path_segment_start =
800 current_path_.poses[path_search_result.closest_segment_index].pose;
801 const auto & path_segment_end =
802 current_path_.poses[path_search_result.closest_segment_index + 1].pose;
803 double path_yaw = std::atan2(
804 path_segment_end.position.y - path_segment_start.position.y,
805 path_segment_end.position.x - path_segment_start.position.x);
806 double robot_yaw = tf2::getYaw(robot_pose_in_path_frame.pose.orientation);
807 heading_tracking_error = angles::shortest_angular_distance(
808 robot_yaw, path_yaw);
812 auto tracking_feedback_msg = std::make_unique<nav2_msgs::msg::TrackingFeedback>();
813 tracking_feedback_msg->header = pose.header;
814 tracking_feedback_msg->position_tracking_error = path_search_result.distance;
815 tracking_feedback_msg->heading_tracking_error = heading_tracking_error;
816 tracking_feedback_msg->current_path_index = path_search_result.closest_segment_index;
817 tracking_feedback_msg->robot_pose = pose;
818 tracking_feedback_msg->distance_to_goal = current_distance_to_goal;
819 tracking_feedback_msg->speed = std::hypot(twist.linear.x, twist.linear.y);
820 start_index_ = path_search_result.closest_segment_index;
821 tracking_feedback_msg->remaining_path_length =
822 nav2_util::geometry_utils::calculate_path_length(current_path_, start_index_);
825 current_tracking_feedback = *tracking_feedback_msg;
826 if (tracking_feedback_pub_->get_subscription_count() > 0) {
827 tracking_feedback_pub_->publish(std::move(tracking_feedback_msg));
832 std::shared_ptr<Action::Feedback> feedback = std::make_shared<Action::Feedback>();
833 feedback->tracking_feedback = current_tracking_feedback;
834 action_server_->publish_feedback(feedback);
839 if (action_server_->is_preempt_requested()) {
840 RCLCPP_INFO(get_logger(),
"Passing new path to controller.");
841 auto goal = action_server_->accept_pending_goal();
842 std::string current_controller;
844 current_controller_ = current_controller;
846 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
847 result->error_code = Action::Result::INVALID_CONTROLLER;
848 result->error_msg =
"Terminating action, invalid controller " +
849 goal->controller_id +
" requested.";
850 action_server_->terminate_current(result);
853 std::string current_goal_checker;
855 current_goal_checker_ = current_goal_checker;
857 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
858 result->error_code = Action::Result::INVALID_CONTROLLER;
859 result->error_msg =
"Terminating action, invalid goal checker " +
860 goal->goal_checker_id +
" requested.";
861 action_server_->terminate_current(result);
864 std::string current_progress_checker;
866 if (current_progress_checker_ != current_progress_checker) {
868 get_logger(),
"Change of progress checker %s requested, resetting it",
869 goal->progress_checker_id.c_str());
870 current_progress_checker_ = current_progress_checker;
871 if (!current_progress_checker_.empty()) {
872 progress_checkers_[current_progress_checker_]->reset();
876 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
877 result->error_code = Action::Result::INVALID_CONTROLLER;
878 result->error_msg =
"Terminating action, invalid progress checker " +
879 goal->progress_checker_id +
" requested.";
880 action_server_->terminate_current(result);
883 std::string current_path_handler;
885 if (current_path_handler_ != current_path_handler) {
887 get_logger(),
"Change of path handler %s requested, resetting it",
888 goal->path_handler_id.c_str());
889 current_path_handler_ = current_path_handler;
892 std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
893 result->error_code = Action::Result::INVALID_CONTROLLER;
894 result->error_msg =
"Terminating action, invalid path handler" +
895 goal->path_handler_id +
" requested.";
896 action_server_->terminate_current(result);
905 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>(velocity);
906 if (!nav2_util::validateTwist(cmd_vel->twist)) {
907 RCLCPP_ERROR(get_logger(),
"Velocity message contains NaNs or Infs! Ignoring as invalid!");
910 if (vel_publisher_->is_activated() && vel_publisher_->get_subscription_count() > 0) {
911 vel_publisher_->publish(std::move(cmd_vel));
917 geometry_msgs::msg::TwistStamped velocity;
918 velocity.twist.angular.x = 0;
919 velocity.twist.angular.y = 0;
920 velocity.twist.angular.z = 0;
921 velocity.twist.linear.x = 0;
922 velocity.twist.linear.y = 0;
923 velocity.twist.linear.z = 0;
924 velocity.header.frame_id = costmap_ros_->getBaseFrameID();
925 velocity.header.stamp = now();
931 if (params_->publish_zero_velocity || force_stop) {
936 for (
auto & controller : controllers_) {
937 controller.second->reset();
943 geometry_msgs::msg::PoseStamped pose;
949 end_pose_.header.stamp = pose.header.stamp;
950 if (!nav2_util::transformPoseInTargetFrame(
951 end_pose_, transformed_end_pose_, *costmap_ros_->getTfBuffer(),
952 costmap_ros_->getGlobalFrameID(), transform_tolerance_))
959 return goal_checkers_[current_goal_checker_]->isGoalReached(
960 pose.pose, transformed_end_pose_.pose,
961 velocity, transformed_global_plan_);
966 geometry_msgs::msg::PoseStamped current_pose;
967 if (!costmap_ros_->getRobotPose(current_pose)) {
974 void ControllerServer::speedLimitCallback(
const nav2_msgs::msg::SpeedLimit::ConstSharedPtr & msg)
976 ControllerMap::iterator it;
977 for (it = controllers_.begin(); it != controllers_.end(); ++it) {
978 it->second->setSpeedLimit(msg->speed_limit, msg->percentage);
984 #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.
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.