Skip to content

Commit 0402b7b

Browse files
committed
back compatible API change to improve the wrapping of legacy code (issue #15)
Eventually, SimpleAction, SimpleDecorators and SimpleCondition can use blackboard and NodeParameters too.
1 parent fcd0d1e commit 0402b7b

File tree

10 files changed

+142
-21
lines changed

10 files changed

+142
-21
lines changed

examples/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ target_link_libraries(t04_blackboard movebase_node ${BEHAVIOR_TREE_LIBRARY} )
2525

2626
add_executable(t05_crossdoor t05_crossdoor.cpp )
2727
target_link_libraries(t05_crossdoor crossdoor_nodes ${BEHAVIOR_TREE_LIBRARY} )
28+
29+
add_executable(t06_wrap_legacy t06_wrap_legacy.cpp )
30+
target_link_libraries(t06_wrap_legacy crossdoor_nodes ${BEHAVIOR_TREE_LIBRARY} )

examples/t06_wrap_legacy.cpp

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#include "behaviortree_cpp/xml_parsing.h"
2+
#include "behaviortree_cpp/loggers/bt_cout_logger.h"
3+
#include "behaviortree_cpp/blackboard/blackboard_local.h"
4+
5+
6+
/** In this tutorial we will see how to wrap legacy code into a
7+
* BehaviorTree in a non-intrusive way, i.e. without modifying the
8+
* original class
9+
*/
10+
11+
// clang-format off
12+
const std::string xml_text = R"(
13+
14+
<root main_tree_to_execute = "MainTree" >
15+
<BehaviorTree ID="MainTree">
16+
<SequenceStar name="root">
17+
<MoveTo goal="-1;3;0.5" />
18+
<MoveTo goal="${myGoal}" />
19+
</SequenceStar>
20+
</BehaviorTree>
21+
</root>
22+
)";
23+
24+
// clang-format on
25+
26+
// This is my custom type.
27+
// By default, we don't know how to read this from a NodeParameter.
28+
struct Point3D { double x,y,z; };
29+
30+
// We want to create an ActionNode that calls the method MyLegacyMoveTo::go
31+
class MyLegacyMoveTo
32+
{
33+
public:
34+
bool go(Point3D goal)
35+
{
36+
printf("Going to: %f %f %f\n", goal.x, goal.y, goal.z);
37+
return true; // true means success in my legacy code
38+
}
39+
};
40+
41+
// Similarly to the previous tutorials, we need to implement this parsing method,
42+
// deplaring a specialization of BT::convertFromString
43+
namespace BT
44+
{
45+
template <> Point3D convertFromString(const StringView& key)
46+
{
47+
// three real numbers separated by semicolons
48+
auto parts = BT::splitString(key, ';');
49+
if (parts.size() != 3)
50+
{
51+
throw std::runtime_error("invalid input)");
52+
}
53+
else
54+
{
55+
Point3D output;
56+
output.x = convertFromString<double>(parts[0]);
57+
output.y = convertFromString<double>(parts[1]);
58+
output.z = convertFromString<double>(parts[2]);
59+
return output;
60+
}
61+
}
62+
}
63+
64+
65+
int main()
66+
{
67+
using namespace BT;
68+
69+
MyLegacyMoveTo move_to;
70+
71+
// Here we use a lambda that captures the reference of move_to
72+
auto MoveToWrapperWithLambda = [&move_to](TreeNode& parent_node) -> NodeStatus
73+
{
74+
Point3D goal;
75+
// thanks to paren_node, you can access easily the NodeParameters and the blackboard
76+
parent_node.getParam("goal", goal);
77+
78+
// you can write and read the blabkcoard if you like
79+
//parent_node.blackboard() ....
80+
81+
bool res = move_to.go( goal );
82+
// convert bool to NodeStatus
83+
return res ? NodeStatus::SUCCESS : NodeStatus::FAILURE;
84+
};
85+
86+
BehaviorTreeFactory factory;
87+
// Regoister the lambda with BehaviorTreeFactory::registerSimpleAction
88+
factory.registerSimpleAction("MoveTo", MoveToWrapperWithLambda);
89+
90+
auto blackboard = Blackboard::create<BlackboardLocal>();
91+
auto tree = buildTreeFromText(factory, xml_text, blackboard);
92+
93+
// We set the entry "myGoal" in the blackboard.
94+
Point3D my_goal = {3,4,5};
95+
blackboard->set("myGoal", my_goal);
96+
97+
NodeStatus status = NodeStatus::RUNNING;
98+
while (status == NodeStatus::RUNNING)
99+
{
100+
status = tree.root_node->executeTick();
101+
}
102+
return 0;
103+
}
104+
105+
/* Expected output:
106+
107+
Going to: -1.000000 3.000000 0.500000
108+
Going to: 3.000000 4.000000 5.000000
109+
110+
The first MoveTo read the parameter from the string "-1;3;0.5"
111+
whilst the second from the blackboard, that contains a copy of the Point3D my_goal.
112+
113+
*/

