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

The subsections below introduce each composite briefly. For a full listing of each composite’s methods, visit the py_trees.composites module api documentation.

Tip

First time through, make sure to follow the link through to relevant demo programs.

Sequence

class py_trees.composites.Sequence(name='Sequence', children=None, *args, **kwargs)[source]

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
  • *args – variable length argument list
  • **kwargs – arbitrary keyword arguments

Selector

class py_trees.composites.Selector(name='Selector', children=None, *args, **kwargs)[source]

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
  • *args – variable length argument list
  • **kwargs – arbitrary keyword arguments

Chooser

class py_trees.composites.Chooser(name='Chooser', children=None, *args, **kwargs)[source]

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
  • *args – variable length argument list
  • **kwargs – arbitrary keyword arguments

Parallel

class py_trees.composites.Parallel(name='Parallel', policy=<ParallelPolicy.SUCCESS_ON_ALL: 'SUCCESS_ON_ALL'>, children=None, *args, **kwargs)[source]

Parallels enable a kind of concurrency

digraph parallel {
graph [fontname="times-roman"];
node [fontname="times-roman"];
edge [fontname="times-roman"];
"Parallel" [fontcolor=black, shape=note, fontsize=11, style=filled, fillcolor=gold];
"B1" [fontcolor=black, shape=ellipse, fontsize=11, style=filled, fillcolor=gray];
"Parallel" -> "B1";
"B2" [fontcolor=black, shape=ellipse, fontsize=11, style=filled, fillcolor=gray];
"Parallel" -> "B2";
}

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

See also

The py-trees-demo-context-switching program demos a parallel used to assist in a context switching scenario.

Parameters:
  • name (str) – the composite behaviour name
  • policy (ParallelPolicy) – policy to use for deciding success or otherwise
  • children ([Behaviour]) – list of children to add
  • *args – variable length argument list
  • **kwargs – arbitrary keyword arguments