Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish current action #106

Merged
merged 7 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,5 @@ ENV/
**/docs/_out
**/docs/cppapi
**/docs/pyapi

.ruff_cache/
5 changes: 1 addition & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ repos:
args:
- "--fix"
- "--exit-non-zero-on-fix"
- repo: https://github.com/psf/black
rev: 23.10.0 # keep this version for Ubuntu support
hooks:
- id: black
- id: ruff-format
- repo: https://github.com/pocc/pre-commit-hooks
rev: v1.3.5
hooks:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from abc import ABCMeta
from typing import TYPE_CHECKING

from dynamic_stack_decider.abstract_stack_element import AbstractStackElement

if TYPE_CHECKING:
from dynamic_stack_decider.dsd import DSD


class AbstractActionElement(AbstractStackElement, metaclass=ABCMeta):
"""
Expand All @@ -14,7 +18,7 @@ class AbstractActionElement(AbstractStackElement, metaclass=ABCMeta):
If the action is complete, it can remove itself from the stack by performing a pop command.
"""

def __init__(self, blackboard, dsd, parameters=None):
def __init__(self, blackboard, dsd: "DSD", parameters: dict[str, bool | int | float | str]):
jaagut marked this conversation as resolved.
Show resolved Hide resolved
"""
Constructor of the action element
:param blackboard: Shared blackboard for data exchange between elements
Expand All @@ -23,10 +27,7 @@ def __init__(self, blackboard, dsd, parameters=None):
"""
super().__init__(blackboard, dsd, parameters)
# Reevaluation can be disabled by setting 'r' or 'reevaluate' to False
if parameters is not None:
self.never_reevaluate = not parameters.get("r", True) or not parameters.get("reevaluate", True)
else:
self.never_reevaluate = False
self.never_reevaluate = not parameters.get("r", True) or not parameters.get("reevaluate", True)

