19#include "auto_apms_behavior_tree/executor/executor_node.hpp"
20#include "auto_apms_util/logging.hpp"
21#include "auto_apms_util/string.hpp"
22#include "rclcpp/rclcpp.hpp"
24sig_atomic_t
volatile termination_requested = 0;
28int main(
int argc,
char ** argv)
30 const std::vector<std::string> args_vector = rclcpp::remove_ros_arguments(argc, argv);
32 bool print_help =
false;
33 std::string build_request =
"";
34 std::string entrypoint =
"";
36 if (args_vector.size() > 1) {
37 const std::string & arg = args_vector[1];
38 print_help =
"-h" == arg ||
"--help" == arg;
41 if (args_vector.size() > 2) {
42 const std::string & arg = args_vector[2];
43 print_help =
"-h" == arg ||
"--help" == arg;
46 if (args_vector.size() > 3) {
47 const std::string & arg = args_vector[3];
48 print_help =
"-h" == arg ||
"--help" == arg;
52 std::cerr <<
"run_behavior: The program accepts: \n\t1.) String specifying the behavior tree "
53 "build request to be passed to the build handler loaded by the underlying tree executor node. If "
54 "empty, build handler must be able to handle that.\n\t2.) Optional string specifying the single point "
55 "of entry for behavior execution.\n\t3.) Optional encoded node manifest specifying the behavior tree "
56 "nodes required for behavior execution.\n";
57 std::cerr <<
"Usage: run_behavior [<build_request>] [<entrypoint>] [<node_manifest>]\n";
63 rclcpp::init(argc, argv, rclcpp::InitOptions(), rclcpp::SignalHandlerOptions::SigTerm);
64 signal(SIGINT, [](
int ) { termination_requested = 1; });
67 rclcpp::NodeOptions opt;
70 const rclcpp::Logger logger = executor.getNodePtr()->get_logger();
73 std::shared_future<TreeExecutorBase::ExecutionResult> future =
74 executor.startExecution(build_request, entrypoint, node_manifest);
75 RCLCPP_INFO(logger,
"Executing tree '%s'.", executor.getTreeName().c_str());
77 const std::chrono::duration<double> termination_timeout(3);
78 rclcpp::Time termination_start;
79 bool termination_started =
false;
81 rclcpp::spin_until_future_complete(executor.get_node_base_interface(), future, std::chrono::milliseconds(250)) !=
82 rclcpp::FutureReturnCode::SUCCESS) {
83 if (termination_started) {
84 if (executor.getNodePtr()->now() - termination_start > termination_timeout) {
85 RCLCPP_WARN(logger,
"Termination took too long. Aborted.");
88 }
else if (termination_requested) {
89 termination_start = executor.getNodePtr()->now();
91 termination_started =
true;
92 RCLCPP_INFO(logger,
"Terminating tree execution...");
97 if (future.wait_for(std::chrono::seconds(0)) != std::future_status::ready) {
98 throw std::logic_error(
"Future object is not ready.");
101 RCLCPP_INFO(logger,
"Finished with status %s.", toStr(future.get()).c_str());
@ TERMINATE
Halt the currently executing tree and terminate the execution routine.
Configuration options for TreeExecutorNode.
Flexible ROS 2 node implementing a standardized interface for dynamically executing behavior trees.
Data structure for information about which behavior tree node plugin to load and how to configure the...
std::string trimWhitespaces(const std::string &str)
Trim whitespaces from both ends of a string.
Powerful tooling for incorporating behavior trees for task development.