include/behaviortree_cpp/action_node.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ class SimpleActionNode : public ActionNodeBase
5252
typedef std::function<NodeStatus(TreeNode&)> TickFunctor;
5353

5454
// Constructor: you must provide the function to call when tick() is invoked
55-
SimpleActionNode(const std::string& name, TickFunctor tick_functor);
55+
SimpleActionNode(const std::string& name, TickFunctor tick_functor,
56+
const NodeParameters &params = NodeParameters());
5657

5758
~SimpleActionNode() override = default;
5859

include/behaviortree_cpp/condition_node.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ class SimpleConditionNode : public ConditionNode
5151
typedef std::function<NodeStatus(TreeNode&)> TickFunctor;
5252

5353
// Constructor: you must provide the function to call when tick() is invoked
54-
SimpleConditionNode(const std::string& name, TickFunctor tick_functor);
54+
SimpleConditionNode(const std::string& name, TickFunctor tick_functor,
55+
const NodeParameters& params = NodeParameters());
5556

5657
~SimpleConditionNode() override = default;
5758

include/behaviortree_cpp/decorator_node.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ class SimpleDecoratorNode : public DecoratorNode
5050
typedef std::function<NodeStatus(NodeStatus, TreeNode&)> TickFunctor;
5151

5252
// Constructor: you must provide the function to call when tick() is invoked
53-
SimpleDecoratorNode(const std::string& name, TickFunctor tick_functor);
53+
SimpleDecoratorNode(const std::string& name, TickFunctor tick_functor,
54+
const NodeParameters& params = NodeParameters());
5455

5556
~SimpleDecoratorNode() override = default;
5657

include/behaviortree_cpp/tree_node.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,6 @@ class TreeNode
103103
/// creation of the TreeNode instance.
104104
const NodeParameters& initializationParameters() const;
105105

106-
protected:
107-
/// Method to be implemented by the user
108-
virtual BT::NodeStatus tick() = 0;
109-
110106
/** Get a parameter from the passed NodeParameters and convert it to type T.
111107
*/
112108
template <typename T>
@@ -146,8 +142,7 @@ class TreeNode
146142
bool found = bb_->get(stripped_key, destination);
147143
return found;
148144
}
149-
else
150-
{
145+
else{
151146
destination = convertFromString<T>(str.c_str());
152147
return true;
153148
}
@@ -159,6 +154,10 @@ class TreeNode
159154
}
160155
}
161156

157+
protected:
158+
/// Method to be implemented by the user
159+
virtual BT::NodeStatus tick() = 0;
160+
162161
/// registrationName() is set by the BehaviorTreeFactory
163162
void setRegistrationName(const std::string& registration_name);
164163

src/action_node.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ NodeStatus ActionNodeBase::executeTick()
3434
//-------------------------------------------------------
3535

