Skip to content

Commit 3183c9d

Browse files
committed
WIP: added an ActionServerBT to execute trees
1 parent 374edcf commit 3183c9d

File tree

17 files changed

+891
-14
lines changed

17 files changed

+891
-14
lines changed

behaviortree_ros2/CMakeLists.txt

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,57 @@ project(behaviortree_ros2)
33

44
set(CMAKE_CXX_STANDARD 17)
55
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6-
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
76

87
set(THIS_PACKAGE_DEPS
98
rclcpp
109
rclcpp_action
1110
ament_index_cpp
12-
behaviortree_cpp)
11+
behaviortree_cpp
12+
btcpp_ros2_interfaces
13+
generate_parameter_library
14+
)
1315

1416
find_package(ament_cmake REQUIRED)
15-
find_package(rclcpp REQUIRED )
16-
find_package(rclcpp_action REQUIRED )
17-
find_package(behaviortree_cpp REQUIRED )
18-
find_package(ament_index_cpp REQUIRED)
19-
20-
# This is compiled only to check if there are errors in the header file
21-
# library will not be exported
22-
include_directories(include)
23-
add_library(${PROJECT_NAME} src/bt_ros2.cpp)
17+
18+
foreach(PACKAGE ${THIS_PACKAGE_DEPS})
19+
find_package(${PACKAGE} REQUIRED )
20+
endforeach()
21+
22+
23+
generate_parameter_library(
24+
bt_executor_parameters
25+
src/bt_executor_parameters.yaml)
26+
27+
add_library(${PROJECT_NAME}
28+
src/bt_ros2.cpp
29+
src/bt_utils.cpp
30+
src/tree_execution_server.cpp )
31+
2432
ament_target_dependencies(${PROJECT_NAME} ${THIS_PACKAGE_DEPS})
2533

34+
target_include_directories(${PROJECT_NAME} PUBLIC
35+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
36+
$<INSTALL_INTERFACE:include>)
37+
38+
target_link_libraries(${PROJECT_NAME} bt_executor_parameters)
39+
40+
2641
######################################################
2742
# INSTALL
2843

2944
install(DIRECTORY include/ DESTINATION include/)
3045

31-
ament_export_include_directories(include)
46+
ament_export_targets(${PROJECT_NAME}Targets HAS_LIBRARY_TARGET)
3247
ament_export_dependencies(${THIS_PACKAGE_DEPS})
3348

