29 , execution_stopped_(true)
38 "' currently executing.");
42 tree_ptr_.reset(
new Tree(create_tree_cb(global_blackboard_ptr_)));
44 catch (
const std::exception& e)
47 std::string(e.what()));
50 groot2_publisher_ptr_.reset();
51 groot2_publisher_ptr_ = std::make_unique<BT::Groot2Publisher>(*tree_ptr_, executor_params_.groot2_port);
52 state_observer_ptr_.reset();
53 state_observer_ptr_ = std::make_unique<BTStateObserver>(*tree_ptr_, node_ptr_->get_logger());
54 state_observer_ptr_->enableTransitionToIdle(
false);
61 termination_reason_ =
"";
62 execution_stopped_ =
true;
65 auto promise_ptr = std::make_shared<std::promise<ExecutionResult>>();
66 TerminationCallback termination_callback = [
this, promise_ptr](
ExecutionResult result,
const std::string& msg) {
67 RCLCPP_DEBUG(node_ptr_->get_logger(),
"Terminating behavior tree execution from state %s. Reason: %s.",
69 onTermination(result);
71 promise_ptr->set_value(result);
72 execution_timer_ptr_->cancel();
76 execution_timer_ptr_ =
77 node_ptr_->create_wall_timer(std::chrono::duration<double>(executor_params_.tick_rate),
78 [
this, termination_callback]() { execution_routine_(termination_callback); });
79 return promise_ptr->get_future();
84 return execution_timer_ptr_ && !execution_timer_ptr_->is_canceled();
92 throw std::logic_error(
"tree_ptr_ cannot be nullptr when execution is started.");
93 if (tree_ptr_->rootNode()->status() == BT::NodeStatus::IDLE)
106 return tree_ptr_->subtrees[0]->tree_ID;
107 return "NO_TREE_NAME";
110void TreeExecutor::execution_routine_(TerminationCallback termination_callback)
113 if (prev_execution_state_ != this_execution_state)
115 RCLCPP_DEBUG(node_ptr_->get_logger(),
"Executor for tree '%s' changed state from '%s' to '%s'.",
117 prev_execution_state_ = this_execution_state;
122 execution_stopped_ =
false;
123 bool do_on_tick =
true;
124 switch (control_command_)
127 execution_stopped_ =
true;
133 if (!onInitialTick())
136 termination_reason_ =
"onInitialTick() returned false";
149 termination_reason_ =
"onTick() returned false";
159 termination_reason_.empty() ?
"Terminated by control command" : termination_reason_);
171 tree_ptr_->haltTree();
173 catch (
const std::exception& e)
176 ": " + std::string(e.what()));
181 throw std::logic_error(
"Handling control command " + std::to_string(
static_cast<int>(control_command_)) +
" '" +
182 toStr(control_command_) +
"' is not implemented.");
187 state_observer_ptr_->setLogging(executor_params_.state_change_logger);
188 BT::NodeStatus bt_status = BT::NodeStatus::IDLE;
192 bt_status = tree_ptr_->tickExactlyOnce();
194 catch (
const std::exception& e)
196 std::string msg =
"Ran into an exception during tick: " + std::string(e.what());
199 tree_ptr_->haltTree();
201 catch (
const std::exception& e)
203 msg +=
"\nDuring haltTree(), another exception occured: " + std::string(e.what());
211 if (bt_status == BT::NodeStatus::RUNNING)
216 if (!(bt_status == BT::NodeStatus::SUCCESS || bt_status == BT::NodeStatus::FAILURE))
218 throw std::logic_error(
"bt_status is " + BT::toStr(bt_status) +
219 ". Must be one of SUCCESS or FAILURE at this point.");
221 const bool success = bt_status == BT::NodeStatus::SUCCESS;
222 switch (onTreeExit(success))
226 "Terminated on tree result " + BT::toStr(bt_status));
233 throw std::logic_error(
"Execution routine is not intended to proceed to this statement.");
236bool TreeExecutor::onInitialTick()
241bool TreeExecutor::onTick()
251void TreeExecutor::onTermination(
const ExecutionResult& )
257 control_command_ = cmd;
262 executor_params_ = p;
272 return node_ptr_->get_node_base_interface();
277 return global_blackboard_ptr_;
282 return executor_params_;
287 return *state_observer_ptr_;
341 return "TREE_SUCCEEDED";
343 return "TREE_FAILED";
345 return "TERMINATED_PREMATURELY";
void setExecutorParameters(const ExecutorParams &p)
executor_params::Params ExecutorParams
ExecutorParams getExecutorParameters()
std::function< Tree(TreeBlackboardSharedPtr)> CreateTreeCallback
void setControlCommand(ControlCommand cmd)
TreeExecutor(rclcpp::Node::SharedPtr node_ptr)
BTStateObserver & getStateObserver()
rclcpp::Node::SharedPtr getNodePtr()
Get a pointer to the internal ROS2 node instance.
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr get_node_base_interface()
Get the node's base interface. Is required to be able to register derived classes as ROS2 components.
TreeBlackboardSharedPtr getGlobalBlackboardPtr()
Get a pointer to the global blackboard instance.
std::shared_future< ExecutionResult > startExecution(CreateTreeCallback create_tree_cb)
std::string getTreeName()
ExecutionState getExecutionState()
std::string toStr(TreeExecutor::ExecutionState state)
std::shared_ptr< TreeBlackboard > TreeBlackboardSharedPtr
BT::Blackboard TreeBlackboard
void exposeToDebugLogging(const rclcpp::Logger &logger)