Skip to content

Commit d7a906e

Browse files
author
Davide Faconti
committed
initial documentation
1 parent d0e83de commit d7a906e

15 files changed

+1253
-0
lines changed

docs/02_BT_description.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Introduction to BTs
2+
3+
Unlike a Finite State Machine, a Behaviour Tree is a __tree of hierarchical nodes__
4+
that controls the flow of decision and the execution of "tasks" or, as we
5+
will call them further, "__Actions__".
6+
7+
The __leaves__ of the tree are the actual commands, ie.e the place where
8+
our coordinating component interacts with the rest of the system.
9+
10+
For instance, in a service-oriented architecture, the leaves would contain
11+
the "client" code that triggers an action.
12+
13+
All the other nodes of the tree, those which are not leaves, control the
14+
"flow of execution".
15+
16+
To better understand how this flow takes place , imagine a signal, that we will further
17+
call "__tick__" that is executed at the __root__ of the tree and propagates through
18+
the branches until it reaches a leave.
19+
20+
The result of a tick can be either:
21+
22+
- __SUCCESS__
23+
- __FAILURE__
24+
- __RUNNING__
25+
26+
The first two, as their names suggest, inform their parent that their operation
27+
was a success or a failure.
28+
The latter usually means that the execution of the TreeNode is not completed
29+
and it needs more time to return a valid result.
30+
31+
The result of a node is propagated back to the parent, that will decide
32+
which child should be ticked next or will return a result itself.
33+
34+
## Types of nodes
35+
36+
__ControlNodes__ are nodes which can have 1 to N children. Once a tick
37+
is received, this tick may be propagated to one or more of the children.
38+
It must be noted that children are always __ordered__, but it is up to the
39+
type of control node to decide if they are ticked in the given order.
40+
41+
__DecoratorNodes__ can have only a single child. Their function is either
42+
to transform the result they receive from the child, to terminate the child,
43+
or repeat processing of the child, depending on the type of decorator.
44+
45+
__ActionNodes__ are leaves and do not have children. The user should implement
46+
their own ActionNodes that perform the actual task.
47+
48+
__ConditionNodes__ are equivalent to ActionNodes, with the exeption that
49+
they are alwais aotmic (they should not return RUNNING) and they should not
50+
alter the state of the system.
51+
52+
![UML hierarchy](images/TypeHierarchy.png)
53+
54+
!!! warning
55+
Actions and Conditions differ only in terms of __semantic__, the C++
56+
framework can not enforce it unfortunately.
57+
58+
## Learn by example
59+
60+
To better understand how a BehaviorTree works let's focus on some practical
61+
examples. For the sake of simplicity we will not take into account what happens
62+
when an action return RUNNING.
63+
64+
We will assume that each Action is executed atomically and synchronously.
65+
In future sections we will more thoughtfully analyze asynchronous actions.
66+
67+
### Sequence
68+
69+
Let's illustrate how a BT works using the most basic and frequently used
70+
ControlNode: the [SequenceNode](SequenceNode.md).
71+
72+
![Simple Sequence: fridge](images/SequenceBasic.png)
73+
74+
It is important to notice that the children of a ControlNode are __ordered__.
75+
In this case the order of execution is __from left to right__.
76+
77+
A Sequence works as described next:
78+
79+
- If a child returns SUCCESS, tick the next one.
80+
- If a child returns FAILURE, then no more children are ticked and the Sequence returns FAILURE.
81+
- If all the children return SUCCESS, then the Fallback returns SUCCESS too.
82+
83+
In this particular case, if the action __GrabBeer__ failed, the door of the fridge would
84+
remain opened, since the last action __CloseDoor__ is skipped.
85+
86+
Let's take into accound another example:
87+
88+
![Simple Sequence: Enter Room](images/Sequence2.png)
89+
90+
In this case __Negation__ is a [DecoratorNode](DecoratorNode.md) that inverts
91+
the result returned by its child.
92+
93+
This means that a Negation followed by the ConditionNode called
94+
__DoorOpen__ is equialent to "is the door closed?".
95+
96+
As a result, the branch on the right side means:
97+
98+
"If the door is closed, then open it".
99+
100+
### Fallback
101+
102+
[FallbackNodes](FallbackNode.md), known also as __"Selector"__ in the literature,
103+
Is a node that is used to express, as the name suggests, fallback strategies,
104+
ie. what to do if a child return FAILURE.
105+
106+
In short, it ticks the children in order, as usual from left to right and:
107+
108+
- If a child returns FAILURE, tick the next one.
109+
- If a child returns SUCCESS, then no more children are ticked and the Fallback returns SUCCESS.
110+
- If all the children return FAILURE, then the Fallback returns FAILURE too.
111+
112+
In the next example, you can see how Sequence and Fallbacks can be combined:
113+
114+
"Try to open the door,
115+
otherwise unlock it with a key (if you have it),
116+
otherwise smash it.
117+
If any of these actions succeeded, then enter the room".
118+
119+
![FallbackNodes](images/FallbackBasic.png)
120+
121+
### "Fetch me a beer" revisited
122+
123+
We can now improve the previous example, which attempted to
124+
grab a beer from the fridge but left the door open if the beer was not there.
125+
126+
In the next picture we use the color green to represent nodes which will return
127+
SUCCESS and red for those which return FAILURE.
128+
129+
The action __GrabBeer__ will always fail.
130+
131+
132+
![FetchBeer failure](images/FetchBeer.png)
133+
134+
Both the trees will close the door of the fridge, eventually, but:
135+
136+
- the tree on the __left__ side will always return SUCCESS if we managed to
137+
open and clode the fridge.
138+
- the tree on the __right__ side will return SUCCESS if the beer was there,
139+
FAILURE otherwise.
140+
141+
We can easily double-check what happen if __GrabBeer__ returns SUCCESS.
142+
143+
![FetchBeer success](images/FetchBeer2.png)
144+
145+
146+

docs/images/FallbackBasic.png

9.87 KB
Loading

docs/images/FetchBeer.png

13.1 KB
Loading

docs/images/FetchBeer2.png

10.6 KB
Loading

docs/images/Sequence2.png

8.42 KB
Loading

docs/images/SequenceBasic.png

3.98 KB
Loading

docs/images/TypeHierarchy.png

3.01 KB
Loading

docs/index.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
2+
# Home
3+
4+
## About this library
5+
6+
This __C++__ library provides a framework to create BehaviorTrees.
7+
It was designed to be flexible, easy to use and fast.
8+
9+
Even if out main use-case is __robotics__, you can use this library to build
10+
__AI for games__, or to replace Finite State Machines in you application with a
11+
more intuitive approach that focus on the execution of tasks, rather than a change in state.
12+
13+
__BehaviorTree.CPP__ has many interesting features:
14+
15+
- It makes asynchronous Actions, i.e. non-blocking, a first-class citizen.
16+
- It allows the creation of trees at run-time, using a textual representation (XML).
17+
- You can link staticaly you custom TreeNodes or convert them into plugins
18+
which are loaded at run-time.
19+
- It includes a __logging/profiling__ infrastructure that allows the user
20+
to visualize, record, replay and analyze state transitions.
21+
22+
## The problem
23+
24+
Many software systems, being robotics a notable example, are inherently
25+
complex.
26+
27+
The usual approach to manage complexity, heterogeneity and scalability is to
28+
use the concept of
29+
[Component Base Software Engineering](https://en.wikipedia.org/wiki/Component-based_software_engineering).
30+
31+
32+
Any existing middleware for robotics took this approach either informally or formally,
33+
being [ROS](www.ros.org), [YARP](www.yarp.it) and
34+
[SmartSoft](http://www.servicerobotik-ulm.de) some notable examples.
35+
36+
A "good" software architecture should have the following characteristics:
37+
38+
- Modularity.
39+
- Reusability.
40+
- Composability.
41+
- Good separation of concerns.
42+
43+
If we don't keep these concepts in mind from the very beginning, we create
44+
software modules/components which are highly coupled to a particular application,
45+
instead of being reusable.
46+
47+
Frequently ,the concern of __Coordination__ is mixed with __Computation__.
48+
In other words, people address the problems of coordinating actions and take decisions
49+
locally.
50+
51+
The business logic becomes spread in many locations and it is hard for the developer
52+
to reason about it and to degub errors in the control flow.
53+
54+
A better solution is to have a strong separation of concern and to centralize
55+
as much as possible the business logic in a single location.
56+
57+
Finite State Machines were created specifically with this goal in mind, but in
58+
the recent years Behavior Trees gained popularity, especially in the game industry.
59+
60+
61+
## What is a Behavior Tree?
62+
63+
A Behavior Tree (__BT__) is a way to structure the switching between different
64+
tasks in an autonomous agent, such as a robot or a virtual entity in a computer game.
65+
66+
BTs are a very efficient way of creating complex systems that are both modular and reactive.
67+
These properties are crucial in many applications, which has led to the spread
68+
of BT from computer game programming to many branches of AI and Robotics.
69+
70+
If you are already familiar with Finite State Machines (__FSM__), you will
71+
easily grasp most of the concepts but, hopefully, you will find that BTs
72+
are more expressive and easier to reason about.
73+
74+
The main advantages of Behavior Trees, when compared to FSMs are:
75+
76+
- __They are intrinsically Hierarchical__: this means that we can _compose_
77+
complex behaviors including entire trees as sub-branches of a bugger one.
78+
For instance, the behavior "Fetch Beer" may reuse in one of its nodes the tree
79+
"Grasp Object".
80+
81+
- __Their graphical representation has a semantic meaning__: it is easier to
82+
"read" a BT and understand the corresponding workflow.
83+
State transitions in FSMs, by comparisons, are harder to understand
84+
both in their textual and graphical representation.
85+
86+
- __They are more expressive__: Ready to use ControlNodes and DecoratorNodes
87+
make possible to express more complex control flows. The use can extend the
88+
"vocabulary" with his/her own custo nodes.
89+

0 commit comments

Comments
 (0)