Skip to content

Commit a55c1ce

Browse files
add the ability to register multiple BTs (#373)
1 parent 6812cc6 commit a55c1ce

File tree

8 files changed

+251
-48
lines changed

8 files changed

+251
-48
lines changed

examples/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,5 @@ if(CURSES_FOUND)
5252
target_link_libraries(t12_ncurses_manual_selector ${BEHAVIOR_TREE_LIBRARY} bt_sample_nodes )
5353
endif()
5454

55+
add_executable(t13_load_multiple_BTs t13_load_multiple_BTs.cpp )
56+
target_link_libraries(t13_load_multiple_BTs ${BEHAVIOR_TREE_LIBRARY} bt_sample_nodes )

examples/t13_load_multiple_BTs.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include "dummy_nodes.h"
2+
#include "behaviortree_cpp_v3/bt_factory.h"
3+
4+
5+
/** This example show how it is possible to:
6+
* - load BehaviorTrees from multiple files manually (without the <include> tag)
7+
* - instantiate a specific tree, instead of the one specified by [main_tree_to_execute]
8+
*/
9+
10+
// clang-format off
11+
12+
static const char* xml_text_main = R"(
13+
<root main_tree_to_execute="MainTree">
14+
<BehaviorTree ID="MainTree">
15+
<Sequence>
16+
<SaySomething message="starting MainTree" />
17+
<SubTree ID="SubA"/>
18+
<SubTree ID="SubB"/>
19+
</Sequence>
20+
</BehaviorTree>
21+
</root> )";
22+
23+
static const char* xml_text_subA = R"(
24+
<root>
25+
<BehaviorTree ID="SubA">
26+
<SaySomething message="Executing SubA" />
27+
</BehaviorTree>
28+
</root> )";
29+
30+
static const char* xml_text_subB = R"(
31+
<root>
32+
<BehaviorTree ID="SubB">
33+
<SaySomething message="Executing SubB" />
34+
</BehaviorTree>
35+
</root> )";
36+
37+
// clang-format on
38+
39+
using namespace BT;
40+
41+
int main()
42+
{
43+
BT::BehaviorTreeFactory factory;
44+
factory.registerNodeType<DummyNodes::SaySomething>("SaySomething");
45+
46+
// Register the behavior tree definitions, but do not instantiate them yet.
47+
// Order is not important.
48+
factory.registerBehaviorTreeFromText(xml_text_subA);
49+
factory.registerBehaviorTreeFromText(xml_text_subB);
50+
factory.registerBehaviorTreeFromText(xml_text_main);
51+
52+
//Check that the BTs have been registered correctly
53+
std::cout << "Registered BehaviorTrees:" << std::endl;
54+
for(const std::string& bt_name: factory.registeredBehaviorTrees())
55+
{
56+
std::cout << " - " << bt_name << std::endl;
57+
}
58+
59+
// You can create the MainTree and the subtrees will be added automatically.
60+
std::cout << "----- MainTree tick ----" << std::endl;
61+
auto main_tree = factory.createdTree("MainTree");
62+
main_tree.tickRoot();
63+
64+
// ... or you can create only one of the subtree
65+
std::cout << "----- SubA tick ----" << std::endl;
66+
auto subA_tree = factory.createdTree("SubA");
67+
subA_tree.tickRoot();
68+
69+
return 0;
70+
}
71+
/* Expected output:
72+
73+
Registered BehaviorTrees:
74+
- MainTree
75+
- SubA
76+
- SubB
77+
----- MainTree tick ----
78+
Robot says: starting MainTree
79+
Robot says: Executing SubA
80+
Robot says: Executing SubB
81+
----- SubA tick ----
82+
Robot says: Executing SubA
83+
84+
*/

include/behaviortree_cpp_v3/bt_factory.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <algorithm>
2323
#include <set>
2424

25-
2625
#include "behaviortree_cpp_v3/behavior_tree.h"
2726

2827
namespace BT
@@ -197,6 +196,8 @@ class Tree
197196

198197
};
199198

199+
class Parser;
200+
200201
/**
201202
* @brief The BehaviorTreeFactory is used to create instances of a
202203
* TreeNode at run-time.
@@ -270,6 +271,12 @@ class BehaviorTreeFactory
270271
*/
271272
void registerFromROSPlugins();
272273

