Skip to content

Commit ed7763e

Browse files
committed
added new tutorial
1 parent 5874eb0 commit ed7763e

File tree

5 files changed

+167
-2
lines changed

5 files changed

+167
-2
lines changed
16.2 KB
Loading
22.7 KB
Loading
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
---
2+
sidebar_position: 16
3+
sidebar_label: 16. The global blackboard idiom
4+
---
5+
6+
# Why a "global blackboard"
7+
8+
:::note
9+
Introduced in Bt.CPP 4.6.0
10+
:::
11+
12+
As described in earlier tutorials, BT.CPP insists on the importance of having "scoped blackboards", to
13+
isolate each subtree as they were independent functions / routines, in a programming language.
14+
15+
Still, there are cases where it could be desirable to have a truly "global" blackboard, that can be
16+
accessed from every Subtree directly, without remapping.
17+
18+
This may make sense for:
19+
20+
- Singletons and global objects that can't be shared as described in [Tutorial 8](tutorial-basics/tutorial_08_additional_args.md)
21+
- Global states of the robot.
22+
- Data that is written / read outside the Behavior Tree, i.e. in the main loop executing the tick.
23+
24+
Additionally, since the blackboard is a generic key/value storage, where the value can have **any** type,
25+
it is a perfect data structure to implement what is known in the literature as "World Model",
26+
i.e. data that represents the state of the world, and that the Nodes in the tree may need to access.
27+
28+
29+
Consider a simple Tree with two subtrees, like this:
30+
31+
![tree_hierarchy.png](images/tree_hierarchy.png)
32+
33+
Each one of the 3 Subtree has its own blackboard; the parent.child relationship between these
34+
blackboards is exactly the same as the BehaviorTrees, i.e. BB1 is the parent of BB2 and BB3.
35+
36+
The lifecycle of these individual blackboards is coupled with their respective Subtree.
37+
38+
We will can introduce easily an external "global blackboard" like this:
39+
40+
```cpp
41+
auto global_bb = BT::Blackboard::create();
42+
auto maintree_bb = BT::Blackboard::create(global_bb);
43+
auto tree = factory.createTree("MainTree", maintree_bb);
44+
```
45+
46+
This will create the following hierarchy, among blackboards:
47+
48+
![bb_hierarchy.png](images/bb_hierarchy.png)
49+
50+
The instance `global_bb` lives "outside" the behavior tree and will persist if the
51+
object `tree` is destroyed.
52+
53+
Furthermore, it can be easily accessed using `set` and `get` methods.
54+
55+
## How to access the top-level blackboard from the tree
56+
57+
We call a blackboard the "top-level" one, when it is the root or the hierarchy.
58+
59+
In the previous tutorials, that would be the one inside "MainTree", but when the code above
60+
is used, `global_bb` will become the top-level one.
61+
62+
Since version **4.6** of BT.CPP, a new syntax was introduced to access the top-level
63+
blackboard **without remapping**.
64+
65+
Simply, add the prefix "@" to the name of the entry. For instance:
66+
67+
68+
```xml
69+
<PrintNumber val="{@value}" />
70+
```
71+
72+
This code will always search the entry `value` in the top-level blackboard, instead of the local one.
73+
74+
## Full example
75+
76+
Consider this tree:
77+
78+
```xml
79+
<BehaviorTree ID="MainTree">
80+
<Sequence>
81+
<PrintNumber name="main_print" val="{@value}" />
82+
<SubTree ID="MySub"/>
83+
</Sequence>
84+
</BehaviorTree>
85+
86+
<BehaviorTree ID="MySub">
87+
<Sequence>
88+
<PrintNumber name="sub_print" val="{@value}" />
89+
<Script code="@value_sqr := @value * @value" />
90+
</Sequence>
91+
</BehaviorTree>
92+
```
93+
94+
And the C++ code:
95+
96+
```cpp
97+
class PrintNumber : public BT::SyncActionNode
98+
{
99+
public:
100+
PrintNumber(const std::string& name, const BT::NodeConfig& config)
101+
: BT::SyncActionNode(name, config)
102+
{}
103+
104+
NodeStatus tick() override
105+
{
106+
const int val = getInput<int>("val").value();
107+
std::cout << "[" << name() << "] val: " << val << std::endl;
108+
return NodeStatus::SUCCESS;
109+
}
110+
111+
static BT::PortsList providedPorts()
112+
{
113+
return { BT::InputPort<int>("val") };
114+
}
115+
};
116+
117+
int main()
118+
{
119+
BehaviorTreeFactory factory;
120+
factory.registerNodeType<PrintNumber>("PrintNumber");
121+
factory.registerBehaviorTreeFromText(xml_main);
122+
123+
// No one will take the ownership of this blackboard
124+
auto global_bb = BT::Blackboard::create();
125+
// "MainTree" will own maintree_bb
126+
auto maintree_bb = BT::Blackboard::create(global_bb);
127+
auto tree = factory.createTree("MainTree", maintree_bb);
128+
129+
// we can interact directly with global_bb
130+
for(int i = 1; i <= 3; i++)
131+
{
132+
// write the entry "value"
133+
global_bb->set("value", i);
134+
// tick the tree
135+
tree.tickOnce();
136+
// read the entry "value_sqr"
137+
auto value_sqr = global_bb->get<int>("value_sqr");
138+
// print
139+
std::cout << "[While loop] value: " << i
140+
<< " value_sqr: " << value_sqr << "\n\n";
141+
}
142+
return 0;
143+
}
144+
```
145+
146+
Output:
147+
```
148+
[main_print] val: 1
149+
[sub_print] val: 1
150+
[While loop] value: 1 value_sqr: 1
151+
152+
[main_print] val: 2
153+
[sub_print] val: 2
154+
[While loop] value: 2 value_sqr: 4
155+
156+
[main_print] val: 3
157+
[sub_print] val: 3
158+
[While loop] value: 3 value_sqr: 9
159+
```
160+
161+
Notes:
162+
163+
- The prefix "@" works both when used in an InputPort or in the scripting language.
164+
- No remapping is needed in the Subtrees.
165+
- When accessing the blackboard directly in the main loop, no prefix "@" is needed.

docusaurus.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const config = {
4545
lastVersion: 'current',
4646
versions: {
4747
current: {
48-
label: '4.5',
48+
label: '4.6',
4949
},
5050
3.8: {
5151
label: '3.8',

src/pages/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function Home() {
4141
<div className="row align-items-center">
4242
<div className="col col--6">
4343
<div className={clsx(styles.heroText)}>
44-
<h1 className="hero__title ">BehaviorTree.CPP 4.5</h1>
44+
<h1 className="hero__title ">BehaviorTree.CPP 4.6</h1>
4545
<p className="hero__subtitle">
4646
The C++ library to build Behavior Trees.
4747
<br />

0 commit comments

Comments
 (0)