10#ifndef _ROS_ACTION_NODE_HPP
11#define _ROS_ACTION_NODE_HPP
13#include <behaviortree_cpp/action_node.h>
16#include <rclcpp_action/rclcpp_action.hpp>
26template <
class ActionT>
31 using GoalHandle = rclcpp_action::ClientGoalHandle<Action>;
33 using WrappedResult =
typename rclcpp_action::ClientGoalHandle<Action>::WrappedResult;
44 const std::string & name,
const BT::NodeConfig & config, rclcpp::Node::SharedPtr ros_node);
51 virtual bool setGoal(
typename Action::Goal & goal) = 0;
63 virtual void onFeedback(
const std::shared_ptr<const Feedback> feedback);
102template <
class ActionT>
104 const std::string & name,
const BT::NodeConfig & config, rclcpp::Node::SharedPtr ros_node)
105: BT::StatefulActionNode(name, config), ros_node_(ros_node)
114template <
class ActionT>
121template <
class ActionT>
124 if (!client_->wait_for_action_server(std::chrono::seconds(1))) {
125 RCLCPP_ERROR(ros_node_->get_logger(),
"Action server '%s' not found", action_name.c_str());
126 return BT::NodeStatus::FAILURE;
130 typename Action::Goal goal_msg;
131 if (!setGoal(goal_msg)) {
132 RCLCPP_ERROR(ros_node_->get_logger(),
"Failed to configure the Goal");
133 return BT::NodeStatus::FAILURE;
136 auto send_goal_options =
typename ActionClient::SendGoalOptions();
137 send_goal_options.feedback_callback =
138 [
this](
typename GoalHandle::SharedPtr,
const std::shared_ptr<const Feedback> feedback) {
139 this->onFeedback(feedback);
142 future_goal_handle_ = client_->async_send_goal(goal_msg, send_goal_options);
143 RCLCPP_INFO(ros_node_->get_logger(),
"Sending goal: %s", action_name.c_str());
144 return BT::NodeStatus::RUNNING;
147template <
class ActionT>
151 if (!active_goal_handle_) {
152 if (future_goal_handle_.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
153 active_goal_handle_ = future_goal_handle_.get();
154 if (!active_goal_handle_) {
155 RCLCPP_ERROR(ros_node_->get_logger(),
"Goal was rejected by the server");
156 return BT::NodeStatus::FAILURE;
159 RCLCPP_INFO(ros_node_->get_logger(),
"Goal accepted. Waiting for result.");
160 future_result_ = client_->async_get_result(active_goal_handle_);
161 return BT::NodeStatus::RUNNING;
163 return BT::NodeStatus::RUNNING;
168 if (future_result_.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
170 active_goal_handle_.reset();
176 return BT::NodeStatus::RUNNING;
180template <
class ActionT>
183 RCLCPP_WARN(ros_node_->get_logger(),
"Action was halted");
184 if (active_goal_handle_) {
185 client_->async_cancel_goal(active_goal_handle_);
186 active_goal_handle_.reset();
Template for ROS2 Action with Behavior Tree.
Definition: ros_action_node.hpp:28
typename rclcpp_action::ClientGoalHandle< Action >::WrappedResult WrappedResult
Definition: ros_action_node.hpp:33
ActionT Action
Definition: ros_action_node.hpp:30
virtual void onFeedback(const std::shared_ptr< const Feedback > feedback)
Behavior when recieving feadback.
Definition: ros_action_node.hpp:115
virtual bool setGoal(typename Action::Goal &goal)=0
Configures the Goal message.
RosActionNode(const std::string &name, const BT::NodeConfig &config, rclcpp::Node::SharedPtr ros_node)
Create action client.
Definition: ros_action_node.hpp:103
std::shared_future< typename GoalHandle::SharedPtr > future_goal_handle_
Definition: ros_action_node.hpp:93
rclcpp::Node::SharedPtr ros_node_
Definition: ros_action_node.hpp:89
std::shared_future< WrappedResult > future_result_
Definition: ros_action_node.hpp:94
BT::NodeStatus onStart() override
Called when the node is first ticked. Initiates the ROS 2 action.
Definition: ros_action_node.hpp:122
ActionClient::SharedPtr client_
Definition: ros_action_node.hpp:90
typename Action::Feedback Feedback
Definition: ros_action_node.hpp:34
void onHalted() override
Cancels the currently active goal if one exists.
Definition: ros_action_node.hpp:181
rclcpp_action::Client< Action > ActionClient
Definition: ros_action_node.hpp:32
GoalHandle::SharedPtr active_goal_handle_
Definition: ros_action_node.hpp:95
virtual BT::NodeStatus onResult(const WrappedResult &wr)=0
Processes the final result received from the server.
std::string action_name
Definition: ros_action_node.hpp:91
rclcpp_action::ClientGoalHandle< Action > GoalHandle
Definition: ros_action_node.hpp:31
BT::NodeStatus onRunning() override
This method manages the asynchronous state machine:
Definition: ros_action_node.hpp:148