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_ROOT_TREE_NAME "root_tree"
22#define INPUT_KEY_NODE_MANIFEST "node_manifest"
23#define INPUT_KEY_NODE_OVERRIDES "node_overrides"
24#define INPUT_KEY_ATTACH "attach"
25#define INPUT_KEY_CLEAR_BB "clear_blackboard"
30class StartExecutor :
public core::RosActionNode<auto_apms_interfaces::action::StartTreeExecutor>
33 using RosActionNode::RosActionNode;
35 static BT::PortsList providedPorts()
40 INPUT_KEY_ATTACH,
true,
"Boolean flag wether to attach to the execution process or start in detached mode."),
42 INPUT_KEY_CLEAR_BB,
true,
43 "Boolean flag wether to clear the existing blackboard entries before the execution starts or not."),
44 BT::InputPort<std::string>(
45 INPUT_KEY_NODE_OVERRIDES,
"",
46 "YAML/JSON formatted string encoding the name and the registration options for any tree nodes supposed to "
47 "override previously loaded ones."),
48 BT::InputPort<std::string>(
49 INPUT_KEY_NODE_MANIFEST,
"",
50 "YAML/JSON formatted string encoding the name and the registration options for the tree nodes supposed to be "
51 "loaded before building the tree."),
52 BT::InputPort<std::string>(
53 INPUT_KEY_ROOT_TREE_NAME,
"",
54 "Name of the root tree. If empty, let the build handler determine the root tree."),
55 BT::InputPort<std::string>(
56 INPUT_KEY_TREE_BUILD_HANDLER,
"",
57 "Fully qualified class name of the build handler that is supposed to take care of the request. If empty, use "
59 BT::InputPort<std::string>(
60 INPUT_KEY_TREE_BUILD_REQUEST,
"String passed to the tree build handler defining which tree is to be built."),
61 BT::InputPort<std::string>(
62 INPUT_KEY_EXECUTOR_NAME,
63 "Name of the executor responsible for building and running the specified behavior tree."),
67 bool setGoal(Goal & goal)
override final
69 const BT::Expected<std::string> expected_build_request = getInput<std::string>(INPUT_KEY_TREE_BUILD_REQUEST);
70 if (!expected_build_request || expected_build_request.value().empty()) {
72 logger_,
"%s - You must provide a non-empty build request.",
73 context_.getFullyQualifiedTreeNodeName(
this).c_str());
74 RCLCPP_DEBUG_EXPRESSION(
75 logger_, !expected_build_request,
"%s - Error message: %s",
76 context_.getFullyQualifiedTreeNodeName(
this).c_str(), expected_build_request.error().c_str());
79 goal.build_request = expected_build_request.value();
80 if (
const BT::Expected<std::string> expected = getInput<std::string>(INPUT_KEY_TREE_BUILD_HANDLER)) {
81 goal.build_handler = expected.value();
83 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
86 if (
const BT::Expected<std::string> expected = getInput<std::string>(INPUT_KEY_ROOT_TREE_NAME)) {
87 goal.root_tree = expected.value();
89 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
92 if (
const BT::Expected<std::string> expected = getInput<std::string>(INPUT_KEY_NODE_MANIFEST)) {
93 goal.node_manifest = expected.value();
95 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
98 if (
const BT::Expected<std::string> expected = getInput<std::string>(INPUT_KEY_NODE_OVERRIDES)) {
99 goal.node_overrides = expected.value();
101 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
104 if (
const BT::Expected<bool> expected = getInput<bool>(INPUT_KEY_ATTACH)) {
105 goal.attach = expected.value();
107 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
110 if (
const BT::Expected<bool> expected = getInput<bool>(INPUT_KEY_CLEAR_BB)) {
111 goal.clear_blackboard = expected.value();
113 RCLCPP_ERROR(logger_,
"%s", expected.error().c_str());
119 BT::NodeStatus onResultReceived(
const WrappedResult & wr)
override final
122 case rclcpp_action::ResultCode::ABORTED: {
123 const std::string msg =
124 context_.getFullyQualifiedTreeNodeName(
this) +
" - Received result ABORTED: " + wr.result->message;
125 RCLCPP_ERROR_STREAM(logger_, msg);
126 throw exceptions::RosNodeError(msg);
129 case rclcpp_action::ResultCode::CANCELED:
131 logger_,
"%s - Received result CANCELED: %s", context_.getFullyQualifiedTreeNodeName(
this).c_str(),
132 wr.result->message.c_str());
134 return BT::NodeStatus::SUCCESS;
142 logger_,
"%s - Tree execution finished successfully with result %i: %s",
143 context_.getFullyQualifiedTreeNodeName(
this).c_str(), wr.result->tree_result, wr.result->message.c_str());
146 if (getInput<bool>(INPUT_KEY_ATTACH).value()) {
147 if (wr.result->tree_result == ActionType::Result::TREE_RESULT_SUCCESS)
return BT::NodeStatus::SUCCESS;
148 return BT::NodeStatus::FAILURE;
152 if (wr.result->tree_result == ActionType::Result::TREE_RESULT_NOT_SET)
return BT::NodeStatus::SUCCESS;
153 const std::string msg = context_.getFullyQualifiedTreeNodeName(
this) +
154 " - Expected tree_result to be TREE_RESULT_NOT_SET when started in detached mode.";
155 RCLCPP_ERROR_STREAM(logger_, msg);
156 throw exceptions::RosNodeError(msg);
Generic behavior tree node wrapper for a ROS 2 action client.
#define AUTO_APMS_BEHAVIOR_TREE_DECLARE_NODE(type)
Macro for registering a behavior tree node plugin.
Useful tooling for incorporating behavior trees for task development.