Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
462ece5
Add I09 and I09-1 sample stages
oliwenmandiamond Jan 27, 2026
3756de7
Add tests for new stages
oliwenmandiamond Jan 27, 2026
0fc5aec
Update doc strings
oliwenmandiamond Jan 27, 2026
cbd692a
Correct doc string
oliwenmandiamond Jan 27, 2026
a107355
Add test
oliwenmandiamond Jan 27, 2026
0eda406
Remove skip
oliwenmandiamond Jan 27, 2026
df80ee8
Merge branch 'main' into add_sample_stage_for_i09
oliwenmandiamond Jan 27, 2026
031e4dd
Remove comments
oliwenmandiamond Jan 27, 2026
c5f3441
Merge branch 'add_sample_stage_for_i09' of ssh://github.com/DiamondLi…
oliwenmandiamond Jan 27, 2026
99dd78a
Moved tilt stage to core motors
oliwenmandiamond Jan 28, 2026
09fb2a5
Also moved tests
oliwenmandiamond Jan 28, 2026
e9afad0
Merge branch 'main' into add_sample_stage_for_i09
oliwenmandiamond Jan 28, 2026
7c3f2d4
Add i05 sample stage
oliwenmandiamond Jan 28, 2026
044178e
Merge branch 'add_sample_stage_for_i09' into add_sample_stage_for_i05
oliwenmandiamond Jan 28, 2026
3b09018
Added I05-1
oliwenmandiamond Jan 28, 2026
19d8baf
Added doc string
oliwenmandiamond Jan 28, 2026
fdfa9d5
Merge branch 'add_sample_stage_for_i05' of ssh://github.com/DiamondLi…
oliwenmandiamond Jan 28, 2026
28fd04c
Correct doc strings
oliwenmandiamond Jan 28, 2026
a9d07f1
Add test for XYZPolarAzimuthDefocusStage
oliwenmandiamond Jan 28, 2026
578e200
Fix typo
oliwenmandiamond Jan 28, 2026
cf02211
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Jan 28, 2026
143ce97
Add configuration back to stage
oliwenmandiamond Jan 28, 2026
8c68c3f
Added perp and long signals
oliwenmandiamond Jan 28, 2026
3fdbcc9
Remove comment
oliwenmandiamond Jan 28, 2026
267d70b
Added configurable rotation_angle_deg
oliwenmandiamond Jan 28, 2026
0715af9
Restructuted using rotation matrix
oliwenmandiamond Jan 29, 2026
46b7eb3
Used a Vector2D dataclass
oliwenmandiamond Jan 29, 2026
31327ad
Made the rotation matrix configurable
oliwenmandiamond Jan 29, 2026
1a105e1
Fixed tests
oliwenmandiamond Jan 29, 2026
f914865
Moved Vector2D to i05_shared (for now)
oliwenmandiamond Jan 29, 2026
7f15174
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Jan 29, 2026
2bb24a9
Rename files to make less confusing when editing
oliwenmandiamond Jan 29, 2026
cde0f4c
Fix import
oliwenmandiamond Jan 29, 2026
a33e813
Fix import
oliwenmandiamond Jan 29, 2026
41b0bad
Removed class and instead use functions
oliwenmandiamond Jan 29, 2026
a603432
Further simplifed, single function
oliwenmandiamond Jan 29, 2026
d848d24
Improved doc string
oliwenmandiamond Jan 29, 2026
a1a1599
Fix doc string import
oliwenmandiamond Jan 29, 2026
a59f535
First attempt at creaint helper function to build signals
oliwenmandiamond Jan 29, 2026
b31c793
Optmise test
oliwenmandiamond Jan 30, 2026
2897073
Create helper function to create i and j virtaul axis. Apply to i05 a…
oliwenmandiamond Jan 30, 2026
a28493b
perp and long motors now correctly done, added read test
oliwenmandiamond Feb 2, 2026
db997ba
Added helper util function for testing rotation signals which can be …
oliwenmandiamond Feb 2, 2026
fbc91d4
Move maths to common, update common motors to use it
oliwenmandiamond Feb 3, 2026
2060152
Fix lint
oliwenmandiamond Feb 3, 2026
b2c29d7
Remove use of type: ignore by utilising bluesky maybe_await and Movable
oliwenmandiamond Feb 3, 2026
26ff07a
Correct doc string and update variable names
oliwenmandiamond Feb 3, 2026
da01cb3
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Feb 3, 2026
8398fb4
Add more detailed doc strings and fix lint
oliwenmandiamond Feb 3, 2026
c9ec869
Reduced duplication of code
oliwenmandiamond Feb 3, 2026
0689c23
Add tests for maths rotation functions
oliwenmandiamond Feb 3, 2026
ec7b7b5
Simplify assert rotated function, add doc string, improve type checking
oliwenmandiamond Feb 3, 2026
d7db203
Improve type checking
oliwenmandiamond Feb 3, 2026
ec853de
Correct defocus infix
oliwenmandiamond Feb 3, 2026
118dc6c
Refactor existing classes to add i21
oliwenmandiamond Feb 3, 2026
b715606
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Feb 3, 2026
8f180b9
Update i05 device location for main branch
oliwenmandiamond Feb 3, 2026
8789887
Fix test imports
oliwenmandiamond Feb 3, 2026
e13e2a2
Fix imports
oliwenmandiamond Feb 4, 2026
0aec707
Merge branch 'add_sample_stage_for_i05' into add_i21_sample_stage
oliwenmandiamond Feb 4, 2026
5271d19
Add I21 sample stages
oliwenmandiamond Feb 4, 2026
6d6b63e
Update smp to smp_ref
oliwenmandiamond Feb 4, 2026
cb0fcc4
Move ToolpointMoition to own file
oliwenmandiamond Feb 5, 2026
73a9551
Add read and set tests
oliwenmandiamond Feb 5, 2026
43cf153
Add test for uvw set
oliwenmandiamond Feb 5, 2026
59cb498
Renamed angles to use deg to make units explicit
oliwenmandiamond Feb 5, 2026
f505d8d
Use expected_uvw_read fucntion for test
oliwenmandiamond Feb 5, 2026
3bce99b
Finished tests
oliwenmandiamond Feb 5, 2026
5d81fd3
Add smp_test
oliwenmandiamond Feb 10, 2026
bf06111
Add diffraction diode rotation, rename to I21SampleManipulatorStage
oliwenmandiamond Feb 10, 2026
ef9b314
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Feb 10, 2026
a99c745
Update src/dodal/devices/beamlines/i05/i05_motors.py
oliwenmandiamond Feb 10, 2026
d0b4214
Update src/dodal/devices/beamlines/i05/i05_motors.py
oliwenmandiamond Feb 10, 2026
0ca0ae0
Update src/dodal/devices/beamlines/i05/i05_motors.py
oliwenmandiamond Feb 10, 2026
5ac37ad
Update src/dodal/devices/beamlines/i05/i05_motors.py
oliwenmandiamond Feb 10, 2026
bdfe3f9
Update src/dodal/devices/beamlines/i05/i05_motors.py
oliwenmandiamond Feb 10, 2026
ce0d79e
Update src/dodal/devices/beamlines/i05_shared/rotation_signals.py
oliwenmandiamond Feb 10, 2026
a36556e
Update src/dodal/devices/beamlines/i05_1/i05_1_motors.py
oliwenmandiamond Feb 10, 2026
d8af671
Update src/dodal/devices/beamlines/i05_1/i05_1_motors.py
oliwenmandiamond Feb 10, 2026
f80b264
Update src/dodal/devices/beamlines/i05_1/i05_1_motors.py
oliwenmandiamond Feb 10, 2026
85345ed
Merge branch 'add_sample_stage_for_i05' of ssh://github.com/DiamondLi…
oliwenmandiamond Feb 10, 2026
cd4cddf
Tidy up doc string after applying feedback commits
oliwenmandiamond Feb 10, 2026
e6364b3
Simplify rotation func
oliwenmandiamond Feb 10, 2026
403b184
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Feb 10, 2026
187013c
Merge branch 'add_sample_stage_for_i05' into add_i21_sample_stage
oliwenmandiamond Feb 10, 2026
2adb1a6
Fix imports
oliwenmandiamond Feb 11, 2026
b74b834
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Feb 11, 2026
cd95db7
Improve type checking for XYZPolarAzimuthDefocusStage
oliwenmandiamond Feb 11, 2026
9867e9d
Rename test device to what it is on i05-1 bl
oliwenmandiamond Feb 11, 2026
55cf364
Merge branch 'add_sample_stage_for_i05' of ssh://github.com/DiamondLi…
oliwenmandiamond Feb 11, 2026
0a71f86
Merge branch 'add_sample_stage_for_i05' into add_i21_sample_stage
oliwenmandiamond Feb 11, 2026
83c08fe
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Feb 11, 2026
17decbf
Merge branch 'add_sample_stage_for_i05' into add_i21_sample_stage
oliwenmandiamond Feb 11, 2026
8956bc2
Improve readability of code
oliwenmandiamond Feb 11, 2026
2831c9e
Removed duplicate import
oliwenmandiamond Feb 11, 2026
019f1cb
Made logic more explicit and reused dataclasses. Fixed tests
oliwenmandiamond Feb 11, 2026
9673b0a
Rename variable names to make clearer
oliwenmandiamond Feb 11, 2026
d5b0592
Add more type checking docs for create_rotational_ij_component_signals
oliwenmandiamond Feb 11, 2026
f78484c
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Feb 12, 2026
f22819f
Merge branch 'main' into add_sample_stage_for_i05
oliwenmandiamond Feb 12, 2026
7276261
Merge branch 'add_sample_stage_for_i05' of ssh://github.com/DiamondLi…
oliwenmandiamond Feb 12, 2026
6ce497a
Merge branch 'add_sample_stage_for_i05' into add_i21_sample_stage
oliwenmandiamond Feb 12, 2026
261efbd
Update test names
oliwenmandiamond Feb 12, 2026
8e50c57
Merge branch 'main' into add_i21_sample_stage
oliwenmandiamond Feb 13, 2026
1d0cb8c
Rename function
oliwenmandiamond Feb 13, 2026
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
10 changes: 5 additions & 5 deletions src/dodal/beamlines/b07.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
)
from dodal.devices.electron_analyser.base import EnergySource
from dodal.devices.electron_analyser.specs import SpecsDetector
from dodal.devices.motors import XYZPolarStage
from dodal.devices.motors import XYZAzimuthStage
from dodal.devices.pgm import PlaneGratingMonochromator
from dodal.log import set_beamline as set_log_beamline
from dodal.utils import BeamlinePrefix, get_beamline_name
Expand Down Expand Up @@ -54,8 +54,8 @@ def sm52b() -> B07SampleManipulator52B:


