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

Fix sequence init #108

Merged
merged 5 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
7 changes: 0 additions & 7 deletions dynamic_stack_decider/CMakeLists.txt

This file was deleted.

7 changes: 2 additions & 5 deletions dynamic_stack_decider/dynamic_stack_decider/dsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,10 @@ def _bind_modules(self, element):
else:
raise ValueError(f'Unknown parser tree element type "{type(element)}" for element "{element}"!')

def _init_element(self, element: AbstractTreeElement):
def _init_element(self, element: AbstractTreeElement) -> AbstractStackElement:
"""Initializes the module belonging to the given element."""
if isinstance(element, SequenceTreeElement):
initialized_actions = list()
for action in element.action_elements:
initialized_actions.append(action.module(self.blackboard, self, action.parameters))
return SequenceElement(self.blackboard, self, initialized_actions)
return SequenceElement(self.blackboard, self, element.action_elements, self._init_element)
else:
return element.module(self.blackboard, self, element.parameters)

Expand Down
48 changes: 33 additions & 15 deletions dynamic_stack_decider/dynamic_stack_decider/sequence_element.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Callable

from dynamic_stack_decider.abstract_action_element import AbstractActionElement
from dynamic_stack_decider.abstract_stack_element import AbstractStackElement
from dynamic_stack_decider.tree import AbstractTreeElement, ActionTreeElement

if TYPE_CHECKING:
from dynamic_stack_decider.dsd import DSD
Expand All @@ -16,21 +17,44 @@ class SequenceElement(AbstractStackElement):
This is not an abstract class to inherit from.
"""

def __init__(self, blackboard, dsd: "DSD", actions: list[AbstractActionElement]):
def __init__(
self,
blackboard,
dsd: "DSD",
actions: list[ActionTreeElement],
init_function: Callable[[AbstractTreeElement], AbstractStackElement],
):
"""
:param blackboard: Shared blackboard for data exchange and code reuse between elements
:param dsd: The stack decider which has this element on its stack.
:param actions: list of initialized action elements
:param init_function: A function that initializes an action element creating a stack element from a tree element
Flova marked this conversation as resolved.
Show resolved Hide resolved
"""
super().__init__(blackboard, dsd, dict())
# Here we store the 'blueprints' of the actions
self.actions = actions
self.current_action_index = 0
# We store a reference to the function that initializes the action elements based on the tree
self._init_function = init_function
# Here we store the actual instances of the active action
# The action is only initialized when it is the current action
assert len(actions) > 0, "A sequence element must contain at least one action"
self.current_action: AbstractActionElement = self._init_function(actions[0])
# Where we are in the sequence
self.current_action_index: int = 0

def perform(self, reevaluate=False):
"""
Perform the current action of the sequence. See AbstractStackElement.perform() for more information

:param reevaluate: Ignored for SequenceElements
"""
# Log the active element
self.publish_debug_data("Active Element", self.current_action.name)
# Pass the perform call to the current action
self.current_action.perform()
Flova marked this conversation as resolved.
Show resolved Hide resolved
# If the action had debug data, publish it
if self.current_action._debug_data:
self.publish_debug_data("Corresponding debug data", self.current_action._debug_data)

def pop_one(self):
"""
Expand All @@ -39,30 +63,24 @@ def pop_one(self):
assert not self.in_last_element(), (
"It is not possible to pop a single element when" "the last element of the sequence is active"
)
# Increment the index to the next action and initialize it
self.current_action_index += 1
# We initilize the current action here to avoid the problem described in
# https://github.com/bit-bots/dynamic_stack_decider/issues/107
self.current_action = self._init_function(self.actions[self.current_action_index])

def in_last_element(self):
"""Returns if the current element is the last element of the sequence"""
return self.current_action_index == len(self.actions) - 1

@property
def current_action(self) -> AbstractActionElement:
"""
Returns the currently executed action of the sequence element
"""
return self.actions[self.current_action_index]

def repr_dict(self) -> dict:
"""
Represent this stack element as dictionary which is JSON encodable
"""
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 = {
"type": "sequence",
"current_action_id": self.current_action_index,
"content": [elem.repr_dict() for elem in self.actions],
"current_action_index": self.current_action_index,
"current_action": self.current_action.repr_dict(),
"debug_data": self._debug_data,
}
self.clear_debug_data()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def param_string(params: dict) -> str:
# Spaces for indentation
action_label = " "
# Mark current element (if this sequence is on the stack)
if stack_element is not None and i == stack_element["current_action_id"]:
if stack_element is not None and i == stack_element["current_action_index"]:
action_label += "--> "
action_label += action["name"] + param_string(action["parameters"])
label.append(action_label)
Expand Down Expand Up @@ -327,7 +327,7 @@ def to_q_item_model(self):
# Set the text of the item
if stack_element["type"] == "sequence":
# Get the names of all actions
action_names = [element["name"] for element in stack_element["content"]]
action_names = [element["name"] for element in stack_element["current_action"]]
# Join them together and set the text
elem_item.setText("Sequence: " + ", ".join(action_names))
else:
Expand Down
Loading