-
Notifications
You must be signed in to change notification settings - Fork 834
Expand file tree
/
Copy patht08_additional_node_args.cpp
More file actions
136 lines (114 loc) · 3.2 KB
/
t08_additional_node_args.cpp
File metadata and controls
136 lines (114 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "behaviortree_cpp/bt_factory.h"
using namespace BT;
// To demonstrate how to pass arguments by reference, we
// use a simple non-copyable object
class NoCopyObj
{
public:
NoCopyObj(int val) : _value(val)
{}
NoCopyObj(const NoCopyObj&) = delete;
NoCopyObj& operator=(const NoCopyObj&) = delete;
int value()
{
return _value;
}
private:
int _value = 0;
};
/*
* Sometimes, it is convenient to pass additional (static) arguments to a Node.
* If these parameters are known at compilation time or at deployment-time
* and they don't change at run-time, input ports are probably overkill and cumbersome.
*
* This tutorial demonstrates two possible ways to initialize a custom node with
* additional arguments.
*/
// Action_A has a different constructor than the default one.
class Action_A : public SyncActionNode
{
public:
// additional arguments passed to the constructor
Action_A(const std::string& name, const NodeConfig& config, int arg_int,
std::string arg_str, NoCopyObj& nc)
: SyncActionNode(name, config), _arg1(arg_int), _arg2(arg_str), _nc(nc)
{}
NodeStatus tick() override
{
std::cout << name() << ": " << _arg1 << " / " << _arg2 << " / " << _nc.value()
<< std::endl;
return NodeStatus::SUCCESS;
}
static PortsList providedPorts()
{
return {};
}
private:
int _arg1;
std::string _arg2;
NoCopyObj& _nc;
};
// Action_B implements an init(...) method that must be called once at the beginning.
class Action_B : public SyncActionNode
{
public:
Action_B(const std::string& name, const NodeConfig& config)
: SyncActionNode(name, config)
{}
// we want this method to be called ONCE and BEFORE the first tick()
void initialize(int arg_int, std::string arg_str)
{
_arg1 = (arg_int);
_arg2 = (arg_str);
}
NodeStatus tick() override
{
std::cout << name() << ": " << _arg1 << " / " << _arg2 << std::endl;
return NodeStatus::SUCCESS;
}
static PortsList providedPorts()
{
return {};
}
private:
int _arg1;
std::string _arg2;
};
// Simple tree, used to execute once each action.
static const char* xml_text = R"(
<root BTCPP_format="4">
<BehaviorTree>
<Sequence>
<Action_A/>
<Action_B/>
</Sequence>
</BehaviorTree>
</root>
)";
int main()
{
BehaviorTreeFactory factory;
NoCopyObj non_copyable(88);
// Passing the extra parameters to the constructor of Action_A
// note that if you want to pass an object by ref, instead of value
// (copy), you must use std::ref wrapper.
factory.registerNodeType<Action_A>("Action_A", 42, "hello world",
std::ref(non_copyable));
// Action_B will require initialization
factory.registerNodeType<Action_B>("Action_B");
auto tree = factory.createTreeFromText(xml_text);
auto visitor = [](TreeNode* node) {
if(auto action_B_node = dynamic_cast<Action_B*>(node))
{
action_B_node->initialize(69, "interesting_value");
}
};
// apply the visitor to all the nodes of the tree
tree.applyVisitor(visitor);
tree.tickWhileRunning();
/* Expected output:
Action_A: 42 / hello world / 88
Action_B: 69 / interesting_value
*/
return 0;
}