py_trees.decorators module
Decorate your children. They make great furniture pieces.
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:
Decorators (Hats)
Decorators with specific functionality:
And the X is Y family:
Decorators for Blocking Behaviours
It is worth making a note of the effect of decorators on
blocking behaviours, i.e. those that return RUNNING
before eventually returning SUCCESS
or FAILURE
.
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 often surprising (to the user) but
is necessary to ensure the underlying child isn’t left in a dangling state (i.e.
RUNNING
) as subsequent ticks move on to other
parts of the tree.
A better approach in this case is to build a non-blocking variant or a combination of non-blocking behaviors that handle construction, monitoring and destruction of the activity represented by the original blocking behaviour.
- class py_trees.decorators.Condition(name: str, child: Behaviour, status: Status)
Bases:
Decorator
A blocking conditional decorator.
Encapsulates a behaviour and wait for it’s status to flip to the desired state. This behaviour will tick with
RUNNING
while waiting andSUCCESS
when the flip occurs.
- class py_trees.decorators.Count(name: str, child: Behaviour)
Bases:
Decorator
Count the number of times it’s child has been ticked.
This increments counters tracking the total number of times it’s child has been ticked as well as the number of times it has landed in each respective state.
It will always re-zero counters on
setup()
.- Attributes:
total_tick_count: number of ticks in total running_count: number of ticks resulting in this state success_count: number of ticks resulting in this state failure_count: number of ticks resulting in this state interrupt_count: number of times a higher priority has interrupted
- setup(**kwargs: int) None
Reset the counters.
- class py_trees.decorators.Decorator(name: str, child: Behaviour)
Bases:
Behaviour
Parent class for decorating a child/subtree with some additional logic.
- Args:
child: the child to be decorated name: the decorator name
- Raises:
TypeError: if the child is not an instance of
Behaviour
- stop(new_status: Status) None
Check if the child is running (dangling) and stop it if that is the case.
- Args:
new_status (
Status
): the behaviour is transitioning to this new status
- class py_trees.decorators.EternalGuard(name: str, child: Behaviour, condition: Any, blackboard_keys: List[str] | Set[str] | None = None)
Bases:
Decorator
Continuously guard (with a condition) the execution of a child/subtree.
The eternal guard checks a condition prior to every tick of the child/subtree. If at any time the condition fails, the child/subtree is invalidated.
Note
This is stronger than a conventional guard which is only checked once before any and all ticking of what follows the guard.
- Args:
child: the child behaviour or subtree condition: a functional check that determines execution or not of the subtree blackboard_keys: provide read access for the conditional function to these keys name: the decorator name
- Examples:
Simple conditional function returning True/False:
def check(): return True foo = py_trees.behaviours.Foo() eternal_guard = py_trees.decorators.EternalGuard( name="Eternal Guard", condition=check, child=foo )
Simple conditional function returning SUCCESS/FAILURE:
def check(): return py_trees.common.Status.SUCCESS foo = py_trees.behaviours.Foo() eternal_guard = py_trees.decorators.EternalGuard( name="Eternal Guard", condition=check, child=foo )
Conditional function that makes checks against data on the blackboard (the blackboard client with pre-configured access is provided by the EternalGuard instance):
def check(blackboard): return blackboard.velocity > 3.0 foo = py_trees.behaviours.Foo() eternal_guard = py_trees.decorators.EternalGuard( name="Eternal Guard", condition=check, blackboard_keys={"velocity"}, child=foo )
See also
py-trees-demo-eternal-guard for an alternative means of implementing the eternal guard concept using sequences without memory.
- class py_trees.decorators.FailureIsRunning(name: str, child: Behaviour)
Bases:
Decorator
Dont stop running.
- class py_trees.decorators.FailureIsSuccess(name: str, child: Behaviour)
Bases:
Decorator
Be positive, always succeed.
- class py_trees.decorators.Inverter(name: str, child: Behaviour)
Bases:
Decorator
A decorator that inverts the result of a class’s update function.
- class py_trees.decorators.OneShot(name: str, child: Behaviour, policy: OneShotPolicy)
Bases:
Decorator
A decorator that implements the oneshot pattern.
This decorator ensures that the underlying child is ticked through to completion just once and while doing so, will return with the same status as it’s child. Thereafter it will return with the final status of the underlying child.
Completion status is determined by the policy given on construction.
With policy
ON_SUCCESSFUL_COMPLETION
, the oneshot will activate only when the underlying child returnsSUCCESS
(i.e. it permits retries).With policy
ON_COMPLETION
, the oneshot will activate when the child returnsSUCCESS
||FAILURE
.
See also
- terminate(new_status: Status) None
Prevent further entry if finishing with
SUCCESS
.This uses a flag to register that the behaviour has gone through to completion. In future ticks, it will block entry to the child and just return the original status result.
- class py_trees.decorators.PassThrough(name: str, child: Behaviour)
Bases:
Decorator
This decorator simply reflects the child’s current status.
This behaviour is useful for debugging or visualisation purposes.
- class py_trees.decorators.Repeat(name: str, child: Behaviour, num_success: int)
Bases:
Decorator
Repeat.
SUCCESS
isRUNNING
up to a specified number at which point this decorator returnsSUCCESS
.- Args:
child: the child behaviour or subtree num_success: repeat this many times (-1 to repeat indefinitely) name: the decorator name
- initialise() None
Reset the currently registered number of successes.
- class py_trees.decorators.Retry(name: str, child: Behaviour, num_failures: int)
Bases:
Decorator
Keep trying, pastafarianism is within reach.
FAILURE
isRUNNING
up to a specified number of attempts.- Args:
child: the child behaviour or subtree num_failures: maximum number of permitted failures name: the decorator name
- initialise() None
Reset the currently registered number of attempts.
- class py_trees.decorators.RunningIsFailure(name: str, child: Behaviour)
Bases:
Decorator
Got to be snappy! We want results…yesterday.
- class py_trees.decorators.RunningIsSuccess(name: str, child: Behaviour)
Bases:
Decorator
Don’t hang around…
- class py_trees.decorators.StatusToBlackboard(name: str, child: Behaviour, variable_name: str)
Bases:
Decorator
Reflect the status of the decorator’s child to the blackboard.
- Args:
child: the child behaviour or subtree variable_name: name of the blackboard variable, may be nested, e.g. foo.status name: the decorator name
- class py_trees.decorators.SuccessIsFailure(name: str, child: Behaviour)
Bases:
Decorator
Be depressed, always fail.
- class py_trees.decorators.SuccessIsRunning(name: str, child: Behaviour)
Bases:
Decorator
The tickling never ends…
- class py_trees.decorators.Timeout(name: str, child: Behaviour, duration: float = 5.0)
Bases:
Decorator
Executes a child/subtree with a timeout.
A decorator that applies a timeout pattern to an existing behaviour. If the timeout is reached, the encapsulated behaviour’s
stop()
method is called with statusFAILURE
otherwise it will simply directly tick and return with the same status as that of it’s encapsulated behaviour.- initialise() None
Reset the feedback message and finish time on behaviour entry.