@devices.factory()
def sm21b() -> XYZPolarStage:
"""Sample manipulator. NOTE: The polar attribute is equivalent to GDA roty."""
return XYZPolarStage(
prefix=f"{B_PREFIX.beamline_prefix}-EA-SM-21:", polar_infix="ROTY"
def sm21b() -> XYZAzimuthStage:
"""Sample manipulator. NOTE: The azimuth attribute is equivalent to GDA roty."""
return XYZAzimuthStage(
prefix=f"{B_PREFIX.beamline_prefix}-EA-SM-21:", azimuth_infix="ROTY"
)
8 changes: 4 additions & 4 deletions src/dodal/beamlines/b07_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
)
from dodal.devices.electron_analyser.base import EnergySource
from dodal.devices.electron_analyser.specs import SpecsDetector
from dodal.devices.motors import XYZPolarAzimuthStage
from dodal.devices.motors import XYZAzimuthPolarStage
from dodal.devices.pgm import PlaneGratingMonochromator
from dodal.log import set_beamline as set_log_beamline
from dodal.utils import BeamlinePrefix, get_beamline_name
Expand Down Expand Up @@ -54,13 +54,13 @@ def analyser(energy_source: EnergySource) -> SpecsDetector[LensMode, PsuMode]:


@devices.factory()
def sm() -> XYZPolarAzimuthStage:
def sm() -> XYZAzimuthPolarStage:
"""Sample manipulator."""
return XYZPolarAzimuthStage(
return XYZAzimuthPolarStage(
f"{C_PREFIX.beamline_prefix}-EA-SM-01:",
x_infix="XP",
y_infix="YP",
z_infix="ZP",
polar_infix="ROTA",
azimuth_infix="ROTB",
polar_infix="ROTA",
)
6 changes: 3 additions & 3 deletions src/dodal/beamlines/i05_1.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dodal.beamlines.i05_shared import devices as i05_shared_devices
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
from dodal.device_manager import DeviceManager
from dodal.devices.beamlines.i05_1 import XYZPolarAzimuthDefocusStage
from dodal.devices.beamlines.i05_1 import XYZAzimuthPolarDefocusStage
from dodal.log import set_beamline as set_log_beamline
from dodal.utils import BeamlinePrefix, get_beamline_name

Expand All @@ -15,6 +15,6 @@


@devices.factory
def sm() -> XYZPolarAzimuthDefocusStage:
def sm() -> XYZAzimuthPolarDefocusStage:
"""Sample Manipulator."""
return XYZPolarAzimuthDefocusStage(prefix=f"{PREFIX.beamline_prefix}-EA-SM-01:")
return XYZAzimuthPolarDefocusStage(prefix=f"{PREFIX.beamline_prefix}-EA-SM-01:")
8 changes: 4 additions & 4 deletions src/dodal/beamlines/i09.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
from dodal.beamlines.i09_2_shared import devices as i09_2_shared_devices
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
from dodal.device_manager import DeviceManager
from dodal.devices.beamlines.i09.enums import LensMode, PassEnergy, PsuMode
from dodal.devices.beamlines.i09 import LensMode, PassEnergy, PsuMode
from dodal.devices.common_dcm import DoubleCrystalMonochromatorWithDSpacing
from dodal.devices.electron_analyser.base import DualEnergySource
from dodal.devices.electron_analyser.vgscienta import VGScientaDetector
from dodal.devices.fast_shutter import DualFastShutter, GenericFastShutter
from dodal.devices.motors import XYZPolarAzimuthStage
from dodal.devices.motors import XYZAzimuthPolarStage
from dodal.devices.pgm import PlaneGratingMonochromator
from dodal.devices.selectable_source import SourceSelector
from dodal.devices.synchrotron import Synchrotron
Expand Down Expand Up @@ -101,6 +101,6 @@ def lakeshore() -> Lakeshore336:


@devices.factory()
def smpm() -> XYZPolarAzimuthStage:
def smpm() -> XYZAzimuthPolarStage:
"""Sample Manipulator."""
return XYZPolarAzimuthStage(prefix=f"{I_PREFIX.beamline_prefix}-MO-SMPM-01:")
return XYZAzimuthPolarStage(prefix=f"{I_PREFIX.beamline_prefix}-MO-SMPM-01:")
6 changes: 3 additions & 3 deletions src/dodal/beamlines/i09_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dodal.devices.common_dcm import DoubleCrystalMonochromatorWithDSpacing
from dodal.devices.electron_analyser.base import EnergySource
from dodal.devices.electron_analyser.specs import SpecsDetector
from dodal.devices.motors import XYZPolarAzimuthTiltStage
from dodal.devices.motors import XYZAzimuthTiltPolarStage
from dodal.devices.synchrotron import Synchrotron
from dodal.devices.temperture_controller import Lakeshore336
from dodal.log import set_beamline as set_log_beamline
Expand Down Expand Up @@ -48,6 +48,6 @@ def lakeshore() -> Lakeshore336:


@devices.factory()
def hsmpm() -> XYZPolarAzimuthTiltStage:
def hsmpm() -> XYZAzimuthTiltPolarStage:
"""Sample Manipulator."""
return XYZPolarAzimuthTiltStage(prefix=f"{PREFIX.beamline_prefix}-MO-HSMPM-01:")
return XYZAzimuthTiltPolarStage(prefix=f"{PREFIX.beamline_prefix}-MO-HSMPM-01:")
16 changes: 15 additions & 1 deletion src/dodal/beamlines/i21.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
from dodal.device_manager import DeviceManager
from dodal.devices.beamlines.i21 import Grating
from dodal.devices.beamlines.i21 import (
Grating,
I21SampleManipulatorStage,
ToolPointMotion,
)
from dodal.devices.insertion_device import (
Apple2,
Apple2EnforceLHMoveController,
Expand Down Expand Up @@ -129,3 +133,13 @@ def energy(
@devices.factory()
def sample_temperature_controller() -> Lakeshore336:
return Lakeshore336(prefix=f"{PREFIX.beamline_prefix}-EA-TCTRL-01:")


@devices.factory()
def smp() -> I21SampleManipulatorStage:
return I21SampleManipulatorStage(prefix=f"{PREFIX.beamline_prefix}-EA-SMPL-01:")


@devices.factory()
def uvw(smp: I21SampleManipulatorStage) -> ToolPointMotion:
return ToolPointMotion(smp)
14 changes: 6 additions & 8 deletions src/dodal/devices/beamlines/i05/i05_motors.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
from dodal.devices.beamlines.i05_shared.rotation_signals import (
create_rotational_ij_component_signals,
)
from dodal.devices.motors import (
_AZIMUTH,
_POLAR,
_TILT,
_X,
_Y,
_Z,
XYZPolarAzimuthTiltStage,
XYZAzimuthTiltPolarStage,
create_rotational_ij_component_signals,
)


class I05Goniometer(XYZPolarAzimuthTiltStage):
class I05Goniometer(XYZAzimuthTiltPolarStage):
"""Six-physical-axis stage with a standard xyz translational stage and three axis of
rotation: polar, azimuth, and tilt.
rotation: azimuth, tilt and polar.

In addition, it defines two virtual translational axes derived signals, `perp` and
`long`, which form a rotated Cartesian frame within the x-y plane.
Expand All @@ -36,9 +34,9 @@ def __init__(
x_infix: str = _X,
y_infix: str = _Y,
z_infix: str = _Z,
polar_infix: str = _POLAR,
azimuth_infix: str = _AZIMUTH,
tilt_infix: str = _TILT,
polar_infix: str = _POLAR,
rotation_angle_deg: float = 50.0,
name: str = "",
):
Expand All @@ -50,9 +48,9 @@ def __init__(
x_infix=x_infix,
y_infix=y_infix,
z_infix=z_infix,
polar_infix=polar_infix,
azimuth_infix=azimuth_infix,
tilt_infix=tilt_infix,
polar_infix=polar_infix,
)

with self.add_children_as_readables():
Expand Down
4 changes: 2 additions & 2 deletions src/dodal/devices/beamlines/i05_1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .i05_1_motors import XYZPolarAzimuthDefocusStage
from .i05_1_motors import XYZAzimuthPolarDefocusStage

__all__ = ["XYZPolarAzimuthDefocusStage"]
__all__ = ["XYZAzimuthPolarDefocusStage"]
14 changes: 7 additions & 7 deletions src/dodal/devices/beamlines/i05_1/i05_1_motors.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from ophyd_async.epics.motor import Motor

from dodal.devices.beamlines.i05_shared.rotation_signals import (
from dodal.devices.motors import (
XYZAzimuthPolarStage,
create_rotational_ij_component_signals,
)
from dodal.devices.motors import XYZPolarAzimuthStage


class XYZPolarAzimuthDefocusStage(XYZPolarAzimuthStage):
"""Six-physical-axis stage with a standard xyz stage, 2 axis of rotation: polar,
azimuth and one extra tranlastional axis defocus.
class XYZAzimuthPolarDefocusStage(XYZAzimuthPolarStage):
"""Six-physical-axis stage with a standard xyz stage, 2 axis of rotation: azimuth,
polar and one extra tranlastional axis defocus.

This device exposes four virtual translational axes that are defined in frames
of reference attached to the sample:
Expand Down Expand Up @@ -40,8 +40,8 @@ def __init__(
x_infix: str = "SMX",
y_infix: str = "SMY",
z_infix: str = "SMZ",
polar_infix: str = "POL",
azimuth_infix: str = "AZM",
polar_infix: str = "POL",
defocus_infix: str = "SMDF",
name: str = "",
):
Expand All @@ -51,8 +51,8 @@ def __init__(
x_infix=x_infix,
y_infix=y_infix,
z_infix=z_infix,
polar_infix=polar_infix,
azimuth_infix=azimuth_infix,
polar_infix=polar_infix,
)

with self.add_children_as_readables():
Expand Down
10 changes: 9 additions & 1 deletion src/dodal/devices/beamlines/i21/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
from .enums import Grating
from .i21_motors import I21SampleManipulatorStage
from .toolpoint_motion import ToolPointMotion, UVWMotorPositions, XYZMotorPositions

__all__ = ["Grating"]
__all__ = [
"Grating",
"I21SampleManipulatorStage",
"ToolPointMotion",
"UVWMotorPositions",
"XYZMotorPositions",
]
75 changes: 75 additions & 0 deletions src/dodal/devices/beamlines/i21/i21_motors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from ophyd_async.epics.motor import Motor

from dodal.devices.motors import (
_AZIMUTH,
_TILT,
_X,
_Y,
_Z,
XYZAzimuthTiltPolarStage,
create_rotational_ij_component_signals,
)


class I21SampleManipulatorStage(XYZAzimuthTiltPolarStage):
"""Seven-axis stage with a standard xyz stage and four axis of rotation: azimuth,
tilt, polar, and difftth (diffraction diode rotation). It also exposes two
virtual translational axes that are defined in frames of reference attached to the
sample.

- `para` and `perp`:
Parallel and perpendicular translation axes in the sample frame.
These axes are derived from the lab-frame x and y motors and rotate
with the polar angle, so that motion along `para` and `perp`
remains aligned with the sample regardless of its polar rotation.

Both virtual axes behave as ordinary orthogonal Cartesian translations
from the user's point of view, while internally coordinating motion of the
underlying motors to account for the current rotation angles.

This allows users to position the sample in physically meaningful, sample-aligned
coordinates without needing to manually compensate for polar rotations.

Note: I21 currently uses the following PV to variable
- PV AZIMUTH but calls the variable phi.
- PV TILT but calls variable chi.
- PV RZ but calls it th (theta).

Inheriting from standard motor class until decided if i21 uses standard name
convention or need to update variables for this class.
"""

def __init__(
self,
prefix: str,
name: str = "",
x_infix: str = _X,
y_infix: str = _Y,
z_infix: str = _Z,
azimuth_infix: str = _AZIMUTH,
tilt_infix: str = _TILT,
polar_infix: str = "RZ",
difftth_infix: str = "DRING",
):
super().__init__(
prefix=prefix,
name=name,
x_infix=x_infix,
y_infix=y_infix,
z_infix=z_infix,
azimuth_infix=azimuth_infix,
tilt_infix=tilt_infix,
polar_infix=polar_infix,
)
with self.add_children_as_readables():
# Diffraction diode rotation.
self.difftth = Motor(prefix + difftth_infix)

self.para, self.perp = create_rotational_ij_component_signals(
i_read=self.x.user_readback,
j_read=self.y.user_readback,
i_write=self.x,
j_write=self.y,
angle_deg=self.polar.user_readback,
clockwise_frame=False,
)
Loading