初次创建仓库提交代码
1. 已经构建好了架子了。 2. 添加了示例的插件
This commit is contained in:
8
thirdparty/py_trees/demos/Readme.md
vendored
Normal file
8
thirdparty/py_trees/demos/Readme.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Guidelines
|
||||
|
||||
Each module here is a self-contained code sample for one of the demo scripts.
|
||||
That means there is a fair bit of copy and paste happening, but that is an
|
||||
intentional decision to ensure each demo script is self-contained and easy
|
||||
for beginners to follow and/or copy-paste from.
|
||||
|
||||
Keep this in mind when adding additional programs.
|
29
thirdparty/py_trees/demos/__init__.py
vendored
Normal file
29
thirdparty/py_trees/demos/__init__.py
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
This package contains py_trees demo script code.
|
||||
"""
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import os,sys
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)),'..','..'))
|
||||
from . import action
|
||||
from . import blackboard
|
||||
from . import blackboard_namespaces
|
||||
from . import blackboard_remappings
|
||||
from . import context_switching
|
||||
from . import display_modes
|
||||
from . import dot_graphs
|
||||
from . import either_or
|
||||
from . import lifecycle
|
||||
from . import selector
|
||||
from . import sequence
|
||||
from . import stewardship
|
179
thirdparty/py_trees/demos/action.py
vendored
Normal file
179
thirdparty/py_trees/demos/action.py
vendored
Normal file
@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.action
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-action-behaviour
|
||||
|
||||
.. image:: images/action.gif
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import atexit
|
||||
import multiprocessing
|
||||
import py_trees.common
|
||||
import time
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "Demonstrates the characteristics of a typical 'action' behaviour.\n"
|
||||
content += "\n"
|
||||
content += "* Mocks an external process and connects to it in the setup() method\n"
|
||||
content += "* Kickstarts new goals with the external process in the initialise() method\n"
|
||||
content += "* Monitors the ongoing goal status in the update() method\n"
|
||||
content += "* Determines RUNNING/SUCCESS pending feedback from the external process\n"
|
||||
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Action Behaviour".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
return argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
|
||||
def planning(pipe_connection):
|
||||
"""
|
||||
Emulates an external process which might accept long running planning jobs.
|
||||
"""
|
||||
idle = True
|
||||
percentage_complete = 0
|
||||
try:
|
||||
while(True):
|
||||
if pipe_connection.poll():
|
||||
pipe_connection.recv()
|
||||
percentage_complete = 0
|
||||
idle = False
|
||||
if not idle:
|
||||
percentage_complete += 10
|
||||
pipe_connection.send([percentage_complete])
|
||||
if percentage_complete == 100:
|
||||
idle = True
|
||||
time.sleep(0.5)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
|
||||
class Action(py_trees.behaviour.Behaviour):
|
||||
"""
|
||||
Connects to a subprocess to initiate a goal, and monitors the progress
|
||||
of that goal at each tick until the goal is completed, at which time
|
||||
the behaviour itself returns with success or failure (depending on
|
||||
success or failure of the goal itself).
|
||||
|
||||
This is typical of a behaviour that is connected to an external process
|
||||
responsible for driving hardware, conducting a plan, or a long running
|
||||
processing pipeline (e.g. planning/vision).
|
||||
|
||||
Key point - this behaviour itself should not be doing any work!
|
||||
"""
|
||||
def __init__(self, name="Action"):
|
||||
"""
|
||||
Default construction.
|
||||
"""
|
||||
super(Action, self).__init__(name)
|
||||
self.logger.debug("%s.__init__()" % (self.__class__.__name__))
|
||||
|
||||
def setup(self):
|
||||
"""
|
||||
No delayed initialisation required for this example.
|
||||
"""
|
||||
self.logger.debug("%s.setup()->connections to an external process" % (self.__class__.__name__))
|
||||
self.parent_connection, self.child_connection = multiprocessing.Pipe()
|
||||
self.planning = multiprocessing.Process(target=planning, args=(self.child_connection,))
|
||||
atexit.register(self.planning.terminate)
|
||||
self.planning.start()
|
||||
|
||||
def initialise(self):
|
||||
"""
|
||||
Reset a counter variable.
|
||||
"""
|
||||
self.logger.debug("%s.initialise()->sending new goal" % (self.__class__.__name__))
|
||||
self.parent_connection.send(['new goal'])
|
||||
self.percentage_completion = 0
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Increment the counter and decide upon a new status result for the behaviour.
|
||||
"""
|
||||
new_status = py_trees.common.Status.RUNNING
|
||||
if self.parent_connection.poll():
|
||||
self.percentage_completion = self.parent_connection.recv().pop()
|
||||
if self.percentage_completion == 100:
|
||||
new_status = py_trees.common.Status.SUCCESS
|
||||
if new_status == py_trees.common.Status.SUCCESS:
|
||||
self.feedback_message = "Processing finished"
|
||||
self.logger.debug("%s.update()[%s->%s][%s]" % (self.__class__.__name__, self.status, new_status, self.feedback_message))
|
||||
else:
|
||||
self.feedback_message = "{0}%".format(self.percentage_completion)
|
||||
self.logger.debug("%s.update()[%s][%s]" % (self.__class__.__name__, self.status, self.feedback_message))
|
||||
return new_status
|
||||
|
||||
def terminate(self, new_status):
|
||||
"""
|
||||
Nothing to clean up in this example.
|
||||
"""
|
||||
self.logger.debug("%s.terminate()[%s->%s]" % (self.__class__.__name__, self.status, new_status))
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
command_line_argument_parser().parse_args()
|
||||
|
||||
print(description())
|
||||
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
|
||||
action = Action()
|
||||
action.setup()
|
||||
try:
|
||||
for unused_i in range(0, 12):
|
||||
action.tick_once()
|
||||
time.sleep(0.5)
|
||||
print("\n")
|
||||
except KeyboardInterrupt:
|
||||
pass
|
241
thirdparty/py_trees/demos/blackboard.py
vendored
Normal file
241
thirdparty/py_trees/demos/blackboard.py
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.blackboard
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-blackboard
|
||||
|
||||
.. graphviz:: dot/demo-blackboard.dot
|
||||
:align: center
|
||||
:caption: Dot Graph
|
||||
|
||||
.. figure:: images/blackboard_demo.png
|
||||
:align: center
|
||||
|
||||
Console Screenshot
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import operator
|
||||
import py_trees
|
||||
import sys
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "Demonstrates usage of the blackboard and related behaviours.\n"
|
||||
content += "\n"
|
||||
content += "A sequence is populated with a few behaviours that exercise\n"
|
||||
content += "reading and writing on the Blackboard in interesting ways.\n"
|
||||
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Blackboard".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
render_group = parser.add_mutually_exclusive_group()
|
||||
render_group.add_argument('-r', '--render', action='store_true', help='render dot tree to file')
|
||||
render_group.add_argument(
|
||||
'--render-with-blackboard-variables',
|
||||
action='store_true',
|
||||
help='render dot tree to file with blackboard variables'
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
class Nested(object):
|
||||
"""
|
||||
A more complex object to interact with on the blackboard.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.foo = "bar"
|
||||
|
||||
def __str__(self):
|
||||
return str({"foo": self.foo})
|
||||
|
||||
|
||||
class BlackboardWriter(py_trees.behaviour.Behaviour):
|
||||
"""
|
||||
Custom writer that submits a more complicated variable to the blackboard.
|
||||
"""
|
||||
def __init__(self, name="Writer"):
|
||||
super().__init__(name=name)
|
||||
self.blackboard = self.attach_blackboard_client()
|
||||
self.blackboard.register_key(key="dude", access=py_trees.common.Access.READ)
|
||||
self.blackboard.register_key(key="spaghetti", access=py_trees.common.Access.WRITE)
|
||||
|
||||
self.logger.debug("%s.__init__()" % (self.__class__.__name__))
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Write a dictionary to the blackboard and return :data:`~py_trees.common.Status.SUCCESS`.
|
||||
"""
|
||||
self.logger.debug("%s.update()" % (self.__class__.__name__))
|
||||
try:
|
||||
unused = self.blackboard.dude
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
unused = self.blackboard.dudette
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
self.blackboard.dudette = "Jane"
|
||||
except AttributeError:
|
||||
pass
|
||||
self.blackboard.spaghetti = {"type": "Carbonara", "quantity": 1}
|
||||
self.blackboard.spaghetti = {"type": "Gnocchi", "quantity": 2}
|
||||
try:
|
||||
self.blackboard.set("spaghetti", {"type": "Bolognese", "quantity": 3}, overwrite=False)
|
||||
except AttributeError:
|
||||
pass
|
||||
return py_trees.common.Status.SUCCESS
|
||||
|
||||
|
||||
class ParamsAndState(py_trees.behaviour.Behaviour):
|
||||
"""
|
||||
A more esotoric use of multiple blackboards in a behaviour to represent
|
||||
storage of parameters and state.
|
||||
"""
|
||||
def __init__(self, name="ParamsAndState"):
|
||||
super().__init__(name=name)
|
||||
# namespaces can include the separator or may leave it out
|
||||
# they can also be nested, e.g. /agent/state, /agent/parameters
|
||||
self.parameters = self.attach_blackboard_client("Params", "parameters")
|
||||
self.state = self.attach_blackboard_client("State", "state")
|
||||
self.parameters.register_key(
|
||||
key="default_speed",
|
||||
access=py_trees.common.Access.READ
|
||||
)
|
||||
self.state.register_key(
|
||||
key="current_speed",
|
||||
access=py_trees.common.Access.WRITE
|
||||
)
|
||||
|
||||
def initialise(self):
|
||||
try:
|
||||
self.state.current_speed = self.parameters.default_speed
|
||||
except KeyError as e:
|
||||
raise RuntimeError("parameter 'default_speed' not found [{}]".format(str(e)))
|
||||
|
||||
def update(self):
|
||||
if self.state.current_speed > 40.0:
|
||||
return py_trees.common.Status.SUCCESS
|
||||
else:
|
||||
self.state.current_speed += 1.0
|
||||
return py_trees.common.Status.RUNNING
|
||||
|
||||
|
||||
def create_root():
|
||||
root = py_trees.composites.Sequence("Blackboard Demo")
|
||||
set_blackboard_variable = py_trees.behaviours.SetBlackboardVariable(
|
||||
name="Set Nested", variable_name="nested", variable_value=Nested()
|
||||
)
|
||||
write_blackboard_variable = BlackboardWriter(name="Writer")
|
||||
check_blackboard_variable = py_trees.behaviours.CheckBlackboardVariableValue(
|
||||
name="Check Nested Foo",
|
||||
check=py_trees.common.ComparisonExpression(
|
||||
variable="nested.foo",
|
||||
value="bar",
|
||||
operator=operator.eq
|
||||
)
|
||||
)
|
||||
params_and_state = ParamsAndState()
|
||||
root.add_children([
|
||||
set_blackboard_variable,
|
||||
write_blackboard_variable,
|
||||
check_blackboard_variable,
|
||||
params_and_state
|
||||
])
|
||||
return root
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
print(description())
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
py_trees.blackboard.Blackboard.enable_activity_stream(maximum_size=100)
|
||||
blackboard = py_trees.blackboard.Client(name="Configuration")
|
||||
blackboard.register_key(key="dude", access=py_trees.common.Access.WRITE)
|
||||
blackboard.register_key(key="/parameters/default_speed", access=py_trees.common.Access.WRITE)
|
||||
blackboard.dude = "Bob"
|
||||
blackboard.parameters.default_speed = 30.0
|
||||
|
||||
root = create_root()
|
||||
|
||||
####################
|
||||
# Rendering
|
||||
####################
|
||||
if args.render:
|
||||
py_trees.display.render_dot_tree(root, with_blackboard_variables=False)
|
||||
sys.exit()
|
||||
if args.render_with_blackboard_variables:
|
||||
py_trees.display.render_dot_tree(root, with_blackboard_variables=True)
|
||||
sys.exit()
|
||||
|
||||
####################
|
||||
# Execute
|
||||
####################
|
||||
root.setup_with_descendants()
|
||||
unset_blackboard = py_trees.blackboard.Client(name="Unsetter")
|
||||
unset_blackboard.register_key(key="foo", access=py_trees.common.Access.WRITE)
|
||||
print("\n--------- Tick 0 ---------\n")
|
||||
root.tick_once()
|
||||
print("\n")
|
||||
print(py_trees.display.unicode_tree(root, show_status=True))
|
||||
print("--------------------------\n")
|
||||
print(py_trees.display.unicode_blackboard())
|
||||
print("--------------------------\n")
|
||||
print(py_trees.display.unicode_blackboard(display_only_key_metadata=True))
|
||||
print("--------------------------\n")
|
||||
unset_blackboard.unset("foo")
|
||||
print(py_trees.display.unicode_blackboard_activity_stream())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
129
thirdparty/py_trees/demos/blackboard_namespaces.py
vendored
Normal file
129
thirdparty/py_trees/demos/blackboard_namespaces.py
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.blackboard_namespaces
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-blackboard-namespaces
|
||||
|
||||
.. figure:: images/blackboard_namespaces.png
|
||||
:align: center
|
||||
|
||||
Console Screenshot
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import py_trees
|
||||
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "Demonstrates usage of blackboard namespaces.\n"
|
||||
content += "\n"
|
||||
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Blackboard".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
unused_args = command_line_argument_parser().parse_args()
|
||||
print(description())
|
||||
print("-------------------------------------------------------------------------------")
|
||||
print("$ py_trees.blackboard.Client(name='Blackboard')")
|
||||
print("$ foo.register_key(key='dude', access=py_trees.common.Access.WRITE)")
|
||||
print("$ foo.register_key(key='/dudette', access=py_trees.common.Access.WRITE)")
|
||||
print("$ foo.register_key(key='/foo/bar/wow', access=py_trees.common.Access.WRITE)")
|
||||
print("-------------------------------------------------------------------------------")
|
||||
blackboard = py_trees.blackboard.Client(name="Blackboard")
|
||||
blackboard.register_key(key="dude", access=py_trees.common.Access.WRITE)
|
||||
blackboard.register_key(key="/dudette", access=py_trees.common.Access.WRITE)
|
||||
blackboard.register_key(key="/foo/bar/wow", access=py_trees.common.Access.WRITE)
|
||||
print(blackboard)
|
||||
print("-------------------------------------------------------------------------------")
|
||||
print("$ blackboard.dude = 'Bob'")
|
||||
print("$ blackboard.dudette = 'Jade'")
|
||||
print("-------------------------------------------------------------------------------")
|
||||
blackboard.dude = "Bob"
|
||||
blackboard.dudette = "Jade"
|
||||
print(py_trees.display.unicode_blackboard())
|
||||
print("-------------------------------------------------------------------------------")
|
||||
print("$ blackboard.foo.bar.wow = 'foobar'")
|
||||
print("-------------------------------------------------------------------------------")
|
||||
blackboard.foo.bar.wow = "foobar"
|
||||
print(py_trees.display.unicode_blackboard())
|
||||
print("-------------------------------------------------------------------------------")
|
||||
print("$ py_trees.blackboard.Client(name='Foo', namespace='foo')")
|
||||
print("$ foo.register_key(key='awesome', access=py_trees.common.Access.WRITE)")
|
||||
print("$ foo.register_key(key='/brilliant', access=py_trees.common.Access.WRITE)")
|
||||
print("$ foo.register_key(key='/foo/clever', access=py_trees.common.Access.WRITE)")
|
||||
print("-------------------------------------------------------------------------------")
|
||||
foo = py_trees.blackboard.Client(name="Foo", namespace="foo")
|
||||
foo.register_key(key="awesome", access=py_trees.common.Access.WRITE)
|
||||
# TODO: should /brilliant be namespaced or go directly to root?
|
||||
foo.register_key(key="/brilliant", access=py_trees.common.Access.WRITE)
|
||||
# absolute names are ok, so long as they include the namespace
|
||||
foo.register_key(key="/foo/clever", access=py_trees.common.Access.WRITE)
|
||||
print(foo)
|
||||
print("-------------------------------------------------------------------------------")
|
||||
print("$ foo.awesome = True")
|
||||
print("$ foo.set('/brilliant', False)")
|
||||
print("$ foo.clever = True")
|
||||
print("-------------------------------------------------------------------------------")
|
||||
foo.awesome = True
|
||||
# Only accessable via set since it's not in the namespace
|
||||
foo.set("/brilliant", False)
|
||||
# This will fail since it looks for the namespaced /foo/brilliant key
|
||||
# foo.brilliant = False
|
||||
foo.clever = True
|
||||
print(py_trees.display.unicode_blackboard())
|
116
thirdparty/py_trees/demos/blackboard_remappings.py
vendored
Normal file
116
thirdparty/py_trees/demos/blackboard_remappings.py
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.blackboard_remappings
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-blackboard-remappings
|
||||
|
||||
.. figure:: images/blackboard_remappings.png
|
||||
:align: center
|
||||
|
||||
Console Screenshot
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import py_trees
|
||||
import typing
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "Demonstrates usage of blackbord remappings.\n"
|
||||
content += "\n"
|
||||
content += "Demonstration is via an exemplar behaviour making use of remappings..\n"
|
||||
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Blackboard".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
class Remap(py_trees.behaviour.Behaviour):
|
||||
"""
|
||||
Custom writer that submits a more complicated variable to the blackboard.
|
||||
"""
|
||||
def __init__(self, name: str, remap_to: typing.Dict[str, str]):
|
||||
super().__init__(name=name)
|
||||
self.logger.debug("%s.__init__()" % (self.__class__.__name__))
|
||||
self.blackboard = self.attach_blackboard_client()
|
||||
self.blackboard.register_key(
|
||||
key="/foo/bar/wow",
|
||||
access=py_trees.common.Access.WRITE,
|
||||
remap_to=remap_to["/foo/bar/wow"]
|
||||
)
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Write a dictionary to the blackboard and return :data:`~py_trees.common.Status.SUCCESS`.
|
||||
"""
|
||||
self.logger.debug("%s.update()" % (self.__class__.__name__))
|
||||
self.blackboard.foo.bar.wow = "colander"
|
||||
|
||||
return py_trees.common.Status.SUCCESS
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
print(description())
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
py_trees.blackboard.Blackboard.enable_activity_stream(maximum_size=100)
|
||||
root = Remap(name="Remap", remap_to={"/foo/bar/wow": "/parameters/wow"})
|
||||
|
||||
####################
|
||||
# Execute
|
||||
####################
|
||||
root.tick_once()
|
||||
print(root.blackboard)
|
||||
print(py_trees.display.unicode_blackboard())
|
||||
print(py_trees.display.unicode_blackboard_activity_stream())
|
173
thirdparty/py_trees/demos/context_switching.py
vendored
Normal file
173
thirdparty/py_trees/demos/context_switching.py
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.context_switching
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-context-switching
|
||||
|
||||
.. graphviz:: dot/demo-context_switching.dot
|
||||
|
||||
.. image:: images/context_switching.gif
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import py_trees
|
||||
import sys
|
||||
import time
|
||||
|
||||
import os,sys
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "Demonstrates context switching with parallels and sequences.\n"
|
||||
content += "\n"
|
||||
content += "A context switching behaviour is run in parallel with a work sequence.\n"
|
||||
content += "Switching the context occurs in the initialise() and terminate() methods\n"
|
||||
content += "of the context switching behaviour. Note that whether the sequence results\n"
|
||||
content += "in failure or success, the context switch behaviour will always call the\n"
|
||||
content += "terminate() method to restore the context. It will also call terminate()\n"
|
||||
content += "to restore the context in the event of a higher priority parent cancelling\n"
|
||||
content += "this parallel subtree.\n"
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Context Switching".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument('-r', '--render', action='store_true', help='render dot tree to file')
|
||||
return parser
|
||||
|
||||
|
||||
class ContextSwitch(py_trees.behaviour.Behaviour):
|
||||
"""
|
||||
An example of a context switching class that sets (in ``initialise()``)
|
||||
and restores a context (in ``terminate()``). Use in parallel with a
|
||||
sequence/subtree that does the work while in this context.
|
||||
|
||||
.. attention:: Simply setting a pair of behaviours (set and reset context) on
|
||||
either end of a sequence will not suffice for context switching. In the case
|
||||
that one of the work behaviours in the sequence fails, the final reset context
|
||||
switch will never trigger.
|
||||
|
||||
"""
|
||||
def __init__(self, name="ContextSwitch"):
|
||||
super(ContextSwitch, self).__init__(name)
|
||||
self.feedback_message = "no context"
|
||||
|
||||
def initialise(self):
|
||||
"""
|
||||
Backup and set a new context.
|
||||
"""
|
||||
self.logger.debug("%s.initialise()[switch context]" % (self.__class__.__name__))
|
||||
# Some actions that:
|
||||
# 1. retrieve the current context from somewhere
|
||||
# 2. cache the context internally
|
||||
# 3. apply a new context
|
||||
self.feedback_message = "new context"
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Just returns RUNNING while it waits for other activities to finish.
|
||||
"""
|
||||
self.logger.debug("%s.update()[RUNNING][%s]" % (self.__class__.__name__, self.feedback_message))
|
||||
return py_trees.common.Status.RUNNING
|
||||
|
||||
def terminate(self, new_status):
|
||||
"""
|
||||
Restore the context with the previously backed up context.
|
||||
"""
|
||||
self.logger.debug("%s.terminate()[%s->%s][restore context]" % (self.__class__.__name__, self.status, new_status))
|
||||
# Some actions that:
|
||||
# 1. restore the cached context
|
||||
self.feedback_message = "restored context"
|
||||
|
||||
|
||||
def create_root():
|
||||
root = py_trees.composites.Parallel(name="Parallel", policy=py_trees.common.ParallelPolicy.SuccessOnOne())
|
||||
context_switch = ContextSwitch(name="Context")
|
||||
sequence = py_trees.composites.Sequence(name="Sequence")
|
||||
for job in ["Action 1", "Action 2"]:
|
||||
success_after_two = py_trees.behaviours.Count(name=job,
|
||||
fail_until=0,
|
||||
running_until=2,
|
||||
success_until=10)
|
||||
sequence.add_child(success_after_two)
|
||||
root.add_child(context_switch)
|
||||
root.add_child(sequence)
|
||||
return root
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
print(description())
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
|
||||
root = create_root()
|
||||
|
||||
####################
|
||||
# Rendering
|
||||
####################
|
||||
if args.render:
|
||||
py_trees.display.render_dot_tree(root)
|
||||
sys.exit()
|
||||
|
||||
####################
|
||||
# Execute
|
||||
####################
|
||||
root.setup_with_descendants()
|
||||
for i in range(1, 6):
|
||||
try:
|
||||
print("\n--------- Tick {0} ---------\n".format(i))
|
||||
root.tick_once()
|
||||
print("\n")
|
||||
print("{}".format(py_trees.display.unicode_tree(root, show_status=True)))
|
||||
time.sleep(1.0)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
print("\n")
|
132
thirdparty/py_trees/demos/display_modes.py
vendored
Normal file
132
thirdparty/py_trees/demos/display_modes.py
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.display_modes
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-display-modes
|
||||
|
||||
.. figure:: images/display_modes.png
|
||||
:align: center
|
||||
|
||||
Console Screenshot
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import itertools
|
||||
import py_trees
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "Demonstrates usage of the ascii/unicode display modes.\n"
|
||||
content += "\n"
|
||||
content += "...\n"
|
||||
content += "...\n"
|
||||
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Display Modes".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def create_root() -> py_trees.behaviour.Behaviour:
|
||||
"""
|
||||
Create the tree to be ticked/displayed.
|
||||
|
||||
Returns:
|
||||
the root of the tree
|
||||
"""
|
||||
root = py_trees.composites.Sequence(name="root")
|
||||
child = py_trees.composites.Sequence(name="child1")
|
||||
child2 = py_trees.composites.Sequence(name="child2")
|
||||
child3 = py_trees.composites.Sequence(name="child3")
|
||||
root.add_child(child)
|
||||
root.add_child(child2)
|
||||
root.add_child(child3)
|
||||
|
||||
child.add_child(py_trees.behaviours.Count(name='Count', fail_until=0, running_until=1, success_until=6,))
|
||||
child2.add_child(py_trees.behaviours.Count(name='Count', fail_until=0, running_until=1, success_until=6,))
|
||||
child2_child1 = py_trees.composites.Sequence(name="Child2_child1")
|
||||
child2_child1.add_child(py_trees.behaviours.Count(name='Count', fail_until=0, running_until=1, success_until=6,))
|
||||
child2.add_child(child2_child1)
|
||||
child3.add_child(py_trees.behaviours.Count(name='Count', fail_until=0, running_until=1, success_until=6,))
|
||||
return root
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
unused_args = command_line_argument_parser().parse_args()
|
||||
print(description())
|
||||
print("-------------------------------------------------------------------------------")
|
||||
print("$ py_trees.blackboard.Client(name='Blackboard')")
|
||||
print("$ foo.register_key(key='dude', access=py_trees.common.Access.WRITE)")
|
||||
print("$ foo.register_key(key='/dudette', access=py_trees.common.Access.WRITE)")
|
||||
print("$ foo.register_key(key='/foo/bar/wow', access=py_trees.common.Access.WRITE)")
|
||||
print("-------------------------------------------------------------------------------")
|
||||
|
||||
snapshot_visitor = py_trees.visitors.SnapshotVisitor()
|
||||
tree = py_trees.trees.BehaviourTree(create_root())
|
||||
tree.add_visitor(snapshot_visitor)
|
||||
|
||||
for tick in range(2):
|
||||
tree.tick()
|
||||
for show_visited, show_status in itertools.product([False, True], [False, True]):
|
||||
console.banner("Tick {} / show_only_visited=={} / show_status=={}".format(tick, show_visited, show_status))
|
||||
print(
|
||||
py_trees.display.unicode_tree(
|
||||
tree.root,
|
||||
show_status=show_status,
|
||||
show_only_visited=show_visited,
|
||||
visited=snapshot_visitor.visited,
|
||||
previously_visited=snapshot_visitor.previously_visited
|
||||
)
|
||||
)
|
||||
print()
|
131
thirdparty/py_trees/demos/dot_graphs.py
vendored
Normal file
131
thirdparty/py_trees/demos/dot_graphs.py
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.dot_graphs
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-dot-graphs
|
||||
|
||||
.. graphviz:: dot/demo-dot-graphs.dot
|
||||
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
import py_trees
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
name = "py-trees-demo-dot-graphs"
|
||||
content = "Renders a dot graph for a simple tree, with blackboxes.\n"
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Dot Graphs".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += console.white
|
||||
s += console.bold + " Generate Full Dot Graph" + console.reset + "\n"
|
||||
s += "\n"
|
||||
s += console.cyan + " {0}".format(name) + console.reset + "\n"
|
||||
s += "\n"
|
||||
s += console.bold + " With Varying Visibility Levels" + console.reset + "\n"
|
||||
s += "\n"
|
||||
s += console.cyan + " {0}".format(name) + console.yellow + " --level=all" + console.reset + "\n"
|
||||
s += console.cyan + " {0}".format(name) + console.yellow + " --level=detail" + console.reset + "\n"
|
||||
s += console.cyan + " {0}".format(name) + console.yellow + " --level=component" + console.reset + "\n"
|
||||
s += console.cyan + " {0}".format(name) + console.yellow + " --level=big_picture" + console.reset + "\n"
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument('-l', '--level', action='store',
|
||||
default='fine_detail',
|
||||
choices=['all', 'fine_detail', 'detail', 'component', 'big_picture'],
|
||||
help='visibility level')
|
||||
return parser
|
||||
|
||||
|
||||
def create_tree(level):
|
||||
root = py_trees.composites.Selector("Demo Dot Graphs %s" % level)
|
||||
first_blackbox = py_trees.composites.Sequence("BlackBox 1")
|
||||
first_blackbox.add_child(py_trees.behaviours.Running("Worker"))
|
||||
first_blackbox.add_child(py_trees.behaviours.Running("Worker"))
|
||||
first_blackbox.add_child(py_trees.behaviours.Running("Worker"))
|
||||
first_blackbox.blackbox_level = py_trees.common.BlackBoxLevel.BIG_PICTURE
|
||||
second_blackbox = py_trees.composites.Sequence("Blackbox 2")
|
||||
second_blackbox.add_child(py_trees.behaviours.Running("Worker"))
|
||||
second_blackbox.add_child(py_trees.behaviours.Running("Worker"))
|
||||
second_blackbox.add_child(py_trees.behaviours.Running("Worker"))
|
||||
second_blackbox.blackbox_level = py_trees.common.BlackBoxLevel.COMPONENT
|
||||
third_blackbox = py_trees.composites.Sequence("Blackbox 3")
|
||||
third_blackbox.add_child(py_trees.behaviours.Running("Worker"))
|
||||
third_blackbox.add_child(py_trees.behaviours.Running("Worker"))
|
||||
third_blackbox.add_child(py_trees.behaviours.Running("Worker"))
|
||||
third_blackbox.blackbox_level = py_trees.common.BlackBoxLevel.DETAIL
|
||||
root.add_child(first_blackbox)
|
||||
root.add_child(second_blackbox)
|
||||
first_blackbox.add_child(third_blackbox)
|
||||
return root
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
args.enum_level = py_trees.common.string_to_visibility_level(args.level)
|
||||
print(description())
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
|
||||
root = create_tree(args.level)
|
||||
py_trees.display.render_dot_tree(root, args.enum_level)
|
||||
|
||||
if py_trees.utilities.which("xdot"):
|
||||
try:
|
||||
subprocess.call(["xdot", "demo_dot_graphs_%s.dot" % args.level])
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
else:
|
||||
print("")
|
||||
console.logerror("No xdot viewer found, skipping display [hint: sudo apt install xdot]")
|
||||
print("")
|
213
thirdparty/py_trees/demos/either_or.py
vendored
Normal file
213
thirdparty/py_trees/demos/either_or.py
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.either_or
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-either-or
|
||||
|
||||
.. graphviz:: dot/demo-either-or.dot
|
||||
|
||||
.. image:: images/either_or.gif
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import operator
|
||||
import py_trees
|
||||
import sys
|
||||
import time
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description(root):
|
||||
content = "A demonstration of the 'either_or' idiom.\n\n"
|
||||
content += "This behaviour tree pattern enables triggering of subtrees\n"
|
||||
content += "with equal priority (first in, first served).\n"
|
||||
content += "\n"
|
||||
content += "EVENTS\n"
|
||||
content += "\n"
|
||||
content += " - 3 : joystick one enabled, task one starts\n"
|
||||
content += " - 5 : task one finishes\n"
|
||||
content += " - 6 : joystick two enabled, task two starts\n"
|
||||
content += " - 7 : joystick one enabled, task one ignored, task two continues\n"
|
||||
content += " - 8 : task two finishes\n"
|
||||
content += "\n"
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Either Or".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(create_root()),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('-r', '--render', action='store_true', help='render dot tree to file')
|
||||
group.add_argument('-i', '--interactive', action='store_true', help='pause and wait for keypress at each tick')
|
||||
return parser
|
||||
|
||||
|
||||
def pre_tick_handler(behaviour_tree):
|
||||
print("\n--------- Run %s ---------\n" % behaviour_tree.count)
|
||||
|
||||
|
||||
def post_tick_handler(snapshot_visitor, behaviour_tree):
|
||||
print(
|
||||
"\n" + py_trees.display.unicode_tree(
|
||||
root=behaviour_tree.root,
|
||||
visited=snapshot_visitor.visited,
|
||||
previously_visited=snapshot_visitor.previously_visited
|
||||
)
|
||||
)
|
||||
print(py_trees.display.unicode_blackboard())
|
||||
|
||||
|
||||
def create_root():
|
||||
trigger_one = py_trees.decorators.FailureIsRunning(
|
||||
name="FisR",
|
||||
child=py_trees.behaviours.SuccessEveryN(
|
||||
name="Joystick 1",
|
||||
n=4
|
||||
)
|
||||
)
|
||||
trigger_two = py_trees.decorators.FailureIsRunning(
|
||||
name="FisR",
|
||||
child=py_trees.behaviours.SuccessEveryN(
|
||||
name="Joystick 2",
|
||||
n=7
|
||||
)
|
||||
)
|
||||
enable_joystick_one = py_trees.behaviours.SetBlackboardVariable(
|
||||
name="Joy1 - Enabled",
|
||||
variable_name="joystick_one",
|
||||
variable_value="enabled")
|
||||
enable_joystick_two = py_trees.behaviours.SetBlackboardVariable(
|
||||
name="Joy2 - Enabled",
|
||||
variable_name="joystick_two",
|
||||
variable_value="enabled")
|
||||
reset_joystick_one = py_trees.behaviours.SetBlackboardVariable(
|
||||
name="Joy1 - Disabled",
|
||||
variable_name="joystick_one",
|
||||
variable_value="disabled")
|
||||
reset_joystick_two = py_trees.behaviours.SetBlackboardVariable(
|
||||
name="Joy2 - Disabled",
|
||||
variable_name="joystick_two",
|
||||
variable_value="disabled")
|
||||
task_one = py_trees.behaviours.TickCounter(
|
||||
name="Task 1",
|
||||
duration=2,
|
||||
completion_status=py_trees.common.Status.SUCCESS
|
||||
)
|
||||
task_two = py_trees.behaviours.TickCounter(
|
||||
name="Task 2",
|
||||
duration=2,
|
||||
completion_status=py_trees.common.Status.SUCCESS
|
||||
)
|
||||
idle = py_trees.behaviours.Running(name="Idle")
|
||||
either_or = py_trees.idioms.either_or(
|
||||
name="Either Or",
|
||||
conditions=[
|
||||
py_trees.common.ComparisonExpression("joystick_one", "enabled", operator.eq),
|
||||
py_trees.common.ComparisonExpression("joystick_two", "enabled", operator.eq),
|
||||
],
|
||||
subtrees=[task_one, task_two],
|
||||
namespace="either_or",
|
||||
)
|
||||
root = py_trees.composites.Parallel(
|
||||
name="Root",
|
||||
policy=py_trees.common.ParallelPolicy.SuccessOnAll(synchronise=False)
|
||||
)
|
||||
reset = py_trees.composites.Sequence(name="Reset")
|
||||
reset.add_children([reset_joystick_one, reset_joystick_two])
|
||||
joystick_one_events = py_trees.composites.Sequence(name="Joy1 Events")
|
||||
joystick_one_events.add_children([trigger_one, enable_joystick_one])
|
||||
joystick_two_events = py_trees.composites.Sequence(name="Joy2 Events")
|
||||
joystick_two_events.add_children([trigger_two, enable_joystick_two])
|
||||
tasks = py_trees.composites.Selector(name="Tasks")
|
||||
tasks.add_children([either_or, idle])
|
||||
root.add_children([reset, joystick_one_events, joystick_two_events, tasks])
|
||||
return root
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
# py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
root = create_root()
|
||||
print(description(root))
|
||||
|
||||
####################
|
||||
# Rendering
|
||||
####################
|
||||
if args.render:
|
||||
py_trees.display.render_dot_tree(root)
|
||||
sys.exit()
|
||||
|
||||
####################
|
||||
# Tree Stewardship
|
||||
####################
|
||||
behaviour_tree = py_trees.trees.BehaviourTree(root)
|
||||
behaviour_tree.add_pre_tick_handler(pre_tick_handler)
|
||||
behaviour_tree.visitors.append(py_trees.visitors.DebugVisitor())
|
||||
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)
|
||||
behaviour_tree.setup(timeout=15)
|
||||
|
||||
####################
|
||||
# Tick Tock
|
||||
####################
|
||||
if args.interactive:
|
||||
py_trees.console.read_single_keypress()
|
||||
for unused_i in range(1, 11):
|
||||
try:
|
||||
behaviour_tree.tick()
|
||||
if args.interactive:
|
||||
py_trees.console.read_single_keypress()
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
print("\n")
|
27079
thirdparty/py_trees/demos/get-pip.py
vendored
Normal file
27079
thirdparty/py_trees/demos/get-pip.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
140
thirdparty/py_trees/demos/lifecycle.py
vendored
Normal file
140
thirdparty/py_trees/demos/lifecycle.py
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.lifecycle
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-behaviour-lifecycle
|
||||
|
||||
.. image:: images/lifecycle.gif
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import py_trees
|
||||
import time
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "Demonstrates a typical day in the life of a behaviour.\n\n"
|
||||
content += "This behaviour will count from 1 to 3 and then reset and repeat. As it does\n"
|
||||
content += "so, it logs and displays the methods as they are called - construction, setup,\n"
|
||||
content += "initialisation, ticking and termination.\n"
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Behaviour Lifecycle".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
return argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
|
||||
class Counter(py_trees.behaviour.Behaviour):
|
||||
"""
|
||||
Simple counting behaviour that facilitates the demonstration of a behaviour in
|
||||
the demo behaviours lifecycle program.
|
||||
|
||||
* Increments a counter from zero at each tick
|
||||
* Finishes with success if the counter reaches three
|
||||
* Resets the counter in the initialise() method.
|
||||
"""
|
||||
def __init__(self, name="Counter"):
|
||||
"""
|
||||
Default construction.
|
||||
"""
|
||||
super(Counter, self).__init__(name)
|
||||
self.logger.debug("%s.__init__()" % (self.__class__.__name__))
|
||||
|
||||
def setup(self):
|
||||
"""
|
||||
No delayed initialisation required for this example.
|
||||
"""
|
||||
self.logger.debug("%s.setup()" % (self.__class__.__name__))
|
||||
|
||||
def initialise(self):
|
||||
"""
|
||||
Reset a counter variable.
|
||||
"""
|
||||
self.logger.debug("%s.initialise()" % (self.__class__.__name__))
|
||||
self.counter = 0
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Increment the counter and decide upon a new status result for the behaviour.
|
||||
"""
|
||||
self.counter += 1
|
||||
new_status = py_trees.common.Status.SUCCESS if self.counter == 3 else py_trees.common.Status.RUNNING
|
||||
if new_status == py_trees.common.Status.SUCCESS:
|
||||
self.feedback_message = "counting...{0} - phew, thats enough for today".format(self.counter)
|
||||
else:
|
||||
self.feedback_message = "still counting"
|
||||
self.logger.debug("%s.update()[%s->%s][%s]" % (self.__class__.__name__, self.status, new_status, self.feedback_message))
|
||||
return new_status
|
||||
|
||||
def terminate(self, new_status):
|
||||
"""
|
||||
Nothing to clean up in this example.
|
||||
"""
|
||||
self.logger.debug("%s.terminate()[%s->%s]" % (self.__class__.__name__, self.status, new_status))
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
command_line_argument_parser().parse_args()
|
||||
|
||||
print(description())
|
||||
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
|
||||
counter = Counter()
|
||||
counter.setup()
|
||||
try:
|
||||
for unused_i in range(0, 7):
|
||||
counter.tick_once()
|
||||
time.sleep(0.5)
|
||||
print("\n")
|
||||
except KeyboardInterrupt:
|
||||
print("")
|
||||
pass
|
192
thirdparty/py_trees/demos/logging.py
vendored
Normal file
192
thirdparty/py_trees/demos/logging.py
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.logging
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-logging
|
||||
|
||||
.. graphviz:: dot/demo-logging.dot
|
||||
|
||||
.. image:: images/logging.gif
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import json
|
||||
import py_trees
|
||||
import sys
|
||||
import time
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description(root):
|
||||
content = "A demonstration of logging with trees.\n\n"
|
||||
content += "This demo utilises a SnapshotVisitor to trigger\n"
|
||||
content += "a post-tick handler to dump a serialisation of the\n"
|
||||
content += "tree to a json log file.\n"
|
||||
content += "\n"
|
||||
content += "This coupling of visitor and post-tick handler can be\n"
|
||||
content += "used for any kind of event handling - the visitor is the\n"
|
||||
content += "trigger and the post-tick handler the action. Aside from\n"
|
||||
content += "logging, the most common use case is to serialise the tree\n"
|
||||
content += "for messaging to a graphical, runtime monitor.\n"
|
||||
content += "\n"
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Logging".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(create_tree()),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('-r', '--render', action='store_true', help='render dot tree to file')
|
||||
group.add_argument('-i', '--interactive', action='store_true', help='pause and wait for keypress at each tick')
|
||||
return parser
|
||||
|
||||
|
||||
def logger(snapshot_visitor, behaviour_tree):
|
||||
"""
|
||||
A post-tick handler that logs the tree (relevant parts thereof) to a yaml file.
|
||||
"""
|
||||
if snapshot_visitor.changed:
|
||||
print(console.cyan + "Logging.......................yes\n" + console.reset)
|
||||
tree_serialisation = {
|
||||
'tick': behaviour_tree.count,
|
||||
'nodes': []
|
||||
}
|
||||
for node in behaviour_tree.root.iterate():
|
||||
node_type_str = "Behaviour"
|
||||
for behaviour_type in [py_trees.composites.Sequence,
|
||||
py_trees.composites.Selector,
|
||||
py_trees.composites.Parallel,
|
||||
py_trees.decorators.Decorator]:
|
||||
if isinstance(node, behaviour_type):
|
||||
node_type_str = behaviour_type.__name__
|
||||
node_snapshot = {
|
||||
'name': node.name,
|
||||
'id': str(node.id),
|
||||
'parent_id': str(node.parent.id) if node.parent else "none",
|
||||
'child_ids': [str(child.id) for child in node.children],
|
||||
'tip_id': str(node.tip().id) if node.tip() else 'none',
|
||||
'class_name': str(node.__module__) + '.' + str(type(node).__name__),
|
||||
'type': node_type_str,
|
||||
'status': node.status.value,
|
||||
'message': node.feedback_message,
|
||||
'is_active': True if node.id in snapshot_visitor.visited else False
|
||||
}
|
||||
tree_serialisation['nodes'].append(node_snapshot)
|
||||
if behaviour_tree.count == 0:
|
||||
with open('dump.json', 'w+') as outfile:
|
||||
json.dump(tree_serialisation, outfile, indent=4)
|
||||
else:
|
||||
with open('dump.json', 'a') as outfile:
|
||||
json.dump(tree_serialisation, outfile, indent=4)
|
||||
else:
|
||||
print(console.yellow + "Logging.......................no\n" + console.reset)
|
||||
|
||||
|
||||
def create_tree():
|
||||
every_n_success = py_trees.behaviours.SuccessEveryN("EveryN", 5)
|
||||
sequence = py_trees.composites.Sequence(name="Sequence")
|
||||
guard = py_trees.behaviours.Success("Guard")
|
||||
periodic_success = py_trees.behaviours.Periodic("Periodic", 3)
|
||||
finisher = py_trees.behaviours.Success("Finisher")
|
||||
sequence.add_child(guard)
|
||||
sequence.add_child(periodic_success)
|
||||
sequence.add_child(finisher)
|
||||
sequence.blackbox_level = py_trees.common.BlackBoxLevel.COMPONENT
|
||||
idle = py_trees.behaviours.Success("Idle")
|
||||
root = py_trees.composites.Selector(name="Logging")
|
||||
root.add_child(every_n_success)
|
||||
root.add_child(sequence)
|
||||
root.add_child(idle)
|
||||
return root
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
tree = create_tree()
|
||||
print(description(tree))
|
||||
|
||||
####################
|
||||
# Rendering
|
||||
####################
|
||||
if args.render:
|
||||
py_trees.display.render_dot_tree(tree)
|
||||
sys.exit()
|
||||
|
||||
####################
|
||||
# Tree Stewardship
|
||||
####################
|
||||
behaviour_tree = py_trees.trees.BehaviourTree(tree)
|
||||
|
||||
debug_visitor = py_trees.visitors.DebugVisitor()
|
||||
snapshot_visitor = py_trees.visitors.DisplaySnapshotVisitor()
|
||||
|
||||
behaviour_tree.visitors.append(debug_visitor)
|
||||
behaviour_tree.visitors.append(snapshot_visitor)
|
||||
|
||||
behaviour_tree.add_post_tick_handler(functools.partial(logger, snapshot_visitor))
|
||||
|
||||
behaviour_tree.setup(timeout=15)
|
||||
|
||||
####################
|
||||
# Tick Tock
|
||||
####################
|
||||
if args.interactive:
|
||||
py_trees.console.read_single_keypress()
|
||||
while True:
|
||||
try:
|
||||
behaviour_tree.tick()
|
||||
if args.interactive:
|
||||
py_trees.console.read_single_keypress()
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
print("\n")
|
181
thirdparty/py_trees/demos/pick_up_where_you_left_off.py
vendored
Normal file
181
thirdparty/py_trees/demos/pick_up_where_you_left_off.py
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.pick_up_where_you_left_off
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-pick-up-where-you-left-off
|
||||
|
||||
.. graphviz:: dot/pick_up_where_you_left_off.dot
|
||||
|
||||
.. image:: images/pick_up_where_you_left_off.gif
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import py_trees
|
||||
import sys
|
||||
import time
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description(root):
|
||||
content = "A demonstration of the 'pick up where you left off' idiom.\n\n"
|
||||
content += "A common behaviour tree pattern that allows you to resume\n"
|
||||
content += "work after being interrupted by a high priority interrupt.\n"
|
||||
content += "\n"
|
||||
content += "EVENTS\n"
|
||||
content += "\n"
|
||||
content += " - 2 : task one done, task two running\n"
|
||||
content += " - 3 : high priority interrupt\n"
|
||||
content += " - 7 : task two restarts\n"
|
||||
content += " - 9 : task two done\n"
|
||||
content += "\n"
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Pick Up Where you Left Off".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(create_root()),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('-r', '--render', action='store_true', help='render dot tree to file')
|
||||
group.add_argument('-i', '--interactive', action='store_true', help='pause and wait for keypress at each tick')
|
||||
return parser
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def post_tick_handler(snapshot_visitor, behaviour_tree):
|
||||
"""
|
||||
Prints an ascii tree with the current snapshot status.
|
||||
"""
|
||||
print(
|
||||
"\n" + py_trees.display.unicode_tree(
|
||||
root=behaviour_tree.root,
|
||||
visited=snapshot_visitor.visited,
|
||||
previously_visited=snapshot_visitor.previously_visited
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def create_root():
|
||||
task_one = py_trees.behaviours.Count(
|
||||
name="Task 1",
|
||||
fail_until=0,
|
||||
running_until=2,
|
||||
success_until=10
|
||||
)
|
||||
task_two = py_trees.behaviours.Count(
|
||||
name="Task 2",
|
||||
fail_until=0,
|
||||
running_until=2,
|
||||
success_until=10
|
||||
)
|
||||
high_priority_interrupt = py_trees.decorators.RunningIsFailure(
|
||||
child=py_trees.behaviours.Periodic(
|
||||
name="High Priority",
|
||||
n=3
|
||||
)
|
||||
)
|
||||
piwylo = py_trees.idioms.pick_up_where_you_left_off(
|
||||
name="Pick Up\nWhere You\nLeft Off",
|
||||
tasks=[task_one, task_two]
|
||||
)
|
||||
root = py_trees.composites.Selector(name="Root")
|
||||
root.add_children([high_priority_interrupt, piwylo])
|
||||
|
||||
return root
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
root = create_root()
|
||||
print(description(root))
|
||||
|
||||
####################
|
||||
# Rendering
|
||||
####################
|
||||
if args.render:
|
||||
py_trees.display.render_dot_tree(root)
|
||||
sys.exit()
|
||||
|
||||
####################
|
||||
# Tree Stewardship
|
||||
####################
|
||||
behaviour_tree = py_trees.trees.BehaviourTree(root)
|
||||
behaviour_tree.add_pre_tick_handler(pre_tick_handler)
|
||||
behaviour_tree.visitors.append(py_trees.visitors.DebugVisitor())
|
||||
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)
|
||||
behaviour_tree.setup(timeout=15)
|
||||
|
||||
####################
|
||||
# Tick Tock
|
||||
####################
|
||||
if args.interactive:
|
||||
py_trees.console.read_single_keypress()
|
||||
for unused_i in range(1, 11):
|
||||
try:
|
||||
behaviour_tree.tick()
|
||||
if args.interactive:
|
||||
py_trees.console.read_single_keypress()
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
print("\n")
|
119
thirdparty/py_trees/demos/selector.py
vendored
Normal file
119
thirdparty/py_trees/demos/selector.py
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.selector
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-selector
|
||||
|
||||
.. graphviz:: dot/demo-selector.dot
|
||||
|
||||
.. image:: images/selector.gif
|
||||
|
||||
"""
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import py_trees
|
||||
import sys
|
||||
import time
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "Higher priority switching and interruption in the children of a selector.\n"
|
||||
content += "\n"
|
||||
content += "In this example the higher priority child is setup to fail initially,\n"
|
||||
content += "falling back to the continually running second child. On the third\n"
|
||||
content += "tick, the first child succeeds and cancels the hitherto running child.\n"
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Selectors".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument('-r', '--render', action='store_true', help='render dot tree to file')
|
||||
return parser
|
||||
|
||||
|
||||
def create_root():
|
||||
root = py_trees.composites.Selector("Selector")
|
||||
success_after_two = py_trees.behaviours.Count(name="After Two",
|
||||
fail_until=2,
|
||||
running_until=2,
|
||||
success_until=10)
|
||||
always_running = py_trees.behaviours.Running(name="Running")
|
||||
root.add_children([success_after_two, always_running])
|
||||
return root
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
print(description())
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
|
||||
root = create_root()
|
||||
|
||||
####################
|
||||
# Rendering
|
||||
####################
|
||||
if args.render:
|
||||
py_trees.display.render_dot_tree(root)
|
||||
sys.exit()
|
||||
|
||||
####################
|
||||
# Execute
|
||||
####################
|
||||
root.setup_with_descendants()
|
||||
for i in range(1, 4):
|
||||
try:
|
||||
print("\n--------- Tick {0} ---------\n".format(i))
|
||||
root.tick_once()
|
||||
print("\n")
|
||||
print(py_trees.display.unicode_tree(root=root, show_status=True))
|
||||
time.sleep(1.0)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
print("\n")
|
118
thirdparty/py_trees/demos/sequence.py
vendored
Normal file
118
thirdparty/py_trees/demos/sequence.py
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.sequence
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-sequence
|
||||
|
||||
.. graphviz:: dot/demo-sequence.dot
|
||||
|
||||
.. image:: images/sequence.gif
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import py_trees
|
||||
import sys
|
||||
import time
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "Demonstrates sequences in action.\n\n"
|
||||
content += "A sequence is populated with 2-tick jobs that are allowed to run through to\n"
|
||||
content += "completion.\n"
|
||||
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Sequences".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument('-r', '--render', action='store_true', help='render dot tree to file')
|
||||
return parser
|
||||
|
||||
|
||||
def create_root():
|
||||
root = py_trees.composites.Sequence("Sequence")
|
||||
for action in ["Action 1", "Action 2", "Action 3"]:
|
||||
success_after_two = py_trees.behaviours.Count(name=action,
|
||||
fail_until=0,
|
||||
running_until=1,
|
||||
success_until=10)
|
||||
root.add_child(success_after_two)
|
||||
return root
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
print(description())
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
|
||||
root = create_root()
|
||||
|
||||
####################
|
||||
# Rendering
|
||||
####################
|
||||
if args.render:
|
||||
py_trees.display.render_dot_tree(root)
|
||||
sys.exit()
|
||||
|
||||
####################
|
||||
# Execute
|
||||
####################
|
||||
root.setup_with_descendants()
|
||||
for i in range(1, 6):
|
||||
try:
|
||||
print("\n--------- Tick {0} ---------\n".format(i))
|
||||
root.tick_once()
|
||||
print("\n")
|
||||
print(py_trees.display.unicode_tree(root=root, show_status=True))
|
||||
time.sleep(1.0)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
print("\n")
|
201
thirdparty/py_trees/demos/stewardship.py
vendored
Normal file
201
thirdparty/py_trees/demos/stewardship.py
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# License: BSD
|
||||
# https://raw.githubusercontent.com/splintered-reality/py_trees/devel/LICENSE
|
||||
#
|
||||
##############################################################################
|
||||
# Documentation
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
.. argparse::
|
||||
:module: py_trees.demos.stewardship
|
||||
:func: command_line_argument_parser
|
||||
:prog: py-trees-demo-tree-stewardship
|
||||
|
||||
.. graphviz:: dot/demo-tree-stewardship.dot
|
||||
|
||||
.. image:: images/tree_stewardship.gif
|
||||
"""
|
||||
|
||||
##############################################################################
|
||||
# Imports
|
||||
##############################################################################
|
||||
|
||||
import argparse
|
||||
import py_trees
|
||||
import sys
|
||||
import time
|
||||
|
||||
import py_trees.console as console
|
||||
|
||||
##############################################################################
|
||||
# Classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
def description():
|
||||
content = "A demonstration of tree stewardship.\n\n"
|
||||
content += "A slightly less trivial tree that uses a simple stdout pre-tick handler\n"
|
||||
content += "and both the debug and snapshot visitors for logging and displaying\n"
|
||||
content += "the state of the tree.\n"
|
||||
content += "\n"
|
||||
content += "EVENTS\n"
|
||||
content += "\n"
|
||||
content += " - 3 : sequence switches from running to success\n"
|
||||
content += " - 4 : selector's first child flicks to success once only\n"
|
||||
content += " - 8 : the fallback idler kicks in as everything else fails\n"
|
||||
content += " - 14 : the first child kicks in again, aborting a running sequence behind it\n"
|
||||
content += "\n"
|
||||
if py_trees.console.has_colours:
|
||||
banner_line = console.green + "*" * 79 + "\n" + console.reset
|
||||
s = "\n"
|
||||
s += banner_line
|
||||
s += console.bold_white + "Trees".center(79) + "\n" + console.reset
|
||||
s += banner_line
|
||||
s += "\n"
|
||||
s += content
|
||||
s += "\n"
|
||||
s += banner_line
|
||||
else:
|
||||
s = content
|
||||
return s
|
||||
|
||||
|
||||
def epilog():
|
||||
if py_trees.console.has_colours:
|
||||
return console.cyan + "And his noodly appendage reached forth to tickle the blessed...\n" + console.reset
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def command_line_argument_parser():
|
||||
parser = argparse.ArgumentParser(description=description(),
|
||||
epilog=epilog(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('-r', '--render', action='store_true', help='render dot tree to file')
|
||||
group.add_argument(
|
||||
'--render-with-blackboard-variables',
|
||||
action='store_true',
|
||||
help='render dot tree to file with blackboard variables'
|
||||
)
|
||||
group.add_argument('-i', '--interactive', action='store_true', help='pause and wait for keypress at each tick')
|
||||
return parser
|
||||
|
||||
|
||||
def pre_tick_handler(behaviour_tree):
|
||||
print("\n--------- Run %s ---------\n" % behaviour_tree.count)
|
||||
|
||||
|
||||
class SuccessEveryN(py_trees.behaviours.SuccessEveryN):
|
||||
def __init__(self):
|
||||
super().__init__(name="EveryN", n=5)
|
||||
self.blackboard = self.attach_blackboard_client(name=self.name)
|
||||
self.blackboard.register_key("count", access=py_trees.common.Access.WRITE)
|
||||
|
||||
def update(self):
|
||||
status = super().update()
|
||||
self.blackboard.count = self.count
|
||||
return status
|
||||
|
||||
|
||||
class PeriodicSuccess(py_trees.behaviours.Periodic):
|
||||
def __init__(self):
|
||||
super().__init__(name="Periodic", n=3)
|
||||
self.blackboard = self.attach_blackboard_client(name=self.name)
|
||||
self.blackboard.register_key("period", access=py_trees.common.Access.WRITE)
|
||||
|
||||
def update(self):
|
||||
status = super().update()
|
||||
self.blackboard.period = self.period
|
||||
return status
|
||||
|
||||
|
||||
class Finisher(py_trees.behaviour.Behaviour):
|
||||
def __init__(self):
|
||||
super().__init__(name="Finisher")
|
||||
self.blackboard = self.attach_blackboard_client(name=self.name)
|
||||
self.blackboard.register_key("count", access=py_trees.common.Access.READ)
|
||||
self.blackboard.register_key("period", access=py_trees.common.Access.READ)
|
||||
|
||||
def update(self):
|
||||
print(console.green + "---------------------------" + console.reset)
|
||||
print(console.bold + " Finisher" + console.reset)
|
||||
print(console.green + " Count : {}".format(self.blackboard.count) + console.reset)
|
||||
print(console.green + " Period: {}".format(self.blackboard.period) + console.reset)
|
||||
print(console.green + "---------------------------" + console.reset)
|
||||
return py_trees.common.Status.SUCCESS
|
||||
|
||||
|
||||
def create_tree():
|
||||
every_n_success = SuccessEveryN()
|
||||
sequence = py_trees.composites.Sequence(name="Sequence")
|
||||
guard = py_trees.behaviours.Success("Guard")
|
||||
periodic_success = PeriodicSuccess()
|
||||
finisher = Finisher()
|
||||
sequence.add_child(guard)
|
||||
sequence.add_child(periodic_success)
|
||||
sequence.add_child(finisher)
|
||||
idle = py_trees.behaviours.Success("Idle")
|
||||
root = py_trees.composites.Selector(name="Demo Tree")
|
||||
root.add_child(every_n_success)
|
||||
root.add_child(sequence)
|
||||
root.add_child(idle)
|
||||
return root
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Main
|
||||
##############################################################################
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the demo script.
|
||||
"""
|
||||
args = command_line_argument_parser().parse_args()
|
||||
py_trees.logging.level = py_trees.logging.Level.DEBUG
|
||||
tree = create_tree()
|
||||
print(description())
|
||||
|
||||
####################
|
||||
# Rendering
|
||||
####################
|
||||
if args.render:
|
||||
py_trees.display.render_dot_tree(tree)
|
||||
sys.exit()
|
||||
|
||||
if args.render_with_blackboard_variables:
|
||||
py_trees.display.render_dot_tree(tree, with_blackboard_variables=True)
|
||||
sys.exit()
|
||||
|
||||
####################
|
||||
# Tree Stewardship
|
||||
####################
|
||||
py_trees.blackboard.Blackboard.enable_activity_stream(100)
|
||||
behaviour_tree = py_trees.trees.BehaviourTree(tree)
|
||||
behaviour_tree.add_pre_tick_handler(pre_tick_handler)
|
||||
behaviour_tree.visitors.append(py_trees.visitors.DebugVisitor())
|
||||
behaviour_tree.visitors.append(
|
||||
py_trees.visitors.DisplaySnapshotVisitor(
|
||||
display_blackboard=True,
|
||||
display_activity_stream=True)
|
||||
)
|
||||
behaviour_tree.setup(timeout=15)
|
||||
|
||||
####################
|
||||
# Tick Tock
|
||||
####################
|
||||
if args.interactive:
|
||||
py_trees.console.read_single_keypress()
|
||||
while True:
|
||||
try:
|
||||
behaviour_tree.tick()
|
||||
if args.interactive:
|
||||
py_trees.console.read_single_keypress()
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
print("\n")
|
Reference in New Issue
Block a user