19 #include "nav2_behavior_tree/plugins/control/pause_resume_controller.hpp"
22 #include "behaviortree_cpp/bt_factory.h"
24 namespace nav2_behavior_tree
27 using namespace std::placeholders;
30 const std::string & xml_tag_name,
31 const BT::NodeConfiguration & conf)
32 : BT::ControlNode(xml_tag_name, conf)
34 auto node = this->config().blackboard->get<rclcpp::Node::SharedPtr>(
"node");
38 cb_group_ = node->create_callback_group(
39 rclcpp::CallbackGroupType::MutuallyExclusive,
false);
42 std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
44 executor_->add_callback_group(cb_group_, node->get_node_base_interface());
46 std::string pause_service_name;
47 getInput(
"pause_service_name", pause_service_name);
48 pause_srv_ = std::make_shared<nav2::ServiceServer<Trigger>>(
51 std::bind(&PauseResumeController::pauseServiceCallback,
this, _1, _2, _3),
54 std::string resume_service_name;
55 getInput(
"resume_service_name", resume_service_name);
56 resume_srv_ = std::make_shared<nav2::ServiceServer<Trigger>>(
59 std::bind(&PauseResumeController::resumeServiceCallback,
this, _1, _2, _3),
65 unsigned int children_count = children_nodes_.size();
66 if (children_count < 1 || children_count > 4) {
67 throw std::runtime_error(
68 "PauseNode must have at least one and at most four children "
69 "(currently has " + std::to_string(children_count) +
")");
72 if (status() == BT::NodeStatus::IDLE) {
75 setStatus(BT::NodeStatus::RUNNING);
77 executor_->spin_some();
80 if (state_ == PAUSE_REQUESTED || state_ == RESUME_REQUESTED) {
86 const uint16_t child_idx = child_indices.at(state_);
87 if (children_nodes_.size() <= child_idx) {
89 return BT::NodeStatus::RUNNING;
93 const BT::NodeStatus child_status =
94 children_nodes_[child_indices.at(state_)]->executeTick();
96 switch (child_status) {
97 case BT::NodeStatus::RUNNING:
98 return BT::NodeStatus::RUNNING;
99 case BT::NodeStatus::SUCCESS:
100 case BT::NodeStatus::SKIPPED:
101 if (state_ == RESUMED) {
103 return BT::NodeStatus::SUCCESS;
107 return BT::NodeStatus::RUNNING;
108 case BT::NodeStatus::FAILURE:
110 logger_,
"%s child returned FAILURE", state_names.at(state_).c_str());
111 return BT::NodeStatus::FAILURE;
113 throw std::runtime_error(
"A child node must never return IDLE");
117 void PauseResumeController::switchToNextState()
119 static const std::map<state_t, state_t> next_states = {
120 {PAUSE_REQUESTED, ON_PAUSE},
122 {RESUME_REQUESTED, ON_RESUME},
126 if (state_ == PAUSED || state_ == RESUMED) {
131 state_ = next_states.at(state_);
132 RCLCPP_INFO(logger_,
"Switched to state: %s", state_names.at(state_).c_str());
135 void PauseResumeController::pauseServiceCallback(
136 const std::shared_ptr<rmw_request_id_t>,
137 const std::shared_ptr<Trigger::Request>,
138 std::shared_ptr<Trigger::Response> response)
140 if (state_ != PAUSED) {
141 RCLCPP_INFO(logger_,
"Received pause request");
142 response->success =
true;
143 state_ = PAUSE_REQUESTED;
147 std::string warn_message =
"PauseResumeController BT node already in state PAUSED";
148 RCLCPP_WARN(logger_,
"%s", warn_message.c_str());
149 response->success =
false;
150 response->message = warn_message;
153 void PauseResumeController::resumeServiceCallback(
154 const std::shared_ptr<rmw_request_id_t>,
155 const std::shared_ptr<Trigger::Request>,
156 std::shared_ptr<Trigger::Response> response)
158 if (state_ == PAUSED) {
159 RCLCPP_INFO(logger_,
"Received resume request");
160 response->success =
true;
161 state_ = RESUME_REQUESTED;
165 std::string warn_message =
"PauseResumeController BT node not in state PAUSED";
166 RCLCPP_WARN(logger_,
"%s", warn_message.c_str());
167 response->success =
false;
168 response->message = warn_message;
179 BT_REGISTER_NODES(factory)
181 BT::NodeBuilder builder =
182 [](
const std::string & name,
const BT::NodeConfiguration & config)
184 return std::make_unique<nav2_behavior_tree::PauseResumeController>(
189 "PauseResumeController", builder);
PauseResumeController(const std::string &xml_tag_name, const BT::NodeConfiguration &conf)
Constructor.
BT::NodeStatus tick() override
Handle transitions if requested and tick child related to the actual state.
void halt() override
Reset state and go to Idle.