Module API

py_trees

This is the top-level namespace of the py_trees package.

py_trees.behaviour

The core behaviour template. All behaviours, standalone and composite, inherit from this class.

class py_trees.behaviour.Behaviour(name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Bases: object

Defines the basic properties and methods required of a node in a behaviour tree. When implementing your own behaviour, subclass this class.

Parameters:

name (str) – the behaviour name

Raises:

TypeError – if the provided name is not a string

Variables:
  • id (uuid.UUID) – automagically generated unique identifier for the behaviour
  • name (str) – the behaviour name
  • status (Status) – the behaviour status (INVALID, RUNNING, FAILURE, SUCCESS)
  • parent (Behaviour) – a Composite instance if nested in a tree, otherwise None
  • children ([Behaviour]) – empty for regular behaviours, populated for composites
  • logger (logging.Logger) – a simple logging mechanism
  • feedback_message (str) – a simple message used to notify of significant happenings
  • blackbox_level (BlackBoxLevel) – a helper variable for dot graphs and runtime gui’s to collapse/explode entire subtrees dependent upon the blackbox level.
has_parent_with_instance_type(instance_type)[source]

Moves up through this behaviour’s parents looking for a behaviour with the same instance type as that specified.

Parameters:instance_type (str) – instance type of the parent to match
Returns:whether a parent was found or not
Return type:bool
has_parent_with_name(name)[source]

Searches through this behaviour’s parents, and their parents, looking for a behaviour with the same name as that specified.

Parameters:name (str) – name of the parent to match, can be a regular expression
Returns:whether a parent was found or not
Return type:bool
initialise()[source]

Note

User Customisable Callback

Subclasses may override this method to perform any necessary initialising/clearing/resetting of variables when when preparing to enter this behaviour if it was not previously RUNNING. i.e. Expect this to trigger more than once!

iterate(direct_descendants=False)[source]

Generator that provides iteration over this behaviour and all its children. To traverse the entire tree:

for node in my_behaviour.iterate():
    print("Name: {0}".format(node.name))
Parameters:direct_descendants (bool) – only yield children one step away from this behaviour.
Yields:Behaviour – one of it’s children
setup()[source]

Note

User Customisable Callback

Subclasses may override this method to do any one-off delayed construction & validation that is necessary prior to ticking the tree. Such construction is best done here rather than in __init__ so that trees can be instantiated on the fly for easy rendering to dot graphs without imposing runtime requirements (e.g. establishing a middleware connection to a sensor).

Equally as important, executing methods which validate the configuration of behaviours will help increase confidence that your tree will successfully tick without logical software errors before actually ticking. This is useful both before a tree’s first tick and immediately after any modifications to a tree has been made between ticks.

Tip

Faults are notified to the user of the behaviour via exceptions. Choice of exception to use is left to the user.

Raises:Exception – if this behaviour has a fault in construction or configuration
setup_with_descendants()[source]

Iterates over this child, it’s children (it’s children’s children, …) calling the user defined setup() on each in turn.

stop(new_status=<Status.INVALID: 'INVALID'>)[source]
Parameters:new_status (Status) – the behaviour is transitioning to this new status

This calls the user defined terminate() method and also resets the generator. It will finally set the new status once the user’s terminate() function has been called.

Warning

Override this method only in exceptional circumstances, prefer overriding terminate() instead.

terminate(new_status)[source]

Note

User Customisable Callback

Subclasses may override this method to clean up. It will be triggered when a behaviour either finishes execution (switching from RUNNING to FAILURE || SUCCESS) or it got interrupted by a higher priority branch (switching to INVALID). Remember that the initialise() method will handle resetting of variables before re-entry, so this method is about disabling resources until this behaviour’s next tick. This could be a indeterminably long time. e.g.

  • cancel an external action that got started
  • shut down any tempoarary communication handles
Parameters:new_status (Status) – the behaviour is transitioning to this new status

Warning

Do not set self.status = new_status here, that is automatically handled by the stop() method. Use the argument purely for introspection purposes (e.g. comparing the current state in self.status with the state it will transition to in new_status.

tick()[source]

This function is a generator that can be used by an iterator on an entire behaviour tree. It handles the logic for deciding when to call the user’s initialise() and terminate() methods as well as making the actual call to the user’s update() method that determines the behaviour’s new status once the tick has finished. Once done, it will then yield itself (generator mechanism) so that it can be used as part of an iterator for the entire tree.

for node in my_behaviour.tick():
    print("Do something")

Note

This is a generator function, you must use this with yield. If you need a direct call, prefer tick_once() instead.

Yields:Behaviour – a reference to itself

Warning

Override this method only in exceptional circumstances, prefer overriding update() instead.

tick_once()[source]

A direct means of calling tick on this object without using the generator mechanism.

tip()[source]

Get the tip of this behaviour’s subtree (if it has one) after it’s last tick. This corresponds to the the deepest node that was running before the subtree traversal reversed direction and headed back to this node.

Returns:child behaviour, itself or None if its status is INVALID
Return type:Behaviour or None
update()[source]

Note

User Customisable Callback

Returns:the behaviour’s new status Status
Return type:Status

Subclasses may override this method to perform any logic required to arrive at a decision on the behaviour’s new status. It is the primary worker function called on by the tick() mechanism.

Tip

This method should be almost instantaneous and non-blocking

verbose_info_string()[source]

Override to provide a one line informative string about the behaviour. This gets used in, e.g. dot graph rendering of the tree.

Tip

Use this sparingly. A good use case is for when the behaviour type and class name isn’t sufficient to inform the user about it’s mechanisms for controlling the flow of a tree tick (e.g. parallels with policies).

visit(visitor)[source]

This is functionality that enables external introspection into the behaviour. It gets used by the tree manager classes to collect information as ticking traverses a tree.

Parameters:visitor (object) – the visiting class, must have a run(Behaviour) method.

py_trees.behaviours

A library of fundamental behaviours for use.

class py_trees.behaviours.Count(name='Count', fail_until=3, running_until=5, success_until=6, reset=True)[source]

Bases: py_trees.behaviour.Behaviour

A counting behaviour that updates its status at each tick depending on the value of the counter. The status will move through the states in order - FAILURE, RUNNING, SUCCESS.

This behaviour is useful for simple testing and demo scenarios.

Parameters:
  • name (str) – name of the behaviour
  • fail_until (int) – set status to FAILURE until the counter reaches this value
  • running_until (int) – set status to RUNNING until the counter reaches this value
  • success_until (int) – set status to SUCCESS until the counter reaches this value
  • reset (bool) – whenever invalidated (usually by a sequence reinitialising, or higher priority interrupting)
Variables:

count (int) – a simple counter which increments every tick

terminate(new_status)[source]

Note

User Customisable Callback

Subclasses may override this method to clean up. It will be triggered when a behaviour either finishes execution (switching from RUNNING to FAILURE || SUCCESS) or it got interrupted by a higher priority branch (switching to INVALID). Remember that the initialise() method will handle resetting of variables before re-entry, so this method is about disabling resources until this behaviour’s next tick. This could be a indeterminably long time. e.g.

  • cancel an external action that got started
  • shut down any tempoarary communication handles
Parameters:new_status (Status) – the behaviour is transitioning to this new status

Warning

Do not set self.status = new_status here, that is automatically handled by the stop() method. Use the argument purely for introspection purposes (e.g. comparing the current state in self.status with the state it will transition to in new_status.

update()[source]

Note

User Customisable Callback

Returns:the behaviour’s new status Status
Return type:Status

Subclasses may override this method to perform any logic required to arrive at a decision on the behaviour’s new status. It is the primary worker function called on by the tick() mechanism.

Tip

This method should be almost instantaneous and non-blocking

class py_trees.behaviours.Dummy(name='Dummy')

Bases: py_trees.behaviour.Behaviour

class py_trees.behaviours.Failure(name='Failure')

Bases: py_trees.behaviour.Behaviour

class py_trees.behaviours.Periodic(name, n)[source]

Bases: py_trees.behaviour.Behaviour

Simply periodically rotates it’s status over the RUNNING, SUCCESS, FAILURE states. That is, RUNNING for N ticks, SUCCESS for N ticks, FAILURE for N ticks…

Parameters:
  • name (str) – name of the behaviour
  • n (int) – period value (in ticks)

Note

It does not reset the count when initialising.

update()[source]

Note

User Customisable Callback

Returns:the behaviour’s new status Status
Return type:Status

Subclasses may override this method to perform any logic required to arrive at a decision on the behaviour’s new status. It is the primary worker function called on by the tick() mechanism.

Tip

This method should be almost instantaneous and non-blocking

class py_trees.behaviours.Running(name='Running')

Bases: py_trees.behaviour.Behaviour

class py_trees.behaviours.Success(name='Success')

Bases: py_trees.behaviour.Behaviour

class py_trees.behaviours.SuccessEveryN(name, n)[source]

Bases: py_trees.behaviour.Behaviour

This behaviour updates it’s status with SUCCESS once every N ticks, FAILURE otherwise.

Parameters:
  • name (str) – name of the behaviour
  • n (int) – trigger success on every n’th tick

Tip

Use with decorators to change the status value as desired, e.g. py_trees.decorators.FailureIsRunning()

update()[source]

Note

User Customisable Callback

Returns:the behaviour’s new status Status
Return type:Status

Subclasses may override this method to perform any logic required to arrive at a decision on the behaviour’s new status. It is the primary worker function called on by the tick() mechanism.

Tip

This method should be almost instantaneous and non-blocking

py_trees.blackboard

Blackboards are not a necessary component, but are a fairly standard feature in most behaviour tree implementations. See, for example, the design notes for blackboards in Unreal Engine.

_images/blackboard.jpg

Implementations however, tend to vary quite a bit depending on the needs of the framework using them. Some of the usual considerations include scope and sharing of blackboards across multiple tree instances.

For this package, we’ve decided to keep blackboards extremely simple to fit with the same ‘rapid development for small scale systems’ principles that this library is designed for.

  • No sharing between tree instances
  • No locking for reading/writing
  • Global scope, i.e. any behaviour can access any variable
  • No external communications (e.g. to a database)
class py_trees.blackboard.Blackboard[source]

Bases: object

Borg style key-value store for sharing amongst behaviours.

Examples

You can instantiate the blackboard from anywhere in your program. Even disconnected calls will get access to the same data store. For example:

def check_foo():
    blackboard = Blackboard()
    assert(blackboard.foo, "bar")

if __name__ == '__main__':
    blackboard = Blackboard()
    blackboard.foo = "bar"
    check_foo()

If the key value you are interested in is only known at runtime, then you can set/get from the blackboard without the convenient variable style access:

blackboard = Blackboard()
result = blackboard.set("foo", "bar")
foo = blackboard.get("foo")

The blackboard can also be converted and printed (with highlighting) as a string. This is useful for logging and debugging.

print(Blackboard())

Warning

Be careful of key collisions. This implementation leaves this management up to the user.

See also

The py-trees-demo-blackboard program demos use of the blackboard along with a couple of the blackboard behaviours.

static clear()[source]

Erase the blackboard contents. Typically this is used only when you have repeated runs of different tree instances, as often happens in testing.

get(name)[source]

For when you only have strings to identify and access the blackboard variables, this provides a convenient accessor.

Parameters:name (str) – name of the variable to set
set(name, value, overwrite=True)[source]

For when you only have strings to identify and access the blackboard variables, this provides a convenient setter.

Parameters:
  • name (str) – name of the variable to set
  • value (any) – any variable type
  • overwrite (bool) – whether to abort if the value is already present
Returns:

always True unless overwrite was set to False and a variable already exists

Return type:

bool

unset(name)[source]

For when you need to unset a blackboard variable, this provides a convenient helper method. This is particularly useful for unit testing behaviours.

Parameters:name (str) – name of the variable to unset
class py_trees.blackboard.CheckBlackboardVariable(name, variable_name='dummy', expected_value=None, comparison_operator=<built-in function eq>, clearing_policy=<ClearingPolicy.ON_INITIALISE: 1>, debug_feedback_message=False)[source]

Bases: py_trees.behaviour.Behaviour

Check the blackboard to see if it has a specific variable and optionally whether that variable has an expected value. It is a binary behaviour, always updating it’s status with either SUCCESS or FAILURE at each tick.

initialise()[source]

Clears the internally stored message ready for a new run if old_data_is_valid wasn’t set.

terminate(new_status)[source]

Always discard the matching result if it was invalidated by a parent or higher priority interrupt.

update()[source]

Check for existence, or the appropriate match on the expected value.

Returns:FAILURE if not matched, SUCCESS otherwise.
Return type:Status
class py_trees.blackboard.ClearBlackboardVariable(name='Clear Blackboard Variable', variable_name='dummy')[source]

Bases: py_trees.meta.Success

Clear the specified value from the blackboard.

Parameters:
  • name (str) – name of the behaviour
  • variable_name (str) – name of the variable to clear
initialise()[source]

Delete the variable from the blackboard.

class py_trees.blackboard.SetBlackboardVariable(name='Set Blackboard Variable', variable_name='dummy', variable_value=None)[source]

Bases: py_trees.meta.Success

Set the specified variable on the blackboard. Usually we set variables from inside other behaviours, but can be convenient to set them from a behaviour of their own sometimes so you don’t get blackboard logic mixed up with more atomic behaviours.

Parameters:
  • name (str) – name of the behaviour
  • variable_name (str) – name of the variable to set
  • variable_value (any) – value of the variable to set

Todo

overwrite option, leading to possible failure/success logic.

initialise()[source]

Note

User Customisable Callback

Subclasses may override this method to perform any necessary initialising/clearing/resetting of variables when when preparing to enter this behaviour if it was not previously RUNNING. i.e. Expect this to trigger more than once!

class py_trees.blackboard.WaitForBlackboardVariable(name, variable_name='dummy', expected_value=None, comparison_operator=<built-in function eq>, clearing_policy=<ClearingPolicy.ON_INITIALISE: 1>)[source]

Bases: py_trees.behaviour.Behaviour

Check the blackboard to see if it has a specific variable and optionally whether that variable has a specific value. Unlike CheckBlackboardVariable this class will be in a RUNNING state until the variable appears and (optionally) is matched.

Parameters:
  • name (str) – name of the behaviour
  • variable_name (str) – name of the variable to check
  • expected_value (any) – expected value to find (if None, check for existence only)
  • comparison_operator (func) – one from the python operator module
  • clearing_policy (any) – when to clear the match result, see ClearingPolicy

Tip

There are times when you want to get the expected match once and then save that result thereafter. For example, to flag once a system has reached a subgoal. Use the NEVER flag to do this.

initialise()[source]

Clears the internally stored message ready for a new run if old_data_is_valid wasn’t set.

terminate(new_status)[source]

Always discard the matching result if it was invalidated by a parent or higher priority interrupt.

update()[source]

Check for existence, or the appropriate match on the expected value.

Returns:FAILURE if not matched, SUCCESS otherwise.
Return type:Status

py_trees.common

Common definitions, methods and variables used by the py_trees library.

class py_trees.common.BlackBoxLevel[source]

Bases: enum.IntEnum

Whether a behaviour is a blackbox entity that may be considered collapsible (i.e. everything in its subtree will not be visualised) by visualisation tools.

Blackbox levels are increasingly persistent in visualisations.

Visualisations by default, should always collapse blackboxes that represent DETAIL.

BIG_PICTURE = 3

A blackbox that represents a big picture part of the entire tree view.

COMPONENT = 2

A blackbox that encapsulates a subgroup of functionalities as a single group.

DETAIL = 1

A blackbox that encapsulates detailed activity.

NOT_A_BLACKBOX = 4

Not a blackbox, do not ever collapse.

class py_trees.common.ClearingPolicy[source]

Bases: enum.IntEnum

Policy rules for behaviours to dictate when data should be cleared/reset.

NEVER = 3

Never clear the data

ON_INITIALISE = 1

Clear when entering the initialise() method.

ON_SUCCESS = 2

Clear when returning SUCCESS.

class py_trees.common.Duration[source]

Bases: enum.Enum

Naming conventions.

INFINITE = inf

INFINITE oft used for perpetually blocking operations.

UNTIL_THE_BATTLE_OF_ALFREDO = inf

UNTIL_THE_BATTLE_OF_ALFREDO is an alias for INFINITE.

class py_trees.common.Name[source]

Bases: enum.Enum

Naming conventions.

AUTO_GENERATED = 'AUTO_GENERATED'

AUTO_GENERATED leaves it to the behaviour to generate a useful, informative name.

class py_trees.common.ParallelPolicy[source]

Configurable policies for Parallel behaviours.

class SuccessOnAll(synchronise=True)[source]

Return SUCCESS only when each and every child returns SUCCESS.

class SuccessOnOne[source]

Return SUCCESS so long as at least one child has SUCCESS and the remainder are RUNNING

class SuccessOnSelected(children, synchronise=True)[source]

Retrun SUCCESS so long as each child in a specified list returns SUCCESS.

class py_trees.common.Status[source]

Bases: enum.Enum

An enumerator representing the status of a behaviour

FAILURE = 'FAILURE'

Behaviour check has failed, or execution of its action finished with a failed result.

INVALID = 'INVALID'

Behaviour is uninitialised and inactive, i.e. this is the status before first entry, and after a higher priority switch has occurred.

RUNNING = 'RUNNING'

Behaviour is in the middle of executing some action, result still pending.

SUCCESS = 'SUCCESS'

Behaviour check has passed, or execution of its action has finished with a successful result.

class py_trees.common.VisibilityLevel[source]

Bases: enum.IntEnum

Closely associated with the BlackBoxLevel for a behaviour. This sets the visibility level to be used for visualisations.

Visibility levels correspond to reducing levels of visibility in a visualisation.

ALL = 0

Do not collapse any behaviour.

BIG_PICTURE = 3

Collapse any blackbox that isn’t marked with BIG_PICTURE.

COMPONENT = 2

Collapse blackboxes marked with COMPONENT or lower.

DETAIL = 1

Collapse blackboxes marked with DETAIL or lower.

common.string_to_visibility_level()

Will convert a string to a visibility level. Note that it will quietly return ALL if the string is not matched to any visibility level string identifier.

Parameters:level (str) – visibility level as a string
Returns:visibility level enum
Return type:VisibilityLevel

py_trees.composites

Composites are the factories and decision makers of a behaviour tree. They are responsible for shaping the branches.

digraph selector {
graph [fontname="times-roman"];
node [fontname="times-roman"];
edge [fontname="times-roman"];
Sequence [fontcolor=black, shape=box, fontsize=11, style=filled, fillcolor=orange];
Selector [fontcolor=black, shape=octagon, fontsize=11, style=filled, fillcolor=cyan];
Chooser [fontcolor=black, shape=doubleoctagon, fontsize=11, style=filled, fillcolor=cyan];
Parallel [fontcolor=black, shape=parallelogram, fontsize=11, style=filled, fillcolor=gold];
}

Tip

You should never need to subclass or create new composites.

Most patterns can be achieved with a combination of the above. Adding to this set exponentially increases the complexity and subsequently making it more difficult to design, introspect, visualise and debug the trees. Always try to find the combination you need to achieve your result before contemplating adding to this set. Actually, scratch that…just don’t contemplate it!

Composite behaviours typically manage children and apply some logic to the way they execute and return a result, but generally don’t do anything themselves. Perform the checks or actions you need to do in the non-composite behaviours.

  • Sequence: execute children sequentially
  • Selector: select a path through the tree, interruptible by higher priorities
  • Chooser: like a selector, but commits to a path once started until it finishes
  • Parallel: manage children concurrently
class py_trees.composites.Chooser(name='Chooser', children=None)[source]

Bases: py_trees.composites.Selector

Choosers are Selectors with Commitment

digraph chooser {
graph [fontname="times-roman"];
node [fontname="times-roman"];
edge [fontname="times-roman"];
Chooser [fontcolor=black, shape=doubleoctagon, fontsize=11, style=filled, fillcolor=cyan];
"High Priority" [fontcolor=black, shape=ellipse, fontsize=11, style=filled, fillcolor=gray];
Chooser -> "High Priority";
"Med Priority" [fontcolor=black, shape=ellipse, fontsize=11, style=filled, fillcolor=gray];
Chooser -> "Med Priority";
"Low Priority" [fontcolor=black, shape=ellipse, fontsize=11, style=filled, fillcolor=gray];
Chooser -> "Low Priority";
}

A variant of the selector class. Once a child is selected, it cannot be interrupted by higher priority siblings. As soon as the chosen child itself has finished it frees the chooser for an alternative selection. i.e. priorities only come into effect if the chooser wasn’t running in the previous tick.

Note

This is the only composite in py_trees that is not a core composite in most behaviour tree implementations. Nonetheless, this is useful in fields like robotics, where you have to ensure that your manipulator doesn’t drop it’s payload mid-motion as soon as a higher interrupt arrives. Use this composite sparingly and only if you can’t find another way to easily create an elegant tree composition for your task.

Parameters:
  • name (str) – the composite behaviour name
  • children ([Behaviour]) – list of children to add
__init__(name='Chooser', children=None)[source]

Initialize self. See help(type(self)) for accurate signature.

tick()[source]

Run the tick behaviour for this chooser. Note that the status of the tick is (for now) always determined by its children, not by the user customised update function.

Yields:Behaviour – a reference to itself or one of its children
class py_trees.composites.Composite(name: str = <Name.AUTO_GENERATED: 'AUTO_GENERATED'>, children: List[py_trees.behaviour.Behaviour] = None)[source]

Bases: py_trees.behaviour.Behaviour

The parent class to all composite behaviours, i.e. those that have children.

Parameters:
  • name (str) – the composite behaviour name
  • children ([Behaviour]) – list of children to add
__init__(name: str = <Name.AUTO_GENERATED: 'AUTO_GENERATED'>, children: List[py_trees.behaviour.Behaviour] = None)[source]

Initialize self. See help(type(self)) for accurate signature.

add_child(child)[source]

Adds a child.

Parameters:child (Behaviour) – child to add
Raises:TypeError – if the provided child is not an instance of Behaviour
Returns:unique id of the child
Return type:uuid.UUID
add_children(children)[source]

Append a list of children to the current list.

Parameters:children ([Behaviour]) – list of children to add
insert_child(child, index)[source]

Insert child at the specified index. This simply directly calls the python list’s insert method using the child and index arguments.

Parameters:
  • child (Behaviour) – child to insert
  • index (int) – index to insert it at
Returns:

unique id of the child

Return type:

uuid.UUID

prepend_child(child)[source]

Prepend the child before all other children.

Parameters:child (Behaviour) – child to insert
Returns:unique id of the child
Return type:uuid.UUID
remove_all_children()[source]

Remove all children. Makes sure to stop each child if necessary.

remove_child(child)[source]

Remove the child behaviour from this composite.

Parameters:child (Behaviour) – child to delete
Returns:index of the child that was removed
Return type:int

Todo

Error handling for when child is not in this list

remove_child_by_id(child_id)[source]

Remove the child with the specified id.

Parameters:child_id (uuid.UUID) – unique id of the child
Raises:IndexError – if the child was not found
replace_child(child, replacement)[source]

Replace the child behaviour with another.

Parameters:
stop(new_status=<Status.INVALID: 'INVALID'>)[source]

There is generally two use cases that must be supported here.

1) Whenever the composite has gone to a recognised state (i.e. FAILURE or SUCCESS), or 2) when a higher level parent calls on it to truly stop (INVALID).

In only the latter case will children need to be forcibly stopped as well. In the first case, they will have stopped themselves appropriately already.

Parameters:new_status (Status) – behaviour will transition to this new status
tip()[source]

Recursive function to extract the last running node of the tree.

Returns:class::~py_trees.behaviour.Behaviour: the tip function of the current child of this composite or None
class py_trees.composites.Parallel(name: str = <Name.AUTO_GENERATED: 'AUTO_GENERATED'>, policy: py_trees.common.ParallelPolicy.Base = <py_trees.common.ParallelPolicy.SuccessOnAll object>, children: List[py_trees.behaviour.Behaviour] = None)[source]

Bases: py_trees.composites.Composite

Parallels enable a kind of concurrency

digraph pastafarianism {
graph [fontname="times-roman", splines=curved];
node [fontname="times-roman"];
edge [fontname="times-roman"];
Parallel [fillcolor=gold, fontcolor=black, fontsize=9, label="Parallel\n--SuccessOnSelected(⚡,[B1,B2])--", shape=parallelogram, style=filled];
B1 [fillcolor=gray, fontcolor=black, fontsize=9, label=B1, shape=ellipse, style=filled];
Parallel -> B1;
B2 [fillcolor=gray, fontcolor=black, fontsize=9, label=B2, shape=ellipse, style=filled];
Parallel -> B2;
B3 [fillcolor=gray, fontcolor=black, fontsize=9, label=B3, shape=ellipse, style=filled];
Parallel -> B3;
}

Ticks every child every time the parallel is run (a poor man’s form of parallelism).

Parallels with policy SuccessOnSelected will validate themselves just-in-time in the setup() and tick() methods to check if the policy’s selected set of children is a subset of the children of this parallel. Doing this just-in-time is due to the fact that the parallel’s children may change after construction and even dynamically between ticks.

__init__(name: str = <Name.AUTO_GENERATED: 'AUTO_GENERATED'>, policy: py_trees.common.ParallelPolicy.Base = <py_trees.common.ParallelPolicy.SuccessOnAll object>, children: List[py_trees.behaviour.Behaviour] = None)[source]
Parameters:
  • name (str) – the composite behaviour name
  • policy (ParallelPolicy) – policy to use for deciding success or otherwise
  • children ([Behaviour]) – list of children to add
current_child

In some cases it’s clear what the current child is, in others, there is an ambiguity as multiple could exist. If the latter is true, it will return the child relevant farthest down the list.

Returns:the child that is currently running, or None
Return type:Behaviour
setup()[source]

Detect before ticking whether the policy configuration is invalid.

Raises:
  • RuntimeError – if the parallel’s policy configuration is invalid
  • Exception – be ready to catch if any of the children raise an exception
tick()[source]

Tick over the children.

Yields:Behaviour – a reference to itself or one of its children
Raises:RuntimeError – if the policy configuration was invalid
validate_policy_configuration()[source]

Policy configuration can be invalid if:

  • Policy is SuccessOnSelected and no behaviours have been specified
  • Policy is SuccessOnSelected and behaviours that are not children exist
Raises:RuntimeError – if policy configuration was invalid
verbose_info_string() → str[source]

Provide additional information about the underlying policy.

Returns:name of the policy along with it’s configuration
Return type:str
class py_trees.composites.Selector(name='Selector', children=None)[source]

Bases: py_trees.composites.Composite

Selectors are the Decision Makers

digraph selector {
graph [fontname="times-roman"];
node [fontname="times-roman"];
edge [fontname="times-roman"];
Selector [fontcolor=black, shape=octagon, fontsize=11, style=filled, fillcolor=cyan];
"High Priority" [fontcolor=black, shape=ellipse, fontsize=11, style=filled, fillcolor=gray];
Selector -> "High Priority";
"Med Priority" [fontcolor=black, shape=ellipse, fontsize=11, style=filled, fillcolor=gray];
Selector -> "Med Priority";
"Low Priority" [fontcolor=black, shape=ellipse, fontsize=11, style=filled, fillcolor=gray];
Selector -> "Low Priority";
}

A selector executes each of its child behaviours in turn until one of them succeeds (at which point it itself returns RUNNING or SUCCESS, or it runs out of children at which point it itself returns FAILURE. We usually refer to selecting children as a means of choosing between priorities. Each child and its subtree represent a decreasingly lower priority path.

Note

Switching from a low -> high priority branch causes a stop(INVALID) signal to be sent to the previously executing low priority branch. This signal will percolate down that child’s own subtree. Behaviours should make sure that they catch this and destruct appropriately.

Make sure you do your appropriate cleanup in the terminate() methods! e.g. cancelling a running goal, or restoring a context.

See also

The py-trees-demo-selector program demos higher priority switching under a selector.

Parameters:
  • name (str) – the composite behaviour name
  • children ([Behaviour]) – list of children to add
__init__(name='Selector', children=None)[source]

Initialize self. See help(type(self)) for accurate signature.

__repr__()[source]

Simple string representation of the object.

Returns:string representation
Return type:str
stop(new_status=<Status.INVALID: 'INVALID'>)[source]

Stopping a selector requires setting the current child to none. Note that it is important to implement this here instead of terminate, so users are free to subclass this easily with their own terminate and not have to remember that they need to call this function manually.

Parameters:new_status (Status) – the composite is transitioning to this new status
tick()[source]

Run the tick behaviour for this selector. Note that the status of the tick is always determined by its children, not by the user customised update function.

Yields:Behaviour – a reference to itself or one of its children
class py_trees.composites.Sequence(name='Sequence', children=None)[source]

Bases: py_trees.composites.Composite

Sequences are the factory lines of Behaviour Trees

digraph sequence {
graph [fontname="times-roman"];
node [fontname="times-roman"];
edge [fontname="times-roman"];
Sequence [fillcolor=orange, fontcolor=black, fontsize=11, shape=box, style=filled];
Guard [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> Guard;
"Action 1" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Action 1";
"Action 2" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Action 2";
"Action 3" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Action 3";
}

A sequence will progressively tick over each of its children so long as each child returns SUCCESS. If any child returns FAILURE or RUNNING the sequence will halt and the parent will adopt the result of this child. If it reaches the last child, it returns with that result regardless.

Note

The sequence halts once it sees a child is RUNNING and then returns the result. It does not get stuck in the running behaviour.

See also

The py-trees-demo-sequence program demos a simple sequence in action.

Parameters:
  • name (str) – the composite behaviour name
  • children ([Behaviour]) – list of children to add
__init__(name='Sequence', children=None)[source]

Initialize self. See help(type(self)) for accurate signature.

current_child

Have to check if there’s anything actually running first.

Returns:the child that is currently running, or None
Return type:Behaviour
stop(new_status=<Status.INVALID: 'INVALID'>)[source]

Stopping a sequence requires taking care of the current index. Note that is important to implement this here intead of terminate, so users are free to subclass this easily with their own terminate and not have to remember that they need to call this function manually.

Parameters:new_status (Status) – the composite is transitioning to this new status
tick()[source]

Tick over the children.

Yields:Behaviour – a reference to itself or one of its children

py_trees.console

Simple colour definitions and syntax highlighting for the console.


Colour Definitions

The current list of colour definitions include:

  • Regular: black, red, green, yellow, blue, magenta, cyan, white,
  • Bold: bold, bold_black, bold_red, bold_green, bold_yellow, bold_blue, bold_magenta, bold_cyan, bold_white

These colour definitions can be used in the following way:

import py_trees.console as console
print(console.cyan + "    Name" + console.reset + ": " + console.yellow + "Dude" + console.reset)
py_trees.console.colours = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']

List of all available colours.

py_trees.console.console_has_colours()[source]

Detects if the console (stdout) has colourising capability.

py_trees.console.has_colours = False

Whether the loading program has access to colours or not.

py_trees.console.logdebug(message)[source]

Prefixes [DEBUG] and colours the message green.

Parameters:message (str) – message to log.
py_trees.console.logerror(message)[source]

Prefixes [ERROR] and colours the message red.

Parameters:message (str) – message to log.
py_trees.console.logfatal(message)[source]

Prefixes [FATAL] and colours the message bold red.

Parameters:message (str) – message to log.
py_trees.console.loginfo(message)[source]

Prefixes [ INFO] to the message.

Parameters:message (str) – message to log.
py_trees.console.logwarn(message)[source]

Prefixes [ WARN] and colours the message yellow.

Parameters:message (str) – message to log.
py_trees.console.read_single_keypress()[source]

Waits for a single keypress on stdin.

This is a silly function to call if you need to do it a lot because it has to store stdin’s current setup, setup stdin for reading single keystrokes then read the single keystroke then revert stdin back after reading the keystroke.

Returns:the character of the key that was pressed
Return type:int
Raises:KeyboardInterrupt – if CTRL-C was pressed (keycode 0x03)

py_trees.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.

_images/many-hats.png

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!";
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python

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:

And the X is Y family:

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.

class py_trees.decorators.Condition(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>, status=<Status.SUCCESS: 'SUCCESS'>)[source]

Bases: py_trees.decorators.Decorator

Encapsulates a behaviour and wait for it’s status to flip to the desired state. This behaviour will tick with RUNNING while waiting and SUCCESS when the flip occurs.

__init__(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>, status=<Status.SUCCESS: 'SUCCESS'>)[source]

Initialise with child and optional name, status variables.

Parameters:
  • child (Behaviour) – the child to be decorated
  • name (str) – the decorator name (can be None)
  • status (Status) – the desired status to watch for
update()[source]

SUCCESS if the decorated child has returned the specified status, otherwise RUNNING. This decorator will never return FAILURE

Returns:the behaviour’s new status Status
Return type:Status
class py_trees.decorators.Decorator(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Bases: py_trees.behaviour.Behaviour

A decorator is responsible for handling the lifecycle of a single child beneath

__init__(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Common initialisation steps for a decorator - type checks and name construction (if None is given).

Parameters:
  • name (str) – the decorator name
  • child (Behaviour) – the child to be decorated
Raises:

TypeError – if the child is not an instance of Behaviour

stop(new_status)[source]

As with other composites, it checks if the child is running and stops it if that is the case.

Parameters:new_status (Status) – the behaviour is transitioning to this new status
tick()[source]

A decorator’s tick is exactly the same as a normal proceedings for a Behaviour’s tick except that it also ticks the decorated child node.

Yields:Behaviour – a reference to itself or one of its children
class py_trees.decorators.FailureIsRunning(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Bases: py_trees.decorators.Decorator

Dont stop running.

update()[source]

Return the decorated child’s status unless it is FAILURE in which case, return RUNNING.

Returns:the behaviour’s new status Status
Return type:Status
class py_trees.decorators.FailureIsSuccess(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Bases: py_trees.decorators.Decorator

Be positive, always succeed.

update()[source]

Return the decorated child’s status unless it is FAILURE in which case, return SUCCESS.

Returns:the behaviour’s new status Status
Return type:Status
class py_trees.decorators.Inverter(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Bases: py_trees.decorators.Decorator

A decorator that inverts the result of a class’s update function.

__init__(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Init with the decorated child.

Parameters:
  • child (Behaviour) – behaviour to time
  • name (str) – the decorator name
update()[source]

Flip FAILURE and SUCCESS

Returns:the behaviour’s new status Status
Return type:Status
class py_trees.decorators.OneShot(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>, policy=<OneShotPolicy.ON_SUCCESSFUL_COMPLETION: [<Status.SUCCESS: 'SUCCESS'>]>)[source]

Bases: py_trees.decorators.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 returns SUCCESS (i.e. it permits retries).
  • With policy ON_COMPLETION, the oneshot will activate when the child returns SUCCESS || FAILURE.
__init__(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>, policy=<OneShotPolicy.ON_SUCCESSFUL_COMPLETION: [<Status.SUCCESS: 'SUCCESS'>]>)[source]

Init with the decorated child.

Parameters:
  • name (str) – the decorator name
  • child (Behaviour) – behaviour to time
  • policy (OneShotPolicy) – policy determining when the oneshot should activate
terminate(new_status)[source]

If returning SUCCESS for the first time, flag it so future ticks will block entry to the child.

tick()[source]

Select between decorator (single child) and behaviour (no children) style ticks depending on whether or not the underlying child has been ticked successfully to completion previously.

update()[source]

Bounce if the child has already successfully completed.

class py_trees.decorators.RunningIsFailure(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Bases: py_trees.decorators.Decorator

Got to be snappy! We want results…yesterday!

update()[source]

Return the decorated child’s status unless it is RUNNING in which case, return FAILURE.

Returns:the behaviour’s new status Status
Return type:Status
class py_trees.decorators.RunningIsSuccess(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Bases: py_trees.decorators.Decorator

Don’t hang around…

update()[source]

Return the decorated child’s status unless it is RUNNING in which case, return SUCCESS.

Returns:the behaviour’s new status Status
Return type:Status
class py_trees.decorators.SuccessIsFailure(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Bases: py_trees.decorators.Decorator

Be depressed, always fail.

update()[source]

Return the decorated child’s status unless it is SUCCESS in which case, return FAILURE.

Returns:the behaviour’s new status Status
Return type:Status
class py_trees.decorators.SuccessIsRunning(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>)[source]

Bases: py_trees.decorators.Decorator

It never ends…

update()[source]

Return the decorated child’s status unless it is SUCCESS in which case, return RUNNING.

Returns:the behaviour’s new status Status
Return type:Status
class py_trees.decorators.Timeout(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>, duration=5.0)[source]

Bases: py_trees.decorators.Decorator

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 status FAILURE otherwise it will simply directly tick and return with the same status as that of it’s encapsulated behaviour.

__init__(child, name=<Name.AUTO_GENERATED: 'AUTO_GENERATED'>, duration=5.0)[source]

Init with the decorated child and a timeout duration.

Parameters:
  • child (Behaviour) – behaviour to time
  • name (str) – the decorator name
  • duration (float) – timeout length in seconds
initialise()[source]

Reset the feedback message and finish time on behaviour entry.

update()[source]

Terminate the child and return FAILURE if the timeout is exceeded.

py_trees.display

Behaviour trees are significantly easier to design, monitor and debug with visualisations. Py Trees does provide minimal assistance to render trees to various simple output formats. Currently this includes dot graphs, strings or stdout.

py_trees.display.ascii_bullet(node)[source]

Generate a text bullet for the specified behaviour’s type.

Parameters:node (Behaviour) – convert this behaviour’s type to text
Returns:the text bullet
Return type:str)
py_trees.display.ascii_check_mark(status)[source]

Generate a text check mark for the specified status.

Parameters:status (Status) – convert this status to text
Returns:the text check mark
Return type:str)
py_trees.display.ascii_tree(tree, indent=0, snapshot_information=None)[source]

Build an ascii tree representation as a string for redirecting to elsewhere other than stdout. This can be the entire tree, or a recorded snapshot of the tree (i.e. just the part that was traversed).

Parameters:
  • tree (Behaviour) – the root of the tree, or subtree you want to show
  • indent (int) – the number of characters to indent the tree
  • snapshot_information (visitors) – a visitor that recorded information about a traversed tree (e.g. SnapshotVisitor)
  • snapshot_information – a visitor that recorded information about a traversed tree (e.g. SnapshotVisitor)
Returns:

an ascii tree (i.e. in string form)

Return type:

str

Examples

Use the SnapshotVisitor and BehaviourTree to generate snapshot information at each tick and feed that to a post tick handler that will print the traversed ascii tree complete with status and feedback messages.

_images/ascii_tree.png
def post_tick_handler(snapshot_visitor, behaviour_tree):
    print(py_trees.display.ascii_tree(behaviour_tree.root,
          snapshot_information=snapshot_visitor))

root = py_trees.composites.Sequence("Sequence")
for action in ["Action 1", "Action 2", "Action 3"]:
    b = py_trees.behaviours.Count(
            name=action,
            fail_until=0,
            running_until=1,
            success_until=10)
    root.add_child(b)
behaviour_tree = py_trees.trees.BehaviourTree(root)
snapshot_visitor = py_trees.visitors.SnapshotVisitor()
behaviour_tree.add_post_tick_handler(
    functools.partial(post_tick_handler,
                      snapshot_visitor))
behaviour_tree.visitors.append(snapshot_visitor)
py_trees.display.generate_pydot_graph(root, visibility_level, collapse_decorators, with_qualified_names)[source]

Generate the pydot graph - this is usually the first step in rendering the tree to file. See also render_dot_tree().

Parameters:
  • root (Behaviour) – the root of a tree, or subtree
  • ( (visibility_level) – class`~py_trees.common.VisibilityLevel`): collapse subtrees at or under this level
  • collapse_decorators (bool) – only show the decorator (not the child)
  • with_qualified_names – (bool): print the class information for each behaviour in each node
Returns:

graph

Return type:

pydot.Dot

py_trees.display.print_ascii_tree(root, indent=0, show_status=False)[source]

Print the ASCII representation of an entire behaviour tree.

Parameters:
  • root (Behaviour) – the root of the tree, or subtree you want to show
  • indent (int) – the number of characters to indent the tree
  • show_status (bool) – additionally show feedback message and status of every element

Examples

Render a simple tree in ascii format to stdout.

_images/ascii_tree_simple.png
root = py_trees.composites.Sequence("Sequence")
for action in ["Action 1", "Action 2", "Action 3"]:
    b = py_trees.behaviours.Count(
            name=action,
            fail_until=0,
            running_until=1,
            success_until=10)
    root.add_child(b)
py_trees.display.print_ascii_tree(root)

Tip

To additionally display status and feedbback message from every behaviour in the tree, simply set the show_status flag to True.

py_trees.display.render_dot_tree(root: py_trees.behaviour.Behaviour, visibility_level: py_trees.common.VisibilityLevel = <VisibilityLevel.DETAIL: 1>, collapse_decorators: bool = False, name: str = None, target_directory: str = '/home/docs/checkouts/readthedocs.org/user_builds/py-trees/checkouts/release-1.0.x/doc', with_qualified_names: bool = False)[source]

Render the dot tree to .dot, .svg, .png. files in the current working directory. These will be named with the root behaviour name.

Parameters:
  • root (Behaviour) – the root of a tree, or subtree
  • ( (visibility_level) – class`~py_trees.common.VisibilityLevel`): collapse subtrees at or under this level
  • collapse_decorators (bool) – only show the decorator (not the child)
  • name (str) – name to use for the created files (defaults to the root behaviour name)
  • target_directory (str) – default is to use the current working directory, set this to redirect elsewhere
  • with_qualified_names (bool) – print the class names of each behaviour in the dot node

Example

Render a simple tree to dot/svg/png file:

digraph sequence {
graph [fontname="times-roman"];
node [fontname="times-roman"];
edge [fontname="times-roman"];
Sequence [fillcolor=orange, fontcolor=black, fontsize=11, shape=box, style=filled];
Guard [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> Guard;
"Action 1" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Action 1";
"Action 2" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Action 2";
"Action 3" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Action 3";
}
root = py_trees.composites.Sequence("Sequence")
for job in ["Action 1", "Action 2", "Action 3"]:
    success_after_two = py_trees.behaviours.Count(name=job,
                                                  fail_until=0,
                                                  running_until=1,
                                                  success_until=10)
    root.add_child(success_after_two)
py_trees.display.render_dot_tree(root)

Tip

A good practice is to provide a command line argument for optional rendering of a program so users can quickly visualise what tree the program will execute.

py_trees.display.stringify_dot_tree(root)[source]

Generate dot tree graphs and return a string representation of the dot graph.

Parameters:root (Behaviour) – the root of a tree, or subtree
Returns:dot graph as a string
Return type:str

py_trees.idioms

A library of subtree creators that build complex patterns of behaviours representing common behaviour tree idioms.

py_trees.idioms.oneshot(name='OneShot Idiom', variable_name='oneshot', behaviour=<py_trees.meta.Dummy object>, policy=<OneShotPolicy.ON_SUCCESSFUL_COMPLETION: [<Status.SUCCESS: 'SUCCESS'>]>)[source]

Ensure that a particular pattern is executed through to completion just once. Thereafter it will just rebound with success.

digraph oneshot {
graph [fontname="times-roman"];
node [fontname="times-roman"];
edge [fontname="times-roman"];
OneShot [fillcolor=cyan, fontcolor=black, fontsize=11, shape=octagon, style=filled];
"Oneshot w/ Guard" [fillcolor=orange, fontcolor=black, fontsize=11, shape=box, style=filled];
OneShot -> "Oneshot w/ Guard";
"Not Completed?" [fillcolor=ghostwhite, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
"Oneshot w/ Guard" -> "Not Completed?";
"Completed?" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
"Not Completed?" -> "Completed?";
Sequence [fillcolor=orange, fontcolor=black, fontsize=11, shape=box, style=filled];
"Oneshot w/ Guard" -> Sequence;
Guard [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> Guard;
"Action 1" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Action 1";
"Action 2" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Action 2";
"Action 3" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Action 3";
"Mark Done\n[SUCCESS]" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
Sequence -> "Mark Done\n[SUCCESS]";
"Oneshot Result" [fillcolor=gray, fontcolor=black, fontsize=11, shape=ellipse, style=filled];
OneShot -> "Oneshot Result";
}

Note

Completion on FAILURE or on SUCCESS only (permits retries if it fails) is determined by the policy.

Parameters:
  • name (str) – the name to use for the oneshot root (selector)
  • variable_name (str) – name for the flag used on the blackboard (ensure it is unique)
  • behaviour (Behaviour) – single behaviour or composited subtree to oneshot
  • policy (OneShotPolicy) – policy determining when the oneshot should activate
Returns:

the root of the oneshot subtree

Return type:

Behaviour

py_trees.idioms.pick_up_where_you_left_off(name='Pickup Where You Left Off Idiom', tasks=[<py_trees.meta.Dummy object>, <py_trees.meta.Dummy object>])[source]

Rudely interrupted while enjoying a sandwich, a caveman (just because they wore loincloths does not mean they were not civilised), picks up his club and fends off the sabre-tooth tiger invading his sanctum as if he were swatting away a gnat. Task accomplished, he returns to the joys of munching through the layers of his sandwich.

digraph pick_up_where_you_left_off {
graph [fontname="times-roman"];
node [fontname="times-roman"];
edge [fontname="times-roman"];
"Pick Up Where You Left Off" [shape=octagon, style=filled, fillcolor=cyan, fontsize=11, fontcolor=black];
"High Priority" [shape=ellipse, style=filled, fillcolor=gray, fontsize=11, fontcolor=black];
"Pick Up Where You Left Off" -> "High Priority";
Tasks [shape=box, style=filled, fillcolor=orange, fontsize=11, fontcolor=black];
"Pick Up Where You Left Off" -> Tasks;
"Do or Don't" [shape=octagon, style=filled, fillcolor=cyan, fontsize=11, fontcolor=black];
Tasks -> "Do or Don't";
"Done?" [shape=ellipse, style=filled, fillcolor=gray, fontsize=11, fontcolor=black];
"Do or Don't" -> "Done?";
Worker [shape=box, style=filled, fillcolor=orange, fontsize=11, fontcolor=black];
"Do or Don't" -> Worker;
"Task 1" [shape=ellipse, style=filled, fillcolor=gray, fontsize=11, fontcolor=black];
Worker -> "Task 1";
"Mark\ntask_1_done" [shape=ellipse, style=filled, fillcolor=gray, fontsize=11, fontcolor=black];
Worker -> "Mark\ntask_1_done";
"Do or Don't*" [shape=octagon, style=filled, fillcolor=cyan, fontsize=11, fontcolor=black];
Tasks -> "Do or Don't*";
"Done?*" [shape=ellipse, style=filled, fillcolor=gray, fontsize=11, fontcolor=black];
"Do or Don't*" -> "Done?*";
"Worker*" [shape=box, style=filled, fillcolor=orange, fontsize=11, fontcolor=black];
"Do or Don't*" -> "Worker*";
"Task 2" [shape=ellipse, style=filled, fillcolor=gray, fontsize=11, fontcolor=black];
"Worker*" -> "Task 2";
"Mark\ntask_2_done" [shape=ellipse, style=filled, fillcolor=gray, fontsize=11, fontcolor=black];
"Worker*" -> "Mark\ntask_2_done";
"Clear\ntask_1_done" [shape=ellipse, style=filled, fillcolor=gray, fontsize=11, fontcolor=black];
Tasks -> "Clear\ntask_1_done";
"Clear\ntask_2_done" [shape=ellipse, style=filled, fillcolor=gray, fontsize=11, fontcolor=black];
Tasks -> "Clear\ntask_2_done";
}

Note

There are alternative ways to accomplish this idiom with their pros and cons.

a) The tasks in the sequence could be replaced by a factory behaviour that dynamically checks the state of play and spins up the tasks required each time the task sequence is first entered and invalidates/deletes them when it is either finished or invalidated. That has the advantage of not requiring much of the blackboard machinery here, but disadvantage in not making visible the task sequence itself at all times (i.e. burying details under the hood).

b) A new composite which retains the index between initialisations can also achieve the same pattern with fewer blackboard shenanigans, but suffers from an increased logical complexity cost for your trees (each new composite increases decision making complexity (O(n!)).

Parameters:
  • name (str) – the name to use for the task sequence behaviour
  • tasks ([Behaviour) – lists of tasks to be sequentially performed
Returns:

root of the generated subtree

Return type:

Behaviour

py_trees.meta

Meta methods to create behaviours without needing to create the behaviours themselves.

py_trees.meta.create_behaviour_from_function(func)[source]

Create a behaviour from the specified function, dropping it in for the Behaviour update() method. Ths function must include the self argument and return a Status value. It also automatically provides a drop-in for the terminate() method that clears the feedback message. Other methods are left untouched.

Parameters:func (function) – a drop-in for the update() method

py_trees.timers

Time related behaviours.

class py_trees.timers.Timer(name='Timer', duration=5.0)[source]

Bases: py_trees.behaviour.Behaviour

Simple timer class that is RUNNING until the timer runs out, at which point it is SUCCESS. This can be used in a wide variety of situations - pause, duration, timeout depending on how it is wired into the tree (e.g. pause in a sequence, duration/timeout in a parallel).

The timer gets reset either upon entry (initialise()) if it hasn’t already been set and gets cleared when it either runs out, or the behaviour is interrupted by a higher priority or parent cancelling it.

Parameters:
  • name (str) – name of the behaviour
  • duration (int) – length of time to run (in seconds)
Raises:

TypeError – if the provided duration is not a real number

Note

This succeeds the first time the behaviour is ticked after the expected finishing time.

Tip

Use the RunningIsFailure() decorator if you need FAILURE until the timer finishes.

__init__(name='Timer', duration=5.0)[source]

Initialize self. See help(type(self)) for accurate signature.

initialise()[source]

Store the expected finishing time.

terminate(new_status)[source]

Clear the expected finishing time.

update()[source]

Check current time against the expected finishing time. If it is in excess, flip to SUCCESS.

py_trees.trees

While a graph of connected behaviours and composites form a tree in their own right (i.e. it can be initialised and ticked), it is usually convenient to wrap your tree in another class to take care of alot of the housework and provide some extra bells and whistles that make your tree flourish.

_images/yggdrasil.jpg

This package provides a default reference implementation that is directly usable, but can also be easily used as inspiration for your own tree custodians.

class py_trees.trees.BehaviourTree(root: py_trees.behaviour.Behaviour)[source]

Bases: object

Grow, water, prune your behaviour tree with this, the default reference implementation. It features a few enhancements to provide richer logging, introspection and dynamic management of the tree itself:

  • Pre and post tick handlers to execute code automatically before and after a tick
  • Visitor access to the parts of the tree that were traversed in a tick
  • Subtree pruning and insertion operations
  • Continuous tick-tock support

See also

The py-trees-demo-tree-stewardship program demonstrates the above features.

Parameters:

root (Behaviour) – root node of the tree

Variables:
  • count (int) – number of times the tree has been ticked.
  • root (Behaviour) – root node of the tree
  • visitors ([visitors]) – entities that visit traversed parts of the tree when it ticks
  • pre_tick_handlers ([func]) – functions that run before the entire tree is ticked
  • post_tick_handlers ([func]) – functions that run after the entire tree is ticked
Raises:

TypeError – if root variable is not an instance of Behaviour

add_post_tick_handler(handler)[source]

Add a function to execute after the tree has ticked. The function must have a single argument of type BehaviourTree.

Some ideas that are often used:

  • logging
  • modifications on the tree itself (e.g. closing down a plan)
  • sending data to visualisation tools
  • introspect the state of the tree to make and send reports
Parameters:handler (func) – function
add_pre_tick_handler(handler)[source]

Add a function to execute before the tree is ticked. The function must have a single argument of type BehaviourTree.

Some ideas that are often used:

  • logging (to file or stdout)
  • modifications on the tree itself (e.g. starting a new plan)
Parameters:handler (func) – function
destroy()[source]

Destroy the tree by stopping the root node.

insert_subtree(child, unique_id, index)[source]

Insert a subtree as a child of the specified parent. If the parent is found, this directly calls the parent’s insert_child() method using the child and index arguments.

Parameters:
  • child (Behaviour) – subtree to insert
  • unique_id (uuid.UUID) – unique id of the parent
  • index (int) – insert the child at this index, pushing all children after it back one.
Returns:

suceess or failure (parent not found) of the operation

Return type:

bool

Raises:

TypeError – if the parent is not a Composite

Todo

Could use better, more informative error handling here. Especially if the insertion has its own error handling (e.g. index out of range). Could also use a different api that relies on the id of the sibling node it should be inserted before/after.

interrupt()[source]

Interrupt tick-tock if it is tick-tocking. Note that this will permit a currently executing tick to finish before interrupting the tick-tock.

prune_subtree(unique_id)[source]

Prune a subtree given the unique id of the root of the subtree.

Parameters:unique_id (uuid.UUID) – unique id of the subtree root
Returns:success or failure of the operation
Return type:bool
Raises:RuntimeError – if unique id is the behaviour tree’s root node id
replace_subtree(unique_id, subtree)[source]

Replace the subtree with the specified id for the new subtree. This is a common pattern where we’d like to swap out a whole sub-behaviour for another one.

Parameters:
  • unique_id (uuid.UUID) – unique id of the parent
  • subtree (Behaviour) – root behaviour of the subtree
Raises
AssertionError: if unique id is the behaviour tree’s root node id
Returns:suceess or failure of the operation
Return type:bool
setup(timeout: float = <Duration.INFINITE: inf>, visitor: py_trees.visitors.VisitorBase = None)[source]

Crawls across the tree calling setup() on each behaviour.

Visitors can optionally be provided to provide a node-by-node analysis on the result of each node’s setup() before the next node’s setup() is called. This is useful on trees with relatively long setup times to progressively report out on the current status of the operation.

Parameters:
  • timeout (float) – time (s) to wait (use common.Duration.INFINITE to block indefinitely)
  • visitor (VisitorBase) – runnable entities on each node after it’s setup
Raises:

Exception – be ready to catch if any of the behaviours raise an exception

tick(pre_tick_handler=None, post_tick_handler=None)[source]

Tick the tree just once and run any handlers before and after the tick. This optionally accepts some one-shot handlers (c.f. those added by add_pre_tick_handler() and add_post_tick_handler() which will be automatically run every time).

The handler functions must have a single argument of type BehaviourTree.

Parameters:
  • pre_tick_handler (func) – function to execute before ticking
  • post_tick_handler (func) – function to execute after ticking
tick_tock(sleep_ms, number_of_iterations=-1, pre_tick_handler=None, post_tick_handler=None)[source]

Tick continuously with a sleep interval as specified. This optionally accepts some handlers that will be used for the duration of this tick tock (c.f. those added by add_pre_tick_handler() and add_post_tick_handler() which will be automatically run every time).

The handler functions must have a single argument of type BehaviourTree.

Parameters:
  • sleep_ms (float) – sleep this much between ticks (milliseconds)
  • number_of_iterations (int) – number of iterations to tick-tock
  • pre_tick_handler (func) – function to execute before ticking
  • post_tick_handler (func) – function to execute after ticking
tip()[source]

Get the tip of the tree. This corresponds to the the deepest node that was running before the subtree traversal reversed direction and headed back to this node.

Returns:child behaviour, itself or None if its status is INVALID
Return type:Behaviour or None

See also

tip()

py_trees.utilities

Assorted utility functions.

py_trees.utilities.get_fully_qualified_name(instance: object) → str[source]

Get at the fully qualified name of an object, e.g. an instance of a Sequence becomes ‘py_trees.composites.Sequence’.

Parameters:instance (object) – an instance of any class
Returns:the fully qualified name
Return type:str
py_trees.utilities.get_valid_filename(s: str) → str[source]

Return the given string converted to a string that can be used for a clean filename (without extension). Remove leading and trailing spaces; convert other spaces and newlines to underscores; and remove anything that is not an alphanumeric, dash, underscore, or dot.

>>> utilities.get_valid_filename("john's portrait in 2004.jpg")
'johns_portrait_in_2004.jpg'
Parameters:program (str) – string to convert to a valid filename
Returns:a representation of the specified string as a valid filename
Return type:str
py_trees.utilities.static_variables(**kwargs)[source]

This is a decorator that can be used with python methods to attach initialised static variables to the method.

@static_variables(counter=0)
def foo():
    foo.counter += 1
    print("Counter: {}".format(foo.counter))
py_trees.utilities.which(program)[source]

Wrapper around the command line ‘which’ program.

Parameters:program (str) – name of the program to find.
Returns:path to the program or None if it doesnt exist.
Return type:str

py_trees.visitors

Visitors are entities that can be passed to a tree implementation (e.g. BehaviourTree) and used to either visit each and every behaviour in the tree, or visit behaviours as the tree is traversed in an executing tick. At each behaviour, the visitor runs its own method on the behaviour to do as it wishes - logging, introspecting, etc.

Warning

Visitors should not modify the behaviours they visit.

class py_trees.visitors.DebugVisitor[source]

Bases: py_trees.visitors.VisitorBase

Picks up and logs feedback messages and the behaviour’s status. Logging is done with the behaviour’s logger.

run(behaviour)[source]

This method gets run as each behaviour is ticked. Override it to perform some activity - e.g. introspect the behaviour to store/process logging data for visualisations.

Parameters:behaviour (Behaviour) – behaviour that is ticking
class py_trees.visitors.SnapshotVisitor(full=False)[source]

Bases: py_trees.visitors.VisitorBase

Visits the tree in tick-tock, recording runtime information for publishing the information as a snapshot view of the tree after the iteration has finished.

Parameters:

full (bool) – flag to indicate whether it should be used to visit only traversed nodes or the entire tree

Variables:
  • nodes (dict) – dictionary of behaviour id (uuid.UUID) and status (Status) pairs
  • running_nodes ([uuid.UUID]) – list of id’s for behaviours which were traversed in the current tick
  • previously_running_nodes ([uuid.UUID]) – list of id’s for behaviours which were traversed in the last tick

See also

This visitor is used with the BehaviourTree class to collect information and ascii_tree() to display information.

initialise()[source]

Switch running to previously running and then reset all other variables. This should get called before a tree ticks.

run(behaviour)[source]

This method gets run as each behaviour is ticked. Catch the id and status and store it. Additionally add it to the running list if it is RUNNING.

Parameters:behaviour (Behaviour) – behaviour that is ticking
class py_trees.visitors.VisitorBase(full=False)[source]

Bases: object

Parent template for visitor types.

Visitors are primarily designed to work with BehaviourTree but they can be used in the same way for other tree custodian implementations.

Parameters:full (bool) – flag to indicate whether it should be used to visit only traversed nodes or the entire tree
Variables:full (bool) – flag to indicate whether it should be used to visit only traversed nodes or the entire tree
initialise()[source]

Override this method if any resetting of variables needs to be performed between ticks (i.e. visitations).

run(behaviour)[source]

This method gets run as each behaviour is ticked. Override it to perform some activity - e.g. introspect the behaviour to store/process logging data for visualisations.

Parameters:behaviour (Behaviour) – behaviour that is ticking
class py_trees.visitors.WindsOfChangeVisitor[source]

Bases: py_trees.visitors.VisitorBase

Visits the ticked part of a tree, checking off the status against the set of status results recorded in the previous tick. If there has been a change, it flags it. This is useful for determining when to trigger, e.g. logging.

Variables:
  • changed (Bool) – flagged if there is a difference in the visited path or Status of any behaviour on the path
  • ticked_nodes (dict) – dictionary of behaviour id (uuid.UUID) and status (Status) pairs from the current tick
  • previously_ticked+nodes (dict) – dictionary of behaviour id (uuid.UUID) and status (Status) pairs from the previous tick
  • running_nodes ([uuid.UUID]) – list of id’s for behaviours which were traversed in the current tick
  • previously_running_nodes ([uuid.UUID]) – list of id’s for behaviours which were traversed in the last tick

See also

The py-trees-demo-logging program demonstrates use of this visitor to trigger logging of a tree serialisation.

initialise()[source]

Switch running to previously running and then reset all other variables. This should get called before a tree ticks.

run(behaviour)[source]

This method gets run as each behaviour is ticked. Catch the id and status and store it. Additionally add it to the running list if it is RUNNING.

Parameters:behaviour (Behaviour) – behaviour that is ticking