49+
install(
50+
TARGETS ${PROJECT_NAME} bt_executor_parameters
51+
EXPORT ${PROJECT_NAME}Targets
52+
ARCHIVE DESTINATION lib
53+
LIBRARY DESTINATION lib
54+
RUNTIME DESTINATION lib/${PROJECT_NAME})
55+
56+
ament_export_include_directories(include)
57+
ament_export_libraries(${PROJECT_NAME})
58+
3459
ament_package()
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright 2024 Marq Rasmussen
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
4+
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
5+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
6+
// permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright
7+
// notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
//
9+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
10+
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
11+
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
12+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13+
14+
#include <functional>
15+
#include <memory>
16+
#include <thread>
17+
18+
// auto-generated header, created by generate_parameter_library
19+
#include "bt_executor_parameters.hpp"
20+
21+
#include "btcpp_ros2_interfaces/msg/node_status.hpp"
22+
23+
#include "behaviortree_cpp/bt_factory.h"
24+
25+
#include "behaviortree_ros2/plugins.hpp"
26+
#include "behaviortree_ros2/ros_node_params.hpp"
27+
28+
#include "rclcpp/rclcpp.hpp"
29+
#include <ament_index_cpp/get_package_share_directory.hpp>
30+
31+
namespace action_server_bt
32+
{
33+
/**
34+
* @brief Convert BT::NodeStatus into Action Server feedback message NodeStatus
35+
* @param status Current status of the executing BehaviorTree
36+
* @return NodeStatus used to publish feedback to the Action Client
37+
*/
38+
btcpp_ros2_interfaces::msg::NodeStatus convert_node_status(BT::NodeStatus& status);
39+
40+
/**
41+
* @brief Function the uses ament_index_cpp to get the package path of the parameter specified by the user
42+
* @param parameter_value String containing 'package_name/subfolder' for the directory path to look up
43+
* @return Full path to the directory specified by the parameter_value
44+
*/
45+
std::string get_directory_path(const std::string& parameter_value);
46+
47+
/**
48+
* @brief Function to load BehaviorTree xml files from a specific directory
49+
* @param factory BehaviorTreeFactory to register the BehaviorTrees into
50+
* @param directory_path Full path to the directory to search for BehaviorTree definitions
51+
*/
52+
void load_behavior_trees(BT::BehaviorTreeFactory& factory,
53+
const std::string& directory_path);
54+
55+
/**
56+
* @brief Function to load BehaviorTree plugins from a specific directory
57+
* @param factory BehaviorTreeFactory to register the plugins into
58+
* @param directory_path Full path to the directory to search for BehaviorTree plugins
59+
*/
60+
void load_plugins(BT::BehaviorTreeFactory& factory, const std::string& directory_path);
61+
62+
/**
63+
* @brief Function to load BehaviorTree ROS plugins from a specific directory
64+
* @param factory BehaviorTreeFactory to register the plugins into
65+
* @param directory_path Full path to the directory to search for BehaviorTree plugins
66+
* @param node node pointer that is shared with the ROS based BehaviorTree plugins
67+
*/
68+
void load_ros_plugins(BT::BehaviorTreeFactory& factory, const std::string& directory_path,
69+
rclcpp::Node::SharedPtr node);
70+
71+
/**
72+
* @brief Function to register all Behaviors and BehaviorTrees from user specified packages
73+
* @param params ROS parameters that contain lists of packages to load
74+
* plugins, ros_plugins and BehaviorTrees from
75+
* @param factory BehaviorTreeFactory to register into
76+
* @param node node pointer that is shared with the ROS based Behavior plugins
77+
*/
78+
void register_behavior_trees(action_server_bt::Params& params,
79+
BT::BehaviorTreeFactory& factory,
80+
rclcpp::Node::SharedPtr node);
81+
82+
} // namespace action_server_bt
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// Copyright 2024 Marq Rasmussen
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
4+
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
5+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
6+
// permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright
7+
// notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
//
9+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
10+
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
11+
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
12+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13+
14+
#include <memory>
15+
#include <optional>
16+
17+
#include "btcpp_ros2_interfaces/action/execute_tree.hpp"
18+
19+
#include "behaviortree_cpp/bt_factory.h"
20+
21+
#include "rclcpp/rclcpp.hpp"
22+
#include "rclcpp_action/rclcpp_action.hpp"
23+
24+
namespace action_server_bt
25+
{
26+
27+
/**
28+
* @brief ActionServerBT class hosts a ROS Action Server that is able
29+
* to load Behavior plugins, BehaviorTree.xml files and execute them.
30+
*/
31+
class ActionServerBT
32+
{
33+
public:
34+
using ExecuteTree = btcpp_ros2_interfaces::action::ExecuteTree;
35+
using GoalHandleExecuteTree = rclcpp_action::ServerGoalHandle<ExecuteTree>;
36+
37+
/**
38+
* @brief Constructor for ActionServerBT.
39+
* @details This initializes a ParameterListener to read configurable options from the user and
40+
* starts an Action Server that takes requests to execute BehaviorTrees.
41+
*
42+
* @param options rclcpp::NodeOptions to pass to node_ when initializing it.
43+
* after the tree is created, while its running and after it finishes.
44+
*/
45+
explicit ActionServerBT(const rclcpp::NodeOptions& options);
46+
47+
virtual ~ActionServerBT();
48+
49+
/**
50+
* @brief Gets the NodeBaseInterface of node_.
51+
* @details This function exists to allow running ActionServerBT as a component in a composable node container.
52+
*
53+
* @return A shared_ptr to the NodeBaseInterface of node_.
54+
*/
55+
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr nodeBaseInterface();
56+
57+
// name of the tree being executed
58+
const std::string& currentTreeName() const;
59+
60+
// tree being executed, nullptr if it doesn't exist yet.
61+
BT::Tree* currentTree();
62+
63+
// pointer to the global blackboard
64+
BT::Blackboard::Ptr globalBlackboard();
65+
66+
protected:
67+
// To be overridden by the user.
68+
// Callback invoked when the tree is created and before it is executed,
69+
// Can be used to update the blackboard or to attach loggers.
70+
virtual void onTreeCreated(BT::Tree& tree)
71+
{}
72+
73+
// To be overridden by the user.
74+
// In addition to the built in mechanism to register nodes from plugins,
75+
// you can use this method to register custom nodes into the factory.
76+
virtual void registerNodesIntoFactory(BT::BehaviorTreeFactory& factory)
77+
{}
78+
79+
// To be overridden by the user.
80+
// Callback invoked after the tickOnce.
81+
// If it returns something different than std::nullopt, the tree execution will
82+
// be halted and the returned value will be the optional NodeStatus.
83+
virtual std::optional<BT::NodeStatus> onLoopAfterTick(BT::NodeStatus status)
84+
{
85+
return std::nullopt;
86+
}
87+
88+
// To be overridden by the user.
89+
// Callback invoked when the tree execution is completed
90+
virtual void onTreeExecutionCompleted(BT::NodeStatus status, bool was_cancelled)
91+
{}
92+
93+
virtual std::optional<std::string> onLoopFeedback()
94+
{
95+
return std::nullopt;
96+
}
97+
98+
private:
99+
struct Pimpl;
100+
std::unique_ptr<Pimpl> p_;
101+
102+
/**
103+
* @brief handle the goal requested: accept or reject. This implementation always accepts.
104+
* @param uuid Goal ID
105+
* @param goal A shared pointer to the specific goal
106+
* @return GoalResponse response of the goal processed
107+
*/
108+
rclcpp_action::GoalResponse handle_goal(const rclcpp_action::GoalUUID& uuid,
109+
std::shared_ptr<const ExecuteTree::Goal> goal);
110+
111+
/**
112+
* @brief Accepts cancellation requests of action server.
113+
* @param goal A server goal handle to cancel
114+
* @return CancelResponse response of the goal cancelled
115+
*/
116+
rclcpp_action::CancelResponse
117+
handle_cancel(const std::shared_ptr<GoalHandleExecuteTree> goal_handle);
118+
119+
/**
120+
* @brief Handles accepted goals and starts a thread to process them
121+
* @param goal_handle Server goal handle to process feedback and set the response when finished
122+
*/
123+
void handle_accepted(const std::shared_ptr<GoalHandleExecuteTree> goal_handle);
124+
125+
/**
126+
* @brief Background processes to execute the BehaviorTree and handle stop requests
127+
* @param goal_handle Server goal handle to process feedback and set the response when finished
128+
*/
129+
void execute(const std::shared_ptr<GoalHandleExecuteTree> goal_handle);
130+
};
131+
132+
} // namespace action_server_bt