274+
void registerBehaviorTreeFromFile(const std::string& filename);
275+
276+
void registerBehaviorTreeFromText(const std::string& xml_text);
277+
278+
std::vector<std::string> registeredBehaviorTrees() const;
279+
273280
/**
274281
* @brief instantiateTreeNode creates an instance of a previously registered TreeNode.
275282
*
@@ -374,11 +381,16 @@ class BehaviorTreeFactory
374381
Tree createTreeFromFile(const std::string& file_path,
375382
Blackboard::Ptr blackboard = Blackboard::create());
376383

384+
Tree createdTree(const std::string& tree_name,
385+
Blackboard::Ptr blackboard = Blackboard::create());
386+
377387
private:
378388
std::unordered_map<std::string, NodeBuilder> builders_;
379389
std::unordered_map<std::string, TreeNodeManifest> manifests_;
380390
std::set<std::string> builtin_IDs_;
391+
std::unordered_map<std::string, Any> behavior_tree_definitions_;
381392

393+
std::shared_ptr<BT::Parser> parser_;
382394
// clang-format on
383395
};
384396

include/behaviortree_cpp_v3/bt_parser.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ class Parser
2121
Parser(const Parser& other) = delete;
2222
Parser& operator=(const Parser& other) = delete;
2323

24-
virtual void loadFromFile(const std::string& filename) = 0;
24+
virtual void loadFromFile(const std::string& filename, bool add_includes = true) = 0;
2525

26-
virtual void loadFromText(const std::string& xml_text) = 0;
26+
virtual void loadFromText(const std::string& xml_text, bool add_includes = true) = 0;
2727

28-
virtual Tree instantiateTree(const Blackboard::Ptr &root_blackboard) = 0;
28+
virtual std::vector<std::string> registeredBehaviorTrees() const = 0;
29+
30+
virtual Tree instantiateTree(const Blackboard::Ptr &root_blackboard, std::string tree_name = {}) = 0;
2931
};
3032

3133
}

include/behaviortree_cpp_v3/xml_parsing.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,19 @@ class XMLParser: public Parser
1616
public:
1717
XMLParser(const BehaviorTreeFactory& factory);
1818

19-
~XMLParser();
19+
~XMLParser() override;
2020

2121
XMLParser(const XMLParser& other) = delete;
2222
XMLParser& operator=(const XMLParser& other) = delete;
2323

24-
void loadFromFile(const std::string& filename) override;
24+
void loadFromFile(const std::string& filename, bool add_includes = true) override;
2525

26-
void loadFromText(const std::string& xml_text) override;
26+
void loadFromText(const std::string& xml_text, bool add_includes = true) override;
2727

28-
Tree instantiateTree(const Blackboard::Ptr &root_blackboard) override;
28+
std::vector<std::string> registeredBehaviorTrees() const override;
29+
30+
Tree instantiateTree(const Blackboard::Ptr &root_blackboard,
31+
std::string main_tree_to_execute = {}) override;
2932

3033
private:
3134

src/bt_factory.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1111
*/
1212

13+
#include <fstream>
1314
#include "behaviortree_cpp_v3/bt_factory.h"
1415
#include "behaviortree_cpp_v3/utils/shared_library.h"
1516
#include "behaviortree_cpp_v3/xml_parsing.h"
17+
#include "private/tinyxml2.h"
1618

1719
#ifdef USING_ROS
1820
#include "filesystem/path.h"
@@ -23,6 +25,7 @@ namespace BT
2325
{
2426
BehaviorTreeFactory::BehaviorTreeFactory()
2527
{
28+
parser_ = std::make_shared<XMLParser>(*this);
2629
registerNodeType<FallbackNode>("Fallback");
2730
registerNodeType<SequenceNode>("Sequence");
2831
registerNodeType<SequenceStarNode>("SequenceStar");
@@ -212,6 +215,22 @@ void BehaviorTreeFactory::registerFromROSPlugins()
212215
}
213216
#endif
214217

218+
219+
void BehaviorTreeFactory::registerBehaviorTreeFromFile(const std::string &filename)
220+
{
221+
parser_->loadFromFile(filename);
222+
}
223+
224+
void BehaviorTreeFactory::registerBehaviorTreeFromText(const std::string &xml_text)
225+
{
226+
parser_->loadFromText(xml_text);
227+
}
228+
229+
std::vector<std::string> BehaviorTreeFactory::registeredBehaviorTrees() const
230+
{
231+
return parser_->registeredBehaviorTrees();
232+
}
233+
215234
std::unique_ptr<TreeNode> BehaviorTreeFactory::instantiateTreeNode(
216235
const std::string& name,
217236
const std::string& ID,
@@ -268,6 +287,13 @@ Tree BehaviorTreeFactory::createTreeFromFile(const std::string &file_path,
268287
return tree;
269288
}
270289

290+
Tree BehaviorTreeFactory::createdTree(const std::string &tree_name, Blackboard::Ptr blackboard)
291+
{
292+
auto tree = parser_->instantiateTree(blackboard, tree_name);
293+
tree.manifests = this->manifests();
294+
return tree;
295+
}
296+
271297
Tree::~Tree()
272298
{
273299
haltTree();

0 commit comments

Comments
 (0)