Skip to content

Commit a336668

Browse files
committed
adding article about blackboard access
1 parent d47dff1 commit a336668

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed
51.4 KB
Loading
36.9 KB
Loading

docs/guides/ports_vs_blackboard.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
sidebar_position: 5
3+
---
4+
5+
# Ports VS Blackboard
6+
7+
**BT.CPP** is the only implementation (to our knowledge) of Behavior Tree that
8+
introduces the concept of **Input/Output Ports**, as an alternative to **Blackboards**.
9+
10+
To be more specific, Ports are an interface that adds a level of
11+
indirection and additional semantics to the blackboard.
12+
13+
To understand why using Ports is recommended and using directly the Blackboard
14+
is **discouraged**, we should first understand some of the core principles
15+
of BehaviorTree.CPP.
16+
17+
## Goals of BT.CPP
18+
19+
### Model Driven Development
20+
21+
It is not the purpose of this article to explain what Model Driven Development is.
22+
But, in short, we want to build a "model" of our Nodes, i.e. some kind of meta-information
23+
that tells us how the Node interacts with the rest of the tree.
24+
25+
Models are important both for developers (being self-documenting) and
26+
for external tools, such as visual editors, being Groot2 a notable example,
27+
or static analyzers.
28+
29+
We believe that the **description of the data-flow between Nodes must be part of the model**.
30+
Additionally, we want to clearly express if a blackboard entry is being written (output),
31+
read (input) or both.
32+
33+
Consider this example:
34+
35+
![no_ports](images/no_ports_sequence.png)
36+
37+
In other implementations (or if anybody uses this library inappropriately...) the
38+
only way to know if these two Nodes communicate and depend on each other is either:
39+
40+
- **inspecting the code**: something that we want to avoid.
41+
- or **reading the documentation**: but documentation is not guaranteed to be accurate and up to date.
42+
43+
Instead, if Input/Output ports are part of the model, the intent of the Node and it
44+
relationship with the others become more explicit:
45+
46+
![with_ports](images/with_ports_sequence.png)
47+
48+
### Nodes composibility and Subtree scoping
49+
50+
Ideally, we want to offer a platform that allows Behavior Designers to build trees
51+
(i.e., "compose Nodes") implemented by different vendors / users.
52+
53+
But when the Blackboard is used directly, name-collision will become immediately an issue.
54+
55+
Think about common names such as `goal`, `results`, `target`, `value`, etc.
56+
57+
For instance, the Nodes **GraspObject** and **MoveBase** may be developed by different people
58+
and they both read the entry `target` from the blackboard.
59+
Unfortunately, they have different meanings and the type itself is different:
60+
the former expects a 3D pose, whilst the latter a 2D one.
61+
62+
**Ports** offer one level of indirection, called also "remapping", as explained in
63+
[Tutorial 2](../tutorial-basics/tutorial_02_basic_ports.md).
64+
65+
This means that, no matter which name is used when defining the Port
66+
(that name is "hardcoded" into your C++ implementation),
67+
you can always "remap" it to a different blackboard entry into your XML,
68+
without modifying the source code.
69+
70+
The same is true for Subtrees remapping, explained in [Tutorial 6](../tutorial-basics/tutorial_06_subtree_ports.md).
71+
Being the Blackboard a glorified map of global variables, it scales very poorly.
72+
There is a reason why global variables are a no-no in programming!
73+
74+
Ports remapping offers a solution to this problem.
75+
76+
77+
## Summary: never use the Blackboard directly
78+
79+
You should do this:
80+
81+
```c++
82+
// example code in your tick()
83+
getInput("goal", goal);
84+
setOutput("result", result);
85+
```
86+
87+
and avoid as much as possible this:
88+
89+
```c++
90+
// example code in your tick()
91+
config().blackboard->get("goal", goal);
92+
config().blackboard->set("result", result);
93+
```
94+
95+
Both these codes may technically work, but the latter (direct access to the blackboard)
96+
is considered bad practice and **it is highly discouraged**:
97+
98+
The problems with the 2nd version, i.e. the direct access to the blackboard:
99+
100+
1. Names "goal" and "result" are hard-coded. To change them, you must recompile your application. Port, instead, can be remapped at run-time, modifying only the XML.
101+
102+
2. The only way to know if a Node reads or writes one or more entries of the blackboard,
103+
is by inspecting the code. Up to date documentation is a solution, but the Port model is self-documenting.
104+
105+
3. The `BehaviorTreeFactory` is unaware that those blackboard entries are being accessed.
106+
In contrast, when using Ports, we are able to introspect how ports communicate to each other
107+
and also to check at deployment time if the connection is done correctly.
108+
109+
4. It may not work as expected when using SubTrees.
110+
111+
5. The template specialization `convertFromString()` will not work correctly.
112+
113+
114+

0 commit comments

Comments
 (0)