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

Add runtime and static type checks #639

Merged
merged 14 commits into from
Jan 10, 2025
Prev Previous commit
Next Next commit
Fix dsd stuff
Flova committed Dec 20, 2024
commit 52a4ccf269e49601fdc4cd478bc97ce9c2818ce7
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Setting up runtime type checking for this package
from beartype.claw import beartype_this_package

beartype_this_package()
4 changes: 4 additions & 0 deletions bitbots_motion/bitbots_hcm/bitbots_hcm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Setting up runtime type checking for this package
from beartype.claw import beartype_this_package

beartype_this_package()
4 changes: 0 additions & 4 deletions bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Setting up runtime type checking for this package
from beartype.claw import beartype_this_package
beartype_this_package()

from bitbots_hcm.hcm_dsd import actions, decisions, hcm_blackboard

__all__ = ["actions", "decisions", "hcm_blackboard"]
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Setting up runtime type checking for this package
# We need to do this again here because the dsd imports
# the decisions and actions from this package in a standalone way
from beartype.claw import beartype_this_package
from dynamic_stack_decider.abstract_action_element import AbstractActionElement

from bitbots_hcm.hcm_dsd.hcm_blackboard import HcmBlackboard

beartype_this_package()


class AbstractHCMActionElement(AbstractActionElement):
"""
29 changes: 15 additions & 14 deletions bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/actions/state.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from abc import ABC, abstractmethod

from bitbots_hcm.hcm_dsd.actions import AbstractHCMActionElement
from bitbots_hcm.type_utils import T_RobotControlState
from bitbots_msgs.msg import RobotControlState


@@ -11,7 +12,7 @@ class AbstractRobotState(AbstractHCMActionElement, ABC):
"""

@abstractmethod
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
"""
Returns the state which should be set. This will be implemented by the subclasses.
"""
@@ -27,65 +28,65 @@ def perform(self, reevaluate=False):


class RobotStateStartup(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.STARTUP


class RobotStateControllable(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.CONTROLLABLE


class RobotStateWalking(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.WALKING


class RobotStateAnimationRunning(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.ANIMATION_RUNNING


class RobotStatePickedUp(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.PICKED_UP


class RobotStateFalling(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.FALLING


class RobotStateFallen(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.FALLEN


class RobotStateGettingUp(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.GETTING_UP


class RobotStatePenalty(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.PENALTY


class RobotStateRecord(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.RECORD


class RobotStateKicking(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.KICKING


class RobotStateHardwareProblem(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.HARDWARE_PROBLEM


class RobotStateMotorOff(AbstractRobotState):
def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
return RobotControlState.MOTOR_OFF
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Setting up runtime type checking for this package
# We need to do this again here because the dsd imports
# the decisions and actions from this package in a standalone way
from beartype.claw import beartype_this_package
from dynamic_stack_decider.abstract_decision_element import AbstractDecisionElement

from bitbots_hcm.hcm_dsd.hcm_blackboard import HcmBlackboard

beartype_this_package()


class AbstractHCMDecisionElement(AbstractDecisionElement):
"""
21 changes: 3 additions & 18 deletions bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/hcm_blackboard.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Literal, Optional
from typing import List, Optional

import numpy
from bitbots_utils.utils import get_parameters_from_other_node_sync
@@ -12,6 +12,7 @@
from std_srvs.srv import Empty as EmptySrv
from std_srvs.srv import SetBool

from bitbots_hcm.type_utils import T_RobotControlState
from bitbots_msgs.action import Dynup, PlayAnimation
from bitbots_msgs.msg import Audio, JointTorque, RobotControlState
from bitbots_msgs.srv import SetTeachingMode
@@ -22,23 +23,7 @@ def __init__(self, node: Node):
self.node = node

# Basic state
self.current_state: Literal[
RobotControlState.CONTROLLABLE,
RobotControlState.FALLING,
RobotControlState.FALLEN,
RobotControlState.GETTING_UP,
RobotControlState.ANIMATION_RUNNING,
RobotControlState.STARTUP,
RobotControlState.SHUTDOWN,
RobotControlState.PENALTY,
RobotControlState.RECORD,
RobotControlState.WALKING,
RobotControlState.MOTOR_OFF,
RobotControlState.HCM_OFF,
RobotControlState.HARDWARE_PROBLEM,
RobotControlState.PICKED_UP,
RobotControlState.KICKING
] = RobotControlState.STARTUP
self.current_state: T_RobotControlState = RobotControlState.STARTUP
self.stopped: bool = False

# Save start time
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@

from bitbots_hcm import hcm_dsd
from bitbots_hcm.hcm_dsd.hcm_blackboard import HcmBlackboard
from bitbots_hcm.type_utils import T_RobotControlState
from bitbots_msgs.msg import FootPressure, RobotControlState
from bitbots_msgs.srv import ManualPenalize, SetTeachingMode

@@ -34,13 +35,13 @@ def __init__(self, use_sim_time, simulation_active, visualization_active):
node_name = "hcm_py"

# Load parameters from yaml file because this is a hacky cpp python hybrid node for performance reasons
parameter_msgs: list(ParameterMsg) = get_parameters_from_ros_yaml(
parameter_msgs: list[ParameterMsg] = get_parameters_from_ros_yaml(
node_name, f"{get_package_share_directory('bitbots_hcm')}/config/hcm_wolfgang.yaml", use_wildcard=True
)
parameters = [
Parameter("use_sim_time", type_=Parameter.Type.BOOL, value=use_sim_time),
Parameter("simulation_active", type_=Parameter.Type.BOOL, value=simulation_active),
Parameter("visualization_active", type_=Parameter.Type.BOOL, value=visualization_active)
Parameter("visualization_active", type_=Parameter.Type.BOOL, value=visualization_active),
]
parameters.extend(map(Parameter.from_parameter_msg, parameter_msgs))

@@ -158,7 +159,7 @@ def diag_cb(self, msg: DiagnosticArray):
elif "/Pressure" in status.name:
self.blackboard.pressure_diag_error = status.level in (DiagnosticStatus.ERROR, DiagnosticStatus.STALE)

def get_state(self) -> RobotControlState:
def get_state(self) -> T_RobotControlState:
"""Returns the current state of the HCM."""
return self.blackboard.current_state

21 changes: 21 additions & 0 deletions bitbots_motion/bitbots_hcm/bitbots_hcm/type_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from typing import Literal, TypeAlias

from bitbots_msgs.msg import RobotControlState

T_RobotControlState: TypeAlias = Literal[
RobotControlState.CONTROLLABLE,
RobotControlState.FALLING,
RobotControlState.FALLEN,
RobotControlState.GETTING_UP,
RobotControlState.ANIMATION_RUNNING,
RobotControlState.STARTUP,
RobotControlState.SHUTDOWN,
RobotControlState.PENALTY,
RobotControlState.RECORD,
RobotControlState.WALKING,
RobotControlState.MOTOR_OFF,
RobotControlState.HCM_OFF,
RobotControlState.HARDWARE_PROBLEM,
RobotControlState.PICKED_UP,
RobotControlState.KICKING,
]