3636
SimpleActionNode::SimpleActionNode(const std::string& name,
37-
SimpleActionNode::TickFunctor tick_functor)
38-
: ActionNodeBase(name, NodeParameters()), tick_functor_(std::move(tick_functor))
37+
SimpleActionNode::TickFunctor tick_functor,
38+
const NodeParameters& params)
39+
: ActionNodeBase(name, params), tick_functor_(std::move(tick_functor))
3940
{
4041
}
4142

src/bt_factory.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ void BehaviorTreeFactory::registerBuilder(const std::string& ID, NodeBuilder bui
6666
void BehaviorTreeFactory::registerSimpleCondition(
6767
const std::string& ID, const SimpleConditionNode::TickFunctor& tick_functor)
6868
{
69-
NodeBuilder builder = [tick_functor, ID](const std::string& name, const NodeParameters&) {
70-
return std::unique_ptr<TreeNode>(new SimpleConditionNode(name, tick_functor));
69+
NodeBuilder builder = [tick_functor, ID](const std::string& name, const NodeParameters& params) {
70+
return std::unique_ptr<TreeNode>(new SimpleConditionNode(name, tick_functor, params));
7171
};
7272

7373
registerBuilder(ID, builder);
@@ -77,8 +77,8 @@ void BehaviorTreeFactory::registerSimpleCondition(
7777
void BehaviorTreeFactory::registerSimpleAction(const std::string& ID,
7878
const SimpleActionNode::TickFunctor& tick_functor)
7979
{
80-
NodeBuilder builder = [tick_functor, ID](const std::string& name, const NodeParameters&) {
81-
return std::unique_ptr<TreeNode>(new SimpleActionNode(name, tick_functor));
80+
NodeBuilder builder = [tick_functor, ID](const std::string& name, const NodeParameters& params) {
81+
return std::unique_ptr<TreeNode>(new SimpleActionNode(name, tick_functor, params));
8282
};
8383

8484
registerBuilder(ID, builder);
@@ -88,8 +88,8 @@ void BehaviorTreeFactory::registerSimpleAction(const std::string& ID,
8888
void BehaviorTreeFactory::registerSimpleDecorator(
8989
const std::string& ID, const SimpleDecoratorNode::TickFunctor& tick_functor)
9090
{
91-
NodeBuilder builder = [tick_functor, ID](const std::string& name, const NodeParameters&) {
92-
return std::unique_ptr<TreeNode>(new SimpleDecoratorNode(name, tick_functor));
91+
NodeBuilder builder = [tick_functor, ID](const std::string& name, const NodeParameters& params) {
92+
return std::unique_ptr<TreeNode>(new SimpleDecoratorNode(name, tick_functor, params));
9393
};
9494

9595
registerBuilder(ID, builder);

src/condition_node.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ void ConditionNode::halt()
2424
{
2525
}
2626

27-
SimpleConditionNode::SimpleConditionNode(const std::string& name, TickFunctor tick_functor)
28-
: ConditionNode(name, NodeParameters()), tick_functor_(std::move(tick_functor))
27+
SimpleConditionNode::SimpleConditionNode(const std::string& name, TickFunctor tick_functor,
28+
const NodeParameters &params)
29+
: ConditionNode(name, params), tick_functor_(std::move(tick_functor))
2930
{
3031
}
3132

src/decorator_node.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ void DecoratorNode::haltChild()
5656
}
5757
}
5858

59-
SimpleDecoratorNode::SimpleDecoratorNode(const std::string& name, TickFunctor tick_functor)
60-
: DecoratorNode(name, NodeParameters()), tick_functor_(std::move(tick_functor))
59+
SimpleDecoratorNode::SimpleDecoratorNode(const std::string& name, TickFunctor tick_functor,
60+
const NodeParameters &params)
61+
: DecoratorNode(name, params), tick_functor_(std::move(tick_functor))
6162
{
6263
}
6364

0 commit comments

Comments
 (0)