behaviortree_ros2/package.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,14 @@
1111

1212
<buildtool_depend>ament_cmake</buildtool_depend>
1313

14+
<depend>fmt</depend>
1415
<depend>libboost-dev</depend>
16+
1517
<depend>rclcpp</depend>
1618
<depend>rclcpp_action</depend>
1719
<depend>behaviortree_cpp</depend>
20+
<depend>generate_parameter_library</depend>
21+
<depend>btcpp_ros2_interfaces</depend>
1822

1923
<export>
2024
<build_type>ament_cmake</build_type>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
action_server_bt:
2+
action_name: {
3+
type: string,
4+
default_value: "action_server_bt",
5+
read_only: true,
6+
description: "The name the Action Server takes requests from",
7+
}
8+
behavior_tick_frequency: {
9+
type: int,
10+
default_value: 100,
11+
read_only: true,
12+
description: "Frequency in Hz to tick() the Behavior tree at",
13+
validation: {
14+
bounds<>: [1, 1000]
15+
}
16+
}
17+
groot2_port: {
18+
type: int,
19+
default_value: 1667,
20+
read_only: true,
21+
description: "Server port value to publish Groot2 messages on",
22+
validation: {
23+
bounds<>: [1, 49151]
24+
}
25+
}
26+
plugins: {
27+
type: string_array,
28+
default_value: [],
29+
description: "List of 'package_name/subfolder' containing BehaviorTree plugins to load into the factory",
30+
validation: {
31+
unique<>: null,
32+
}
33+
}
34+
ros_plugins: {
35+
type: string_array,
36+
default_value: [],
37+
description: "List of 'package_name/subfolder' containing BehaviorTree ROS plugins to load into the factory",
38+
validation: {
39+
unique<>: null,
40+
}
41+
}
42+
behavior_trees: {
43+
type: string_array,
44+
default_value: [],
45+
description: "List of 'package_name/subfolder' containing SubTrees to load into the BehaviorTree factory",
46+
validation: {
47+
unique<>: null,
48+
}
49+
}

0 commit comments

Comments
 (0)