def do_not_reevaluate(self):
"""
Expand All @@ -41,6 +42,6 @@ def repr_dict(self) -> dict:
"""
return {
"type": "action",
"name": self.__class__.__name__,
"name": self.name,
"debug_data": self._debug_data,
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def repr_dict(self) -> dict:
"""
return {
"type": "decision",
"name": self.__class__.__name__,
"name": self.name,
"debug_data": self._debug_data,
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from abc import ABCMeta, abstractmethod
from typing import Union
from typing import TYPE_CHECKING, Union

from dynamic_stack_decider.logger import get_logger

if TYPE_CHECKING:
from dynamic_stack_decider.dsd import DSD


class AbstractStackElement(metaclass=ABCMeta):
"""
Expand All @@ -12,14 +15,14 @@ class AbstractStackElement(metaclass=ABCMeta):
Each element which inherits from the AbstractStackElement can be used as a root element on the stack.
"""

_dsd = None
_init_data = None
_dsd: "DSD"
parameters: dict[str, bool | int | float | str]

def __init__(self, blackboard, dsd, parameters=None):
def __init__(self, blackboard, dsd: "DSD", parameters: dict[str, bool | int | float | str]):
"""
:param blackboard: Shared blackboard for data exchange between elements
:param dsd: The stack decider which has this element on its stack.
:param parameters: Optional parameters which serve as arguments to this element
:param parameters: Parameters which serve as arguments to this element
"""
self._debug_data = {}
"""
Expand All @@ -28,8 +31,16 @@ def __init__(self, blackboard, dsd, parameters=None):
"""

self._dsd = dsd
self.parameters = parameters
self.blackboard = blackboard

@property
def name(self) -> str:
"""
Returns the name of the action
"""
return self.__class__.__name__

def pop(self):
"""
Help method which pops the element of the stack.
Expand Down Expand Up @@ -90,6 +101,6 @@ def repr_dict(self) -> dict:
"""Represent this stack element as dictionary which is JSON encodable"""
return {
"type": "abstract",
"name": self.__class__.__name__,
"name": self.name,
"debug_data": self._debug_data,
}
35 changes: 33 additions & 2 deletions dynamic_stack_decider/dynamic_stack_decider/dsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class DSD:
stack_reevaluate = False
do_not_reevaluate = False
old_representation = ""
debug_active_action_cache: Optional[str] = None

def __init__(self, blackboard, debug_topic: str = None, node: Optional[Node] = None):
"""
Expand Down Expand Up @@ -142,6 +143,10 @@ def __init__(self, blackboard, debug_topic: str = None, node: Optional[Node] = N
debug_stack_topic = f"{debug_topic}/dsd_stack"
self.debug_stack_publisher = node.create_publisher(String, debug_stack_topic, 10)
get_logger().debug(f"Debugging stack on '{debug_stack_topic}'")
# Publish the currently active action
debug_current_action_topic = f"{debug_topic}/dsd_current_action"
self.debug_current_action_publisher = node.create_publisher(String, debug_current_action_topic, 10)
get_logger().debug(f"Debugging current action on '{debug_current_action_topic}'")

def register_actions(self, module_path):
"""
Expand Down Expand Up @@ -196,7 +201,7 @@ def _bind_modules(self, element):
else:
raise ValueError(f'Unknown parser tree element type "{type(element)}" for element "{element}"!')

def _init_element(self, element):
def _init_element(self, element: AbstractTreeElement):
"""Initializes the module belonging to the given element."""
if isinstance(element, SequenceTreeElement):
initialized_actions = list()
Expand All @@ -206,7 +211,7 @@ def _init_element(self, element):
else:
return element.module(self.blackboard, self, element.parameters)

def set_start_element(self, start_element):
def set_start_element(self, start_element: AbstractTreeElement):
"""
This method defines the start element on the stack, which stays always on the bottom of the stack.
It should be called in __init__.
Expand Down Expand Up @@ -236,6 +241,7 @@ def update(self, reevaluate: bool = True):
"""
try:
self.debug_publish_stack()
self.debug_publish_current_action()

if reevaluate and not self.do_not_reevaluate:
self.stack_exec_index = 0
Expand Down Expand Up @@ -362,3 +368,28 @@ def debug_publish_tree(self):
data = self.tree.repr_dict()
msg = String(data=json.dumps(data))
self.debug_tree_publisher.publish(msg)

def debug_publish_current_action(self):
"""
Publishes the name of the currently active action
"""
# Check if debugging is active and if there is something on the stack
if not self.debug_active or len(self.stack) == 0:
return

# Get the top element
stack_top = self.stack[-1][1]
# Check if it is an action or a sequence element and retrieve the current action
if isinstance(stack_top, AbstractActionElement):
current_action = stack_top
elif isinstance(stack_top, SequenceElement):
current_action = stack_top.current_action
else:
return

# Only publish if the action changed
if current_action.name != self.debug_active_action_cache:
# Publish the name of the current action
self.debug_current_action_publisher.publish(String(data=current_action.name))
# Cache the current action name
self.debug_active_action_cache = current_action.name
20 changes: 11 additions & 9 deletions dynamic_stack_decider/dynamic_stack_decider/sequence_element.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
from typing import TYPE_CHECKING

from dynamic_stack_decider.abstract_action_element import AbstractActionElement
from dynamic_stack_decider.abstract_stack_element import AbstractStackElement

if TYPE_CHECKING:
from dynamic_stack_decider.dsd import DSD


class SequenceElement(AbstractStackElement):
"""
Expand All @@ -10,11 +16,11 @@ class SequenceElement(AbstractStackElement):
This is not an abstract class to inherit from.
"""

def __init__(self, blackboard, dsd, actions=()):
def __init__(self, blackboard, dsd: "DSD", actions: list[AbstractActionElement]):
"""
:param actions: list of initialized action elements
"""
super().__init__(blackboard, dsd)
super().__init__(blackboard, dsd, dict())
self.actions = actions
self.current_action_index = 0

Expand All @@ -40,21 +46,17 @@ def in_last_element(self):
return self.current_action_index == len(self.actions) - 1

@property
def current_action(self):
def current_action(self) -> AbstractActionElement:
"""
Returns the currently executed action of the sequence element

:rtype: AbstractActionElement
"""
return self.actions[self.current_action_index]

def repr_dict(self):
def repr_dict(self) -> dict:
"""
Represent this stack element as dictionary which is JSON encodable

:rtype: dict
"""
self.publish_debug_data("Active Element", self.current_action.__class__.__name__)
self.publish_debug_data("Active Element", self.current_action.name)
if self.current_action._debug_data:
self.publish_debug_data("Corresponding debug data", self.current_action._debug_data)
data = {
Expand Down
2 changes: 0 additions & 2 deletions dynamic_stack_decider/dynamic_stack_decider/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ def __init__(self, name, parent, parameters=None, unset_parameters=None):
:param parent: the parent element, None for the root element
:param parameters: A dictionary of parameters
:param unset_parameters: A dictionary of parameters that must be set later
:type parent: DecisionTreeElement
"""
# Call the constructor of the superclass
super().__init__(name, parent, parameters, unset_parameters)
Expand Down Expand Up @@ -185,7 +184,6 @@ def __init__(self, name, parent, parameters=None, unset_parameters=None):
Create a new ActionTreeElement
:param name: the class name of the corresponding AbstractActionElement
:param parent: the parent element
:type parent: DecisionTreeElement
:param parameters: A dictionary of parameters
:param unset_parameters: A dictionary of parameters that must be set later
"""
Expand Down
Loading