Skip to content

Commit a536944

Browse files
author
Jonathan Cacace
committed
added tree_execution_client node
1 parent 9e8a9af commit a536944

2 files changed

Lines changed: 112 additions & 0 deletions

File tree

behaviortree_ros2/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ add_executable(bt_ros_plugins_to_xml src/tools/bt_ros_plugins_to_xml.cpp
5353
include_directories(${behaviortree_cpp_INCLUDE_DIRS} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
5454
ament_target_dependencies(bt_ros_plugins_to_xml behaviortree_cpp rclcpp)
5555

56+
57+
add_executable(tree_execution_client src/tools/client/tree_execution_client.cpp)
58+
ament_target_dependencies(tree_execution_client ${THIS_PACKAGE_DEPS})
59+
ament_target_dependencies(tree_execution_client behaviortree_cpp rclcpp)
60+
5661
# Build btros2 plugin library
5762
add_library(${PROJECT_NAME}_nodemodels SHARED src/plugin.cpp)
5863
target_include_directories(${PROJECT_NAME}_nodemodels PRIVATE
@@ -68,6 +73,11 @@ ament_target_dependencies(${PROJECT_NAME}_nodemodels ${THIS_PACKAGE_DEPS})
6873
install(TARGETS bt_ros_plugins_to_xml
6974
DESTINATION lib/${PROJECT_NAME} )
7075

76+
install(TARGETS tree_execution_client
77+
DESTINATION lib/${PROJECT_NAME} )
78+
79+
80+
7181
install(DIRECTORY include/ DESTINATION include/)
7282

7383
ament_export_targets(${PROJECT_NAME}Targets HAS_LIBRARY_TARGET)
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#include <rclcpp/rclcpp.hpp>
2+
#include <rclcpp_action/rclcpp_action.hpp>
3+
#include <btcpp_ros2_interfaces/action/execute_tree.hpp>
4+
5+
class TreeExecutionClient : public rclcpp::Node
6+
{
7+
public:
8+
using ExecuteTree = btcpp_ros2_interfaces::action::ExecuteTree;
9+
using GoalHandleExecuteTree = rclcpp_action::ClientGoalHandle<ExecuteTree>;
10+
11+
explicit TreeExecutionClient(const std::string& target_tree, const rclcpp::NodeOptions &options = rclcpp::NodeOptions())
12+
: Node("tree_execution_client", options)
13+
{
14+
action_client_ = rclcpp_action::create_client<ExecuteTree>(this, "/bt_action_server_example");
15+
16+
if (!action_client_->wait_for_action_server(std::chrono::seconds(10)))
17+
{
18+
RCLCPP_ERROR(this->get_logger(), "Action server not available after waiting");
19+
rclcpp::shutdown();
20+
return;
21+
}
22+
23+
if (target_tree.empty())
24+
{
25+
RCLCPP_ERROR(this->get_logger(), "Target tree name must be specified");
26+
rclcpp::shutdown();
27+
return;
28+
}
29+
30+
send_goal(target_tree);
31+
}
32+
33+
private:
34+
rclcpp_action::Client<ExecuteTree>::SharedPtr action_client_;
35+
36+
void send_goal(const std::string &target_tree)
37+
{
38+
auto goal_msg = ExecuteTree::Goal();
39+
goal_msg.target_tree = target_tree;
40+
goal_msg.payload = ""; // Optional payload can be set here
41+
42+
RCLCPP_INFO(this->get_logger(), "Sending goal to execute tree: %s", target_tree.c_str());
43+
44+
auto send_goal_options = rclcpp_action::Client<ExecuteTree>::SendGoalOptions();
45+
46+
send_goal_options.goal_response_callback =
47+
[this](GoalHandleExecuteTree::SharedPtr goal_handle) {
48+
if (!goal_handle)
49+
{
50+
RCLCPP_ERROR(this->get_logger(), "Goal was rejected by the server");
51+
}
52+
else
53+
{
54+
RCLCPP_INFO(this->get_logger(), "Goal accepted by the server, waiting for result");
55+
}
56+
};
57+
58+
send_goal_options.feedback_callback =
59+
[this](GoalHandleExecuteTree::SharedPtr, const std::shared_ptr<const ExecuteTree::Feedback> feedback) {
60+
RCLCPP_INFO(this->get_logger(), "Feedback received: %s", feedback->message.c_str());
61+
};
62+
63+
send_goal_options.result_callback =
64+
[this](const GoalHandleExecuteTree::WrappedResult &result) {
65+
switch (result.code)
66+
{
67+
case rclcpp_action::ResultCode::SUCCEEDED:
68+
RCLCPP_INFO(this->get_logger(), "Result received: Status=%d, Message=%s",
69+
result.result->node_status, result.result->return_message.c_str());
70+
break;
71+
case rclcpp_action::ResultCode::ABORTED:
72+
RCLCPP_ERROR(this->get_logger(), "Goal was aborted");
73+
break;
74+
case rclcpp_action::ResultCode::CANCELED:
75+
RCLCPP_WARN(this->get_logger(), "Goal was canceled");
76+
break;
77+
default:
78+
RCLCPP_ERROR(this->get_logger(), "Unknown result code");
79+
break;
80+
}
81+
rclcpp::shutdown();
82+
};
83+
84+
action_client_->async_send_goal(goal_msg, send_goal_options);
85+
}
86+
};
87+
88+
int main(int argc, char **argv)
89+
{
90+
rclcpp::init(argc, argv);
91+
92+
if (argc < 2) {
93+
RCLCPP_ERROR(rclcpp::get_logger("tree_execution_client"), "Usage: ros2 run package_name node_name <target_tree_name>");
94+
return 1;
95+
}
96+
97+
std::string target_tree = argv[1];
98+
auto node = std::make_shared<TreeExecutionClient>(target_tree);
99+
rclcpp::spin(node);
100+
rclcpp::shutdown();
101+
return 0;
102+
}

0 commit comments

Comments
 (0)