Package: action-trees
Action TreesDocumentation:https://roxautomation.gitlab.io/action-treesSource Code:https://gitlab.com/roxautomation/action-treesSummaryAction Treesis anasyncio-based framework designed for orchestrating hierarchical, asynchronous actions. It enables the structuring of complex processes into manageable, interdependent tasks, facilitating the execution of multi-step workflows either sequentially or in parallel. This framework is particularly suitable for systems that require coordinated, concurrent task management.TheActionItemclass, a key component of theaction_treesmodule, is an abstract base class tailored for managing hierarchical action items, especially in VDA5050 compliant systems. Its main features include:State Management:Manages various states (NONE,WAITING,INITIALIZING,RUNNING,PAUSED,FINISHED,FAILED) for action items, ensuring valid transitions between these states.Exception Handling:Implements custom exceptions (StateTransitionExceptionandActionFailedException) to handle invalid state transitions and failures in action completion.Task Execution and Management:Supports starting, pausing, resuming, and canceling action items, with an emphasis on asynchronous execution usingasyncio.Child Actions Handling:Provides functionality for adding, removing, and managing child action items, enabling a structured, hierarchical approach to action management.Core Method Implementation:Requires subclasses to implement the_on_runabstract method to define the primary behavior of the action item. An optional_on_initmethod can be implemented for initial setup steps.Action Trees vs. Behavior TreesBehavior Trees (BTs) and Action Trees (ATs) use a tree-like structure but have different goals. BTs make choices aboutwhat to do nextbased on current situations, which is great for tasks needing quick decisions. ATs are aboutexecutingcomplex tasks efficiently, with a focus on robust error-handling errors and asynchronous operation.
In short, BTs are for making decisions, while ATs are for carrying out tasks effectively.Example - Coffee makerLet's simulate a coffee-making machine using the following action hierarchy:- cappuccino_order
    - prepare
        - initialize
        - clean
    - make_cappuccino
        - boil_water
        - grind_coffeeAn implementation would look like this:importasynciofromaction_treesimportActionItemclassAtomicAction(ActionItem):"""Mock action with no children."""def__init__(self,name:str,duration:float=0.1):super().__init__(name=name)self._duration=durationasyncdef_on_run(self):awaitself._wait_if_paused()# pause/resume helperawaitasyncio.sleep(self._duration)classPrepareMachineAction(ActionItem):"""Prepare the machine."""def__init__(self):super().__init__(name="prepare")self.add_child(AtomicAction(name="initialize"))self.add_child(AtomicAction(name="clean"))asyncdef_on_run(self):# sequentially run childrenawaitself.get_child("initialize").start()awaitself.get_child("clean").start()classMakeCappuccinoAction(ActionItem):"""Make cappuccino."""def__init__(self):super().__init__(name="make_cappuccino")self.add_child(AtomicAction(name="boil_water"))self.add_child(AtomicAction(name="grind_coffee"))asyncdef_on_run(self):# simultaneously run childrenawaitself._start_children_parallel()classCappuccinoOrder(ActionItem):"""High-level action to make a cappuccino."""def__init__(self):super().__init__(name="cappuccino_order")self.add_child(PrepareMachineAction())self.add_child(MakeCappuccinoAction())asyncdef_on_run(self):forchildinself.children:awaitchild.start()# create root orderorder=CappuccinoOrder()# start tasks in the backgroundawaitorder.start()DevelopmentseedocsThis project was forked fromcookiecutter templatetemplate.