Skip to content

Commit e6777b6

Browse files
committed
some refactoring of parameters and plugin loading
1 parent 9497662 commit e6777b6

File tree

7 files changed

+162
-73
lines changed

7 files changed

+162
-73
lines changed

behaviortree_ros2/include/behaviortree_ros2/bt_utils.hpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,14 @@ void LoadBehaviorTrees(BT::BehaviorTreeFactory& factory,
5656
const std::string& directory_path);
5757

5858
/**
59-
* @brief Function to load BehaviorTree plugins from a specific directory
59+
* @brief Function to load BehaviorTree ROS plugins (or standard BT.CPP plugins) from a specific directory
6060
*
6161
* @param factory BehaviorTreeFactory to register the plugins into
6262
* @param directory_path Full path to the directory to search for BehaviorTree plugins
63-
*/
64-
void LoadPlugins(BT::BehaviorTreeFactory& factory, const std::string& directory_path);
65-
66-
/**
67-
* @brief Function to load BehaviorTree ROS plugins from a specific directory
68-
*
69-
* @param factory BehaviorTreeFactory to register the plugins into
70-
* @param directory_path Full path to the directory to search for BehaviorTree plugins
71-
* @param node node pointer that is shared with the ROS based BehaviorTree plugins
63+
* @param params parameters passed to the ROS plugins
7264
*/
7365
void LoadRosPlugins(BT::BehaviorTreeFactory& factory, const std::string& directory_path,
74-
rclcpp::Node::SharedPtr node);
66+
BT::RosNodeParams params);
7567

7668
/**
7769
* @brief Function to register all Behaviors and BehaviorTrees from user specified packages
@@ -81,8 +73,7 @@ void LoadRosPlugins(BT::BehaviorTreeFactory& factory, const std::string& directo
8173
* @param factory BehaviorTreeFactory to register into
8274
* @param node node pointer that is shared with the ROS based Behavior plugins
8375
*/
84-
void RegisterBehaviorTrees(action_server_bt::Params& params,
85-
BT::BehaviorTreeFactory& factory,
76+
void RegisterBehaviorTrees(bt_server::Params& params, BT::BehaviorTreeFactory& factory,
8677
rclcpp::Node::SharedPtr node);
8778

8879
} // namespace BT

behaviortree_ros2/include/behaviortree_ros2/plugins.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
#include "behaviortree_cpp/utils/shared_library.h"
2121
#include "behaviortree_ros2/ros_node_params.hpp"
2222

23+
namespace BT
24+
{
25+
constexpr const char* ROS_PLUGIN_SYMBOL = "BT_RegisterRosNodeFromPlugin";
26+
}
27+
2328
// Use this macro to generate a plugin for:
2429
//
2530
// - BT::RosActionNode
@@ -54,6 +59,6 @@ inline void RegisterRosNode(BT::BehaviorTreeFactory& factory,
5459
{
5560
BT::SharedLibrary loader(filepath.generic_string());
5661
typedef void (*Func)(BT::BehaviorTreeFactory&, const BT::RosNodeParams&);
57-
auto func = (Func)loader.getSymbol("BT_RegisterRosNodeFromPlugin");
62+
auto func = (Func)loader.getSymbol(BT::ROS_PLUGIN_SYMBOL);
5863
func(factory, params);
5964
}

behaviortree_ros2/src/bt_executor_parameters.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
action_server_bt:
1+
bt_server:
22
action_name: {
33
type: string,
44
default_value: "bt_action_server",
55
read_only: true,
66
description: "The name the Action Server takes requests from",
77
}
8-
behavior_tick_frequency: {
8+
tick_frequency: {
99
type: int,
1010
default_value: 100,
1111
read_only: true,
@@ -31,10 +31,10 @@ action_server_bt:
3131
unique<>: null,
3232
}
3333
}
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",
34+
ros_plugins_timeout: {
35+
type: int,
36+
default_value: 1000,
37+
description: "Timeout (ms) used in BT::RosNodeParams",
3838
validation: {
3939
unique<>: null,
4040
}

behaviortree_ros2/src/bt_utils.cpp

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1313

1414
#include "behaviortree_ros2/bt_utils.hpp"
15+
#include "behaviortree_ros2/plugins.hpp"
1516

1617
namespace
1718
{
@@ -92,73 +93,69 @@ void LoadBehaviorTrees(BT::BehaviorTreeFactory& factory,
9293
}
9394
}
9495

95-
void LoadPlugins(BT::BehaviorTreeFactory& factory, const std::string& directory_path)
96-
{
97-
using std::filesystem::directory_iterator;
98-
for(const auto& entry : directory_iterator(directory_path))
99-
{
100-
if(entry.path().extension() == ".so")
101-
{
102-
try
103-
{
104-
factory.registerFromPlugin(entry.path().string());
105-
RCLCPP_INFO(kLogger, "Loaded Plugin: %s", entry.path().filename().c_str());
106-
}
107-
catch(const std::exception& e)
108-
{
109-
RCLCPP_ERROR(kLogger, "Failed to load Plugin: %s \n %s",
110-
entry.path().filename().c_str(), e.what());
111-
}
112-
}
113-
}
114-
}
115-
11696
void LoadRosPlugins(BT::BehaviorTreeFactory& factory, const std::string& directory_path,
117-
rclcpp::Node::SharedPtr node)
97+
BT::RosNodeParams params)
11898
{
11999
using std::filesystem::directory_iterator;
120-
BT::RosNodeParams params;
121-
params.nh = node;
100+
122101
for(const auto& entry : directory_iterator(directory_path))
123102
{
103+
const auto filename = entry.path().filename();
124104
if(entry.path().extension() == ".so")
125105
{
126106
try
127107
{
128-
RegisterRosNode(factory, entry.path().string(), params);
129-
RCLCPP_INFO(kLogger, "Loaded ROS Plugin: %s", entry.path().filename().c_str());
108+
BT::SharedLibrary loader(entry.path().string());
109+
if(loader.hasSymbol(BT::PLUGIN_SYMBOL))
110+
{
111+
typedef void (*Func)(BehaviorTreeFactory&);
112+
auto func = (Func)loader.getSymbol(BT::PLUGIN_SYMBOL);
113+
func(factory);
114+
}
115+
else if(loader.hasSymbol(BT::ROS_PLUGIN_SYMBOL))
116+
{
117+
typedef void (*Func)(BT::BehaviorTreeFactory&, const BT::RosNodeParams&);
118+
auto func = (Func)loader.getSymbol(BT::ROS_PLUGIN_SYMBOL);
119+
func(factory, params);
120+
}
121+
else
122+
{
123+
RCLCPP_ERROR(kLogger, "Failed to load Plugin from file: %s.", filename.c_str());
124+
continue;
125+
}
126+
RCLCPP_INFO(kLogger, "Loaded ROS Plugin: %s", filename.c_str());
130127
}
131128
catch(const std::exception& e)
132129
{
133-
RCLCPP_ERROR(kLogger, "Failed to load ROS Plugin: %s \n %s",
134-
entry.path().filename().c_str(), e.what());
130+
RCLCPP_ERROR(kLogger, "Failed to load ROS Plugin: %s \n %s", filename.c_str(),
131+
e.what());
135132
}
136133
}
137134
}
138135
}
139136

140-
void RegisterBehaviorTrees(action_server_bt::Params& params,
141-
BT::BehaviorTreeFactory& factory, rclcpp::Node::SharedPtr node)
137+
void RegisterBehaviorTrees(bt_server::Params& params, BT::BehaviorTreeFactory& factory,
138+
rclcpp::Node::SharedPtr node)
142139
{
143-
// clear the factory and load/reload it with the Behaviors and Trees specified by the user in their action_server_bt config yaml
140+
// clear the factory and load/reload it with the Behaviors and Trees specified by the user in their [bt_action_server] config yaml
144141
factory.clearRegisteredBehaviorTrees();
145142

143+
BT::RosNodeParams ros_params;
144+
ros_params.nh = node;
145+
ros_params.server_timeout = std::chrono::milliseconds(params.ros_plugins_timeout);
146+
ros_params.wait_for_server_timeout = ros_params.server_timeout;
147+
146148
for(const auto& plugin : params.plugins)
147149
{
148150
const auto plugin_directory = GetDirectoryPath(plugin);
149151
// skip invalid plugins directories
150152
if(plugin_directory.empty())
153+
{
151154
continue;
152-
LoadPlugins(factory, plugin_directory);
153-
}
154-
for(const auto& plugin : params.ros_plugins)
155-
{
156-
const auto plugin_directory = GetDirectoryPath(plugin);
157-
// skip invalid plugins directories
158-
if(plugin_directory.empty())
159-
continue;
160-
LoadRosPlugins(factory, plugin_directory, node);
155+
}
156+
LoadRosPlugins(factory, plugin_directory, ros_params);
161157
}
158+
162159
for(const auto& tree_dir : params.behavior_trees)
163160
{
164161
const auto tree_directory = GetDirectoryPath(tree_dir);

behaviortree_ros2/src/tree_execution_server.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ struct TreeExecutionServer::Pimpl
3838
// thread safe bool to keep track of cancel requests
3939
std::atomic<bool> cancel_requested{ false };
4040

41-
std::shared_ptr<action_server_bt::ParamListener> param_listener;
42-
action_server_bt::Params params;
41+
std::shared_ptr<bt_server::ParamListener> param_listener;
42+
bt_server::Params params;
4343

4444
BT::BehaviorTreeFactory factory;
4545
std::shared_ptr<BT::Groot2Publisher> groot_publisher;
@@ -62,7 +62,7 @@ struct TreeExecutionServer::Pimpl
6262
TreeExecutionServer::Pimpl::Pimpl(const rclcpp::NodeOptions& node_options)
6363
: node(std::make_unique<rclcpp::Node>("bt_action_server", node_options))
6464
{
65-
param_listener = std::make_shared<action_server_bt::ParamListener>(node);
65+
param_listener = std::make_shared<bt_server::ParamListener>(node);
6666
params = param_listener->get_params();
6767
global_blackboard = BT::Blackboard::create();
6868
}
@@ -168,8 +168,8 @@ void TreeExecutionServer::execute(
168168
std::make_shared<BT::Groot2Publisher>(*(p_->tree), p_->params.groot2_port);
169169

170170
// Loop until the tree is done or a cancel is requested
171-
const auto period = std::chrono::milliseconds(
172-
static_cast<int>(1000.0 / p_->params.behavior_tick_frequency));
171+
const auto period =
172+
std::chrono::milliseconds(static_cast<int>(1000.0 / p_->params.tick_frequency));
173173
auto loop_deadline = std::chrono::steady_clock::now() + period;
174174

175175
// operations to be done if the tree execution is aborted, either by
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# TreeExecutionServer
2+
3+
This base class is used to implement a Behavior Tree executor wrapped inside a `rclcpp_action::Server`.
4+
5+
Users are expected to create a derived class to improve its functionalities, but often it can be used
6+
out of the box directly.
7+
8+
Further, the terms "load" will be equivalent to "register into the `BT::BehaviorTreeFactory`".
9+
10+
The `TreeExecutionServer`offers the following features:
11+
12+
- Configurable using ROS parameters (see below).
13+
- Load Behavior Trees definitions (XML files) from a list of folders.
14+
- Load BT plugins from a list of folders. These plugins may depend or not on ROS.
15+
- Invoke the execution of a Tree from an external ROS Node, using `rclcpp_action::Client`.
16+
17+
Furthermore, the user can customize it to:
18+
19+
- Register custom BT Nodes directly (static linking).
20+
- Attach additional loggers. The **Groot2** publisher will be attached by default.
21+
- Use the "global blackboard", a new idiom/pattern explained in [this tutorial](https://github.com/BehaviorTree/BehaviorTree.CPP/blob/master/examples/t19_global_blackboard.cpp).
22+
- Customize the feedback of the `rclcpp_action::Server`.
23+
24+
25+
## ROS Parameters
26+
27+
Default Config
28+
29+
```yaml
30+
bt_action_server:
31+
ros__parameters:
32+
action_name: bt_action_server
33+
behavior_tick_frequency: 100.0
34+
behavior_trees: '{}'
35+
groot2_port: 1667.0
36+
plugins: '{}'
37+
ros_plugins: '{}'
38+
39+
```
40+
41+
## action_name
42+
43+
The name the Action Server takes requests from
44+
45+
* Type: `string`
46+
* Default Value: "bt_action_server"
47+
* Read only: True
48+
49+
## behavior_tick_frequency
50+
51+
Frequency in Hz to tick() the Behavior tree at
52+
53+
* Type: `int`
54+
* Default Value: 100
55+
* Read only: True
56+
57+
*Constraints:*
58+
- parameter must be within bounds 1
59+
60+
## groot2_port
61+
62+
Server port value to publish Groot2 messages on
63+
64+
* Type: `int`
65+
* Default Value: 1667
66+
* Read only: True
67+
68+
*Constraints:*
69+
- parameter must be within bounds 1
70+
71+
## plugins
72+
73+
List of 'package_name/subfolder' containing BehaviorTree plugins to load into the factory
74+
75+
* Type: `string_array`
76+
* Default Value: {}
77+
78+
*Constraints:*
79+
- contains no duplicates
80+
81+
## ros_plugins
82+
83+
List of 'package_name/subfolder' containing BehaviorTree ROS plugins to load into the factory
84+
85+
* Type: `string_array`
86+
* Default Value: {}
87+
88+
*Constraints:*
89+
- contains no duplicates
90+
91+
## behavior_trees
92+
93+
List of 'package_name/subfolder' containing SubTrees to load into the BehaviorTree factory
94+
95+
* Type: `string_array`
96+
* Default Value: {}
97+
98+
*Constraints:*
99+
- contains no duplicates
Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
action_server_bt:
1+
bt_action_server:
22
ros__parameters:
3-
action_name: "behavior_server" # Optional (defaults to `action_server_bt`)
4-
behavior_tick_frequency: 100 # Optional (defaults to 100 Hz)
3+
action_name: "behavior_server" # Optional (defaults to `bt_action_server`)
4+
tick_frequency: 100 # Optional (defaults to 100 Hz)
55
groot2_port: 1667 # Optional (defaults to 1667)
6+
ros_plugins_timeout: 1000 # Optional (defaults 1000 ms)
67

7-
# Below are a list plugins and BehaviorTrees to load
8-
# (you are not required to have all 3 types)
9-
# These are dynamic parameters and can be changed at runtime via rosparam
10-
# see `action_server_bt/parameters.md` for documentation.
118
plugins:
129
- behaviortree_cpp/bt_plugins
13-
ros_plugins:
1410
- btcpp_ros2_samples/bt_plugins
11+
1512
behavior_trees:
1613
- btcpp_ros2_samples/behavior_trees

0 commit comments

Comments
 (0)