15#include "auto_apms_behavior_tree_core/node.hpp"
16#include "auto_apms_interfaces/action/start_tree_executor.hpp"
18#define INPUT_KEY_EXECUTOR_NAME "executor"
19#define INPUT_KEY_TREE_BUILD_REQUEST "build_request"
20#define INPUT_KEY_TREE_BUILD_HANDLER "build_handler"
21#define INPUT_KEY_ENTRYPOINT "entrypoint"
22#define INPUT_KEY_NODE_MANIFEST "node_manifest"
23#define INPUT_KEY_ATTACH "attach"
24#define INPUT_KEY_CLEAR_BB "clear_blackboard"
29class StartExecutor :
public core::RosActionNode<auto_apms_interfaces::action::StartTreeExecutor>
32 using RosActionNode::RosActionNode;
34 static BT::PortsList providedPorts()
39 INPUT_KEY_ATTACH,
true,
"Boolean flag wether to attach to the execution process or start in detached mode."),
41 INPUT_KEY_CLEAR_BB,
true,
42 "Boolean flag wether to clear the existing blackboard entries before the execution starts or not."),
43 BT::InputPort<std::string>(
44 INPUT_KEY_NODE_MANIFEST,
"",
45 "YAML/JSON formatted string encoding the name and the registration options for the tree nodes supposed to be "
46 "loaded before building the tree."),
47 BT::InputPort<std::string>(
48 INPUT_KEY_ENTRYPOINT,
"",
49 "Entrypoint for the behavior. If empty, let the build handler determine the entrypoint."),
50 BT::InputPort<std::string>(
51 INPUT_KEY_TREE_BUILD_HANDLER,
"",
52 "Fully qualified class name of the build handler that is supposed to take care of the request. If empty, use "
54 BT::InputPort<std::string>(
55 INPUT_KEY_TREE_BUILD_REQUEST,
"String passed to the tree build handler defining which tree is to be built."),
56 BT::InputPort<std::string>(
57 INPUT_KEY_EXECUTOR_NAME,
58 "Name of the executor responsible for building and running the specified behavior tree."),
62 bool setGoal(Goal & goal)
override final
64 const BT::Expected<std::string> expected_build_request = getInput<std::string>(INPUT_KEY_TREE_BUILD_REQUEST);
65 if (!expected_build_request || expected_build_request.value().empty()) {
67 logger_,
"%s - You must provide a non-empty build request.",
68 context_.getFullyQualifiedTreeNodeName(
this).c_str());
69 RCLCPP_DEBUG_EXPRESSION(
70 logger_, !expected_build_request,
"%s - Error message: %s",
71 context_.getFullyQualifiedTreeNodeName(
this).c_str(), expected_build_request.error().c_str());
74 goal.build_request = expected_build_request.value();
75 if (
const BT::Expected<std::string> expected = getInput<std::string>(INPUT_KEY_TREE_BUILD_HANDLER)) {
76 goal.build_handler = expected.value();
78 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
81 if (
const BT::Expected<std::string> expected = getInput<std::string>(INPUT_KEY_ENTRYPOINT)) {
82 goal.entrypoint = expected.value();
84 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
87 if (
const BT::Expected<std::string> expected = getInput<std::string>(INPUT_KEY_NODE_MANIFEST)) {
88 goal.node_manifest = expected.value();
90 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
93 if (
const BT::Expected<bool> expected = getInput<bool>(INPUT_KEY_ATTACH)) {
94 goal.attach = expected.value();
96 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
99 if (
const BT::Expected<bool> expected = getInput<bool>(INPUT_KEY_CLEAR_BB)) {
100 goal.clear_blackboard = expected.value();
102 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
108 BT::NodeStatus onResultReceived(
const WrappedResult & wr)
override final
111 case rclcpp_action::ResultCode::ABORTED: {
112 const std::string msg =
113 context_.getFullyQualifiedTreeNodeName(
this) +
" - Received result ABORTED: " + wr.result->message;
114 RCLCPP_ERROR_STREAM(logger_, msg);
115 throw exceptions::RosNodeError(msg);
118 case rclcpp_action::ResultCode::CANCELED:
120 logger_,
"%s - Received result CANCELED: %s", context_.getFullyQualifiedTreeNodeName(
this).c_str(),
121 wr.result->message.c_str());
123 return BT::NodeStatus::SUCCESS;
131 logger_,
"%s - Tree execution finished successfully with result %i: %s",
132 context_.getFullyQualifiedTreeNodeName(
this).c_str(), wr.result->tree_result, wr.result->message.c_str());
135 if (getInput<bool>(INPUT_KEY_ATTACH).value()) {
136 if (wr.result->tree_result == ActionType::Result::TREE_RESULT_SUCCESS)
return BT::NodeStatus::SUCCESS;
137 return BT::NodeStatus::FAILURE;
141 if (wr.result->tree_result == ActionType::Result::TREE_RESULT_NOT_SET)
return BT::NodeStatus::SUCCESS;
142 const std::string msg = context_.getFullyQualifiedTreeNodeName(
this) +
143 " - Expected tree_result to be TREE_RESULT_NOT_SET when started in detached mode.";
144 RCLCPP_ERROR_STREAM(logger_, msg);
145 throw exceptions::RosNodeError(msg);
Generic behavior tree node wrapper for a ROS 2 action client.
#define AUTO_APMS_BEHAVIOR_TREE_REGISTER_NODE(type)
Macro for registering a behavior tree node plugin.
Powerful tooling for incorporating behavior trees for task development.