19#include "auto_apms_behavior_tree/executor/generic_executor_node.hpp"
20#include "auto_apms_util/action_context.hpp"
21#include "rclcpp_action/rclcpp_action.hpp"
45template <
typename ActionT>
50 using TriggerGoal =
typename ActionT::Goal;
51 using TriggerFeedback =
typename ActionT::Feedback;
52 using TriggerResult =
typename ActionT::Result;
53 using TriggerGoalHandle = rclcpp_action::ServerGoalHandle<ActionT>;
102 virtual bool shouldAcceptGoal(
const rclcpp_action::GoalUUID & uuid, std::shared_ptr<const TriggerGoal> goal_ptr);
129 TriggerActionContext trigger_action_context_;
130 std::map<rclcpp_action::GoalUUID, TreeConstructor> pending_tree_constructors_;
137 rclcpp_action::GoalResponse handle_trigger_goal_(
138 const rclcpp_action::GoalUUID & uuid, std::shared_ptr<const TriggerGoal> goal_ptr);
139 rclcpp_action::CancelResponse handle_trigger_cancel_(std::shared_ptr<TriggerGoalHandle> goal_handle_ptr);
140 void handle_trigger_accept_(std::shared_ptr<TriggerGoalHandle> goal_handle_ptr);
142 typename rclcpp_action::Server<ActionT>::SharedPtr trigger_action_ptr_;
149template <
typename ActionT>
151 rclcpp::Node::SharedPtr node_ptr,
const std::string & action_name, Options options)
154 using namespace std::placeholders;
155 trigger_action_ptr_ = rclcpp_action::create_server<ActionT>(
156 node_ptr_, action_name, std::bind(&ActionBasedTreeExecutorNode::handle_trigger_goal_,
this, _1, _2),
157 std::bind(&ActionBasedTreeExecutorNode::handle_trigger_cancel_,
this, _1),
158 std::bind(&ActionBasedTreeExecutorNode::handle_trigger_accept_,
this, _1));
161template <
typename ActionT>
163 const std::string & name,
const std::string & action_name, Options options)
168template <
typename ActionT>
170 const std::string & name,
const std::string & action_name)
175template <
typename ActionT>
177 const rclcpp_action::GoalUUID & uuid, std::shared_ptr<const TriggerGoal> )
181 logger_,
"Goal %s was REJECTED: Tree '%s' is currently executing.", rclcpp_action::to_string(uuid).c_str(),
188template <
typename ActionT>
193template <
typename ActionT>
196 trigger_action_context_.setUp(goal_handle_ptr);
197 RCLCPP_INFO(
logger_,
"Successfully started execution of tree '%s' via action trigger.",
getTreeName().c_str());
200template <
typename ActionT>
225template <
typename ActionT>
226void ActionBasedTreeExecutorNode<ActionT>::onTermination(
const ExecutionResult & result)
228 if (trigger_action_context_.isValid()) {
229 onGoalExecutionTermination(result, trigger_action_context_);
230 trigger_action_context_.invalidate();
234template <
typename ActionT>
235rclcpp_action::GoalResponse ActionBasedTreeExecutorNode<ActionT>::handle_trigger_goal_(
236 const rclcpp_action::GoalUUID & uuid, std::shared_ptr<const TriggerGoal> goal_ptr)
238 if (!shouldAcceptGoal(uuid, goal_ptr)) {
239 return rclcpp_action::GoalResponse::REJECT;
243 pending_tree_constructors_[uuid] = getTreeConstructorFromGoal(goal_ptr);
244 }
catch (
const std::exception & e) {
246 logger_,
"Goal %s was REJECTED: Exception in getTreeConstructorFromGoal(): %s",
247 rclcpp_action::to_string(uuid).c_str(), e.what());
248 return rclcpp_action::GoalResponse::REJECT;
250 return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
253template <
typename ActionT>
254rclcpp_action::CancelResponse ActionBasedTreeExecutorNode<ActionT>::handle_trigger_cancel_(
255 std::shared_ptr<TriggerGoalHandle> )
257 setControlCommand(ControlCommand::TERMINATE);
258 return rclcpp_action::CancelResponse::ACCEPT;
261template <
typename ActionT>
262void ActionBasedTreeExecutorNode<ActionT>::handle_trigger_accept_(std::shared_ptr<TriggerGoalHandle> goal_handle_ptr)
264 onAcceptedGoal(goal_handle_ptr);
266 const rclcpp_action::GoalUUID uuid = goal_handle_ptr->get_goal_id();
267 auto node = pending_tree_constructors_.extract(uuid);
269 RCLCPP_ERROR(logger_,
"No pending tree constructor found for goal %s.", rclcpp_action::to_string(uuid).c_str());
270 auto result_ptr = std::make_shared<TriggerResult>();
271 goal_handle_ptr->abort(result_ptr);
274 TreeConstructor tree_constructor = std::move(node.mapped());
276 const ExecutorParameters params = executor_param_listener_.get_params();
278 startExecution(tree_constructor, params.tick_rate, params.groot2_port);
279 }
catch (
const std::exception & e) {
280 auto result_ptr = std::make_shared<TriggerResult>();
281 goal_handle_ptr->abort(result_ptr);
282 RCLCPP_ERROR(logger_,
"An error occurred trying to start execution: %s", e.what());
286 onExecutionStarted(goal_handle_ptr);
ActionBasedTreeExecutorNode(const std::string &name, const std::string &action_name)
Constructor with default executor options.
virtual void onExecutionStarted(std::shared_ptr< TriggerGoalHandle > goal_handle_ptr)
Hook called after execution has been started successfully.
virtual void onAcceptedGoal(std::shared_ptr< TriggerGoalHandle > goal_handle_ptr)
Hook called after a trigger action goal has been accepted and before execution begins.
virtual void onGoalExecutionTermination(const ExecutionResult &result, TriggerActionContext &context)
Handle the execution result for the action client.
ActionBasedTreeExecutorNode(rclcpp::Node::SharedPtr node_ptr, const std::string &action_name, Options options)
Constructor using an existing ROS 2 node.
ActionBasedTreeExecutorNode(const std::string &name, const std::string &action_name, Options options)
Constructor which creates a new ROS 2 node.
virtual TreeConstructor getTreeConstructorFromGoal(std::shared_ptr< const TriggerGoal > goal_ptr)=0
Create a TreeConstructor from the received action goal.
virtual bool shouldAcceptGoal(const rclcpp_action::GoalUUID &uuid, std::shared_ptr< const TriggerGoal > goal_ptr)
Determine whether an incoming trigger action goal should be accepted.
GenericTreeExecutorNode(rclcpp::Node::SharedPtr node_ptr, Options options)
Constructor using an existing ROS 2 node.
bool isBusy()
Determine whether this executor is currently executing a behavior tree.
rclcpp::Node::SharedPtr node_ptr_
Shared pointer to the parent ROS 2 node.
std::string getTreeName()
Get the name of the tree that is currently executing.
ExecutionResult
Enum representing possible behavior tree execution results.
@ TREE_SUCCEEDED
Tree completed with BT::NodeStatus::SUCCESS.
@ TERMINATED_PREMATURELY
Execution terminated before the tree was able to propagate the tick to all its nodes.
@ TREE_FAILED
Tree completed with BT::NodeStatus::FAILURE.
@ ERROR
An unexpected error occurred.
const rclcpp::Logger logger_
Logger associated with the parent ROS 2 node.
Helper class that stores contextual information related to a ROS 2 action.
void cancel()
Terminate the current goal and mark it as canceled.
std::shared_ptr< GoalHandle > getGoalHandlePtr()
Get the goal handle managed by this ActionContext instance.
void succeed()
Terminate the current goal and mark it as succeeded.
void abort()
Terminate the current goal and mark it as aborted.
Powerful tooling for incorporating behavior trees for task development.