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.
This package provides a default reference implementation that is directly usable, but can also be easily used as inspiration for your own tree custodians.
The Behaviour Tree¶
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
The py-trees-demo-tree-stewardship program demonstrates the above features.
Behaviour) – root node of the tree
- 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
AssertionError– if incoming root variable is not the correct type
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#!/usr/bin/env python import py_trees if __name__ == '__main__': root = py_trees.composites.Selector("Selector") high = py_trees.behaviours.Success(name="High Priority") med = py_trees.behaviours.Success(name="Med Priority") low = py_trees.behaviours.Success(name="Low Priority") root.add_children([high, med, low]) behaviour_tree = py_trees.trees.BehaviourTree(root) behaviour_tree.setup(15) try: behaviour_tree.tick_tock( sleep_ms=500, number_of_iterations=py_trees.trees.CONTINUOUS_TICK_TOCK, pre_tick_handler=None, post_tick_handler=None ) except KeyboardInterrupt: behaviour_tree.interrupt()
or create your own loop and tick at your own leisure with
Pre/Post Tick Handlers¶
Pre and post tick handlers can be used to perform some activity on or with the tree
immediately before and after ticking. This is mostly useful with the continuous
This is useful for a variety of purposes:
- doing introspection on the tree to make reports
- extracting data from the blackboard
- triggering on external conditions to modify the tree (e.g. new plan arrived)
This can be done of course, without locking since the tree won’t be ticking while these handlers run. This does however, mean that your handlers should be light. They will be consuming time outside the regular tick period.
The py-trees-demo-tree-stewardship program demonstrates a very simple pre-tick handler that just prints a line to stdout notifying the user of the current run. The relevant code:
1 2 3 4 5 6 7 8 9 10 11
def pre_tick_handler(behaviour_tree): """ This prints a banner and will run immediately before every tick of the tree. Args: behaviour_tree (:class:`~py_trees.trees.BehaviourTree`): the tree custodian """ print("\n--------- Run %s ---------\n" % behaviour_tree.count)
# Rendering ####################
Visitors are entities that can be passed to a tree implementation
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.
Visitors should not modify the behaviours they visit.
The py-trees-demo-tree-stewardship program demonstrates the two reference visitor implementations:
DebugVisitorprints debug logging messages to stdout and
SnapshotVisitorcollects runtime data to be used by visualisations
Adding visitors to a tree:
behaviour_tree = py_trees.trees.BehaviourTree(root) behaviour_tree.visitors.append(py_trees.visitors.DebugVisitor()) snapshot_visitor = py_trees.visitors.SnapshotVisitor() behaviour_tree.visitors.append(snapshot_visitor)
These visitors are automatically run inside the tree’s
The former immediately logs to screen, the latter collects information which is then used to display an
behaviour_tree.tick() ascii_tree = py_trees.display.ascii_tree( behaviour_tree.root, snapshot_information=snapshot_visitor) ) print(ascii_tree)