Start to refactor into having an internal and external coordinates for stages to handle inversion

This commit is contained in:
Julian Stirling 2025-07-30 11:13:45 +01:00
parent ee9362ce48
commit b373931c1a
2 changed files with 36 additions and 18 deletions

View file

@ -11,6 +11,7 @@ As the object will be used as a context manager create the hardware connection i
from __future__ import annotations
from collections.abc import Sequence, Mapping
from typing import Literal
import labthings_fastapi as lt
@ -25,12 +26,15 @@ class BaseStage(lt.Thing):
"""
_axis_names = ("x", "y", "z")
def __init__(self):
self._internal_position = dict.fromkeys(self._axis_names, 0)
@lt.thing_property
def axis_names(self) -> Sequence[str]:
"""The names of the stage's axes, in order."""
return self._axis_names
# TODO make this have a getter so it uses axis direction to invert.
position = lt.ThingProperty(
Mapping[str, int],
dict.fromkeys(_axis_names, 0),
@ -47,11 +51,41 @@ class BaseStage(lt.Thing):
)
"""Whether the stage is in motion."""
axis_direction = lt.ThingSetting(
initial_value={"x": -1, "y": 1, "z": -1},
model=Mapping[str, int],
)
"""The direction that each motor should move.
Testing reveals that z and either x or y generally need inverting."""
def apply_axis_direction(self, position: list|Mapping[str|int]) -> list|Mapping[str|int]:
# TODO check if isinstance works for Mapping
if isinstance(position, (list, tuple)):
# TODO: check list length is axis length
position = [pos*ax_dir for pos, ax_dir in zip(position, self.axis_direction.values())]
return dict(zip(self.axis_names, position))
elif isinstance(position, Mapping):
# TODO add try for KeyError
return {axis: position[axis] * self.axis_direction[axis] for axis in self.position}
raise TypeError #TODO message
@property
def thing_state(self):
"""Summary metadata describing the current state of the stage."""
return {"position": self.position}
@lt.thing_action
def invert_axis_direction(self, axis: Literal["x", "y", "z"]):
"""Invert the direction setting of the given axis.
:param axis: The axis name (x, y or z) to invert.
"""
direction = self.axis_direction
direction[axis] *= -1
self.axis_direction = direction
@lt.thing_action
def move_relative(
self,

View file

@ -38,6 +38,7 @@ class SangaboardThing(BaseStage):
"""
self.sangaboard_kwargs = kwargs
self.sangaboard_kwargs["port"] = port
# TODO super init
def __enter__(self):
"""Connect to the sangaboard when the Thing context manager is opened."""
@ -168,21 +169,4 @@ class SangaboardThing(BaseStage):
sb.query(f"{led_command} {on_brightness}")
time.sleep(dt)
axis_direction = lt.ThingSetting(
initial_value={"x": -1, "y": 1, "z": -1},
model=dict,
)
"""The direction that each motor should move.
Testing reveals that z and either x or y generally need inverting."""
@lt.thing_action
def invert_axis_direction(self, axis: Literal["x", "y", "z"]):
"""Invert the direction setting of the given axis.
:param axis: The axis name (x, y or z) to invert.
"""
direction = self.axis_direction
direction[axis] *= -1
self.axis_direction = direction
self.update_position()