Decorators¶
Decorators are behaviours that manage a single child and provide common modifications to their underlying child behaviour (e.g. inverting the result). That is, they provide a means for behaviours to wear different ‘hats’ and this combinatorially expands the capabilities of your behaviour library.

An example:
![digraph life {
graph [fontname="times-roman"];
node [fontname="times-roman"];
edge [fontname="times-roman"];
Life [fillcolor=orange, fontcolor=black, fontsize=11, shape=box, style=filled];
Inverter [fillcolor=ghostwhite, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Life -> Inverter;
"Busy?" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Inverter -> "Busy?";
Timeout [fillcolor=ghostwhite, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Life -> Timeout;
"Have a Beer!" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Timeout -> "Have a Beer!";
}](_images/graphviz-ce09d937cafde941a1e3b40955a1b909b325f2a1.png)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import py_trees.decorators
import py_trees.display
if __name__ == '__main__':
root = py_trees.composites.Sequence(name="Life")
timeout = py_trees.decorators.Timeout(
name="Timeout",
child=py_trees.behaviours.Success(name="Have a Beer!")
)
failure_is_success = py_trees.decorators.Inverter(
name="Inverter",
child=py_trees.behaviours.Success(name="Busy?")
)
root.add_children([failure_is_success, timeout])
py_trees.display.render_dot_tree(root)
|
Decorators (Hats)
Decorators with very specific functionality:
py_trees.decorators.Condition
py_trees.decorators.EternalGuard
py_trees.decorators.Inverter
py_trees.decorators.OneShot
py_trees.decorators.StatusToBlackboard
py_trees.decorators.Timeout
And the X is Y family:
py_trees.decorators.FailureIsRunning
py_trees.decorators.FailureIsSuccess
py_trees.decorators.RunningIsFailure
py_trees.decorators.RunningIsSuccess
py_trees.decorators.SuccessIsFailure
py_trees.decorators.SuccessIsRunning
Decorators for Blocking Behaviours
It is worth making a note of the effect of decorators on
behaviours that return RUNNING
for
some time before finally returning SUCCESS
or FAILURE
(blocking behaviours) since
the results are often at first, surprising.
A decorator, such as py_trees.decorators.RunningIsSuccess()
on
a blocking behaviour will immediately terminate the underlying child and
re-intialise on it’s next tick. This is necessary to ensure the underlying
child isn’t left in a dangling state (i.e.
RUNNING
), but is often not what is being
sought.
The typical use case being attempted is to convert the blocking
behaviour into a non-blocking behaviour. If the underlying child has no
state being modified in either the initialise()
or terminate()
methods (e.g. machinery is
entirely launched at init or setup time), then conversion to a non-blocking
representative of the original succeeds. Otherwise, another approach is
needed. Usually this entails writing a non-blocking counterpart, or
combination of behaviours to affect the non-blocking characteristics.