@@ -35,12 +35,8 @@ which child should be ticked next or will return a result itself.
3535
3636__ ControlNodes__ are nodes which can have 1 to N children. Once a tick
3737is 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.
4038
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.
39+ __ DecoratorNodes__ can have only a single child.
4440
4541__ ActionNodes__ are leaves and do not have children. The user should implement
4642their own ActionNodes that perform the actual task.
@@ -51,15 +47,15 @@ alter the state of the system.
5147
5248![ UML hierarchy] ( images/TypeHierarchy.png )
5349
54- !!! warning
55- Actions and Conditions differ only in terms of __ semantic__ , the C++
56- framework can not enforce it unfortunately .
50+ !!! note
51+ Actions and Conditions differ only in terms of __ semantic__ .
52+ From an implementation point of view they are the same .
5753
5854## Learn by example
5955
60- To better understand how a BehaviorTree works let's focus on some practical
56+ To better understand how a BehaviorTrees work let's focus on some practical
6157examples. For the sake of simplicity we will not take into account what happens
62- when an action return RUNNING.
58+ when an action returns RUNNING.
6359
6460We will assume that each Action is executed atomically and synchronously.
6561In future sections we will more thoughtfully analyze asynchronous actions.
@@ -80,22 +76,43 @@ A Sequence works as described next:
8076- If a child returns FAILURE, then no more children are ticked and the Sequence returns FAILURE.
8177- If all the children return SUCCESS, then the Fallback returns SUCCESS too.
8278
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.
79+ ??? warning "Exercise: find the bug! Expand to read the answer."
80+ If the action __ GrabBeer__ fails, the door of the
81+ fridge would remain opened, since the last action __ CloseDoor__ is skipped.
8582
86- Let's take into accound another example:
8783
88- ![ Simple Sequence: Enter Room ] ( images/Sequence2.png )
84+ ### Decorators
8985
90- In this case __ Negation__ is a [ DecoratorNode] ( DecoratorNode.md ) that inverts
91- the result returned by its child.
86+ The goal of a [ DecoratorNode] ( DecoratorNode.md ) is either to transform the result it received
87+ from the child, to terminate the child,
88+ or repeat ticking of the child, depending on the type of Decorator.
9289
93- This means that a Negation followed by the ConditionNode called
94- __ DoorOpen__ is equialent to "is the door closed?".
90+ You can create your own Decorators too.
9591
96- As a result, the branch on the right side means:
92+ ![ Simple Decorator: Enter Room ] ( images/DecoratorEnterRoom.png )
9793
98- "If the door is closed, then open it".
94+ The node __ Negation__ is a Decorator that inverts
95+ the result returned by its child; Negation followed by the node called
96+ __ DoorOpen__ is therefore equivalent to
97+
98+ "Is the door closed?".
99+
100+ The node __ Retry__ will repeat ticking the child up to N times (3 in this case)
101+ if the child returns FAILURE.
102+
103+ __ Apparently__ , the branch on the right side means:
104+
105+ If the door is closed, then try to open it.
106+ Try up to 3 times, otherwise give up and return FAILURE.
107+
108+
109+ __ But__ there is an error. Can you find it?
110+
111+ ??? warning "Exercise: find the bug! Expand to read the answer."
112+ If __ DoorOpen__ returns FAILURE, we have the desired behaviour.
113+ But if it returns SUCCESS, the left branch fails and the entire Sequence
114+ is interrupted.
115+
99116
100117### Fallback
101118
@@ -111,22 +128,33 @@ In short, it ticks the children in order, as usual from left to right and:
111128
112129In the next example, you can see how Sequence and Fallbacks can be combined:
113130
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".
118131
119132![ FallbackNodes] ( images/FallbackBasic.png )
120133
134+
135+ > In the door open?
136+ >
137+ > I not, try to open the door.
138+ >
139+ > Otherwise, if you have a key, unlock and open the door.
140+ >
141+ > Otherwise, smash the door.
142+ >
143+ > If any of these actions succeeded, then enter the room.
144+
121145### "Fetch me a beer" revisited
122146
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.
147+ We can now improve the "Fetch Me a Beer" example, which leaves the door open
148+ if the beer was not there.
149+
150+ We use the color "green" to represent nodes which will return
151+ SUCCESS and "red" for those which return FAILURE. Black nodes are never executed.
152+
153+ ![ FetchBeer failure] ( images/FetchBeerFails.png )
125154
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.
128155
129- The action __ GrabBeer__ will always fail.
156+ Let's create an alternative tree that closes the door even when __ GrabBeer__
157+ returns FAILURE.
130158
131159
132160![ FetchBeer failure] ( images/FetchBeer.png )
@@ -138,7 +166,7 @@ Both the trees will close the door of the fridge, eventually, but:
138166- the tree on the __ right__ side will return SUCCESS if the beer was there,
139167FAILURE otherwise.
140168
141- We can easily double-check what happen if __ GrabBeer__ returns SUCCESS.
169+ We can easily double-check that everything works as usual if __ GrabBeer__ returns SUCCESS.
142170
143171![ FetchBeer success] ( images/FetchBeer2.png )
144172
0 commit comments