15#include "auto_apms_behavior_tree/executor/executor_node.hpp"
19#include "auto_apms_behavior_tree/exceptions.hpp"
20#include "auto_apms_behavior_tree_core/definitions.hpp"
21#include "auto_apms_util/container.hpp"
22#include "auto_apms_util/string.hpp"
23#include "rclcpp/utilities.hpp"
29 rclcpp::Node::SharedPtr node_ptr,
const std::string & start_action_name, Options options)
32 start_action_name.empty()
33 ? std::string(node_ptr->get_name()) + _AUTO_APMS_BEHAVIOR_TREE__EXECUTOR_START_ACTION_NAME_SUFFIX
38 std::vector<std::string> args_with_ros_arguments =
node_ptr_->get_node_options().arguments();
39 int argc = args_with_ros_arguments.size();
40 char ** argv =
new char *[argc + 1];
41 for (
int i = 0; i < argc; ++i) {
42 argv[i] =
const_cast<char *
>(args_with_ros_arguments[i].c_str());
48 if (
const std::vector<std::string> args = rclcpp::remove_ros_arguments(argc, argv); args.size() > 1) {
50 std::vector<std::string> relevant_args{args.begin() + 1, args.end()};
52 logger_,
"Additional cli arguments in rclcpp::NodeOptions: [ %s ]",
53 auto_apms_util::join(relevant_args,
", ").c_str());
55 const ExecutorParameters initial_params = executor_param_listener_.get_params();
62:
TreeExecutorNode(std::make_shared<rclcpp::Node>(name, options.getROSNodeOptions()), start_action_name, options)
69:
TreeExecutorNode(_AUTO_APMS_BEHAVIOR_TREE__EXECUTOR_DEFAULT_NAME, Options(ros_options))
74 const rclcpp_action::GoalUUID & uuid, std::shared_ptr<const TriggerGoal> )
78 logger_,
"Goal %s was REJECTED: Tree '%s' is currently executing.", rclcpp_action::to_string(uuid).c_str(),
87 if (!goal_ptr->build_handler.empty()) {
88 if (executor_param_listener_.get_params().allow_other_build_handlers) {
90 }
else if (goal_ptr->build_handler != current_build_handler_name_) {
91 throw exceptions::TreeExecutorError(
92 "Current tree build handler '" + current_build_handler_name_ +
93 "' must not change since the 'Allow other build handlers' option is disabled.");
97 core::NodeManifest node_manifest = core::NodeManifest::decode(goal_ptr->node_manifest);
104 if (goal_handle_ptr->get_goal()->clear_blackboard) {
111 const std::string started_tree_name =
getTreeName();
115 if (goal_handle_ptr->get_goal()->attach) {
116 trigger_action_context_.setUp(goal_handle_ptr);
117 RCLCPP_INFO(
logger_,
"Successfully started execution of tree '%s' (Mode: Attached).", started_tree_name.c_str());
119 auto result_ptr = std::make_shared<TriggerResult>();
120 result_ptr->message =
"Successfully started execution of tree '" + started_tree_name +
"' (Mode: Detached).";
121 result_ptr->tree_result = TriggerResult::TREE_RESULT_NOT_SET;
122 result_ptr->terminated_tree_identity = started_tree_name;
123 goal_handle_ptr->succeed(result_ptr);
124 RCLCPP_INFO_STREAM(
logger_, result_ptr->message);
128bool TreeExecutorNode::afterTick()
131 if (!GenericTreeExecutorNode::afterTick())
return false;
134 if (trigger_action_context_.
isValid()) {
138 feedback_ptr->running_tree_identity =
getTreeName();
140 if (!running_action_history.empty()) {
142 feedback_ptr->running_action_name = auto_apms_util::join(running_action_history,
" + ");
143 feedback_ptr->running_action_timestamp =
144 std::chrono::duration<double>{std::chrono::high_resolution_clock::now().time_since_epoch()}.count();
147 state_observer.
flush();
149 trigger_action_context_.publishFeedback();
157 auto result_ptr = context.getResultPtr();
158 result_ptr->terminated_tree_identity =
getTreeName();
161 result_ptr->tree_result = TriggerResult::TREE_RESULT_SUCCESS;
162 result_ptr->message =
"Tree execution finished with status SUCCESS";
166 result_ptr->tree_result = TriggerResult::TREE_RESULT_FAILURE;
167 result_ptr->message =
"Tree execution finished with status FAILURE";
171 result_ptr->tree_result = TriggerResult::TREE_RESULT_NOT_SET;
172 if (context.getGoalHandlePtr()->is_canceling()) {
173 result_ptr->message =
"Tree execution canceled successfully";
176 result_ptr->message =
"Tree execution terminated prematurely";
181 result_ptr->tree_result = TriggerResult::TREE_RESULT_NOT_SET;
182 result_ptr->message =
"An unexpected error occurred during tree execution";
186 result_ptr->tree_result = TriggerResult::TREE_RESULT_NOT_SET;
187 result_ptr->message =
"Execution result unknown";
ActionBasedTreeExecutorNode(rclcpp::Node::SharedPtr node_ptr, const std::string &action_name, Options options)
virtual bool clearGlobalBlackboard() override
Reset the global blackboard and clear all entries.
std::shared_future< ExecutionResult > startExecution(const std::string &build_request, const std::string &entry_point="", const core::NodeManifest &node_manifest={})
Start the behavior tree specified by a particular build request.
void loadBuildHandler(const std::string &name)
Load a particular behavior tree build handler plugin.
TreeConstructor makeTreeConstructor(const std::string &build_request, const std::string &entry_point="", const core::NodeManifest &node_manifest={})
Create a callback that builds a behavior tree according to a specific request.
ExecutionState getExecutionState()
Get a status code indicating the current state of execution.
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.
TreeStateObserver & getStateObserver()
Get a reference to the current behavior tree state observer.
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.
TreeExecutorNode(rclcpp::Node::SharedPtr node_ptr, const std::string &start_action_name, Options options)
Constructor using an existing ROS 2 node.
TreeConstructor getTreeConstructorFromGoal(std::shared_ptr< const TriggerGoal > goal_ptr) override
Create a TreeConstructor from a StartTreeExecutor action goal.
void onExecutionStarted(std::shared_ptr< TriggerGoalHandle > goal_handle_ptr) override
Hook called after execution has been started successfully.
void onAcceptedGoal(std::shared_ptr< TriggerGoalHandle > goal_handle_ptr) override
Hook called after a start action goal has been accepted and before execution begins.
void onGoalExecutionTermination(const ExecutionResult &result, TriggerActionContext &context) override
Handle the execution result for the StartTreeExecutor action client.
bool shouldAcceptGoal(const rclcpp_action::GoalUUID &uuid, std::shared_ptr< const TriggerGoal > goal_ptr) override
Determine whether an incoming start action goal should be accepted.
State observer for a particular behavior tree object that writes introspection and debugging informat...
virtual void flush() override
Reset the internal state variables.
const std::vector< std::string > & getRunningActionHistory() const
Get all names of action nodes that returned BT::NodeStatus::RUNNING since the last time TreeStateObse...
Data structure for information about which behavior tree node plugin to load and how to configure the...
std::shared_ptr< Feedback > getFeedbackPtr()
Access the internal action feedback buffer.
bool isValid()
Check if this ActionContext is valid (e.g. is managing a valid action goal handle).
Powerful tooling for incorporating behavior trees for task development.