mirror of
https://github.com/bec-project/ophyd_devices.git
synced 2026-11-10 05:03:54 +01:00
fix(positioner): validate deadband against tolerance
This commit is contained in:
1 parent
42370b4c3c
commit
003717ff46
2 files changed
+35
-5
No files matched your search
@@ -142,7 +142,7 @@ class PSISimplePositionerBase(ABC, PSIDeviceBase, PositionerBase):
|
||||
Args:
|
||||
name (str): (required) the name of the device
|
||||
limits (list | tuple | None): If given, a length-2 sequence within the range of which movement is allowed.
|
||||
deadband (float | None): If given, set a soft deadband of this absolute value, within which positioner moves will return immediately. If the positioner has no motor_done_move signal, you must provide this.
|
||||
deadband (float | None): If given, set a soft deadband of this absolute value, within which positioner moves will return immediately. If the positioner has no motor_done_move signal, you must provide this. It must not exceed the configured tolerance when moving.
|
||||
use_put_completion (bool | None): If given, use put completion on the setpoint signal to resolve the move status.
|
||||
override_suffixes (dict[str, str]): a dictionary of signal_name: pv_suffix which will replace the values in the signal classvar.
|
||||
"""
|
||||
@@ -294,13 +294,17 @@ class PSISimplePositionerBase(ABC, PSIDeviceBase, PositionerBase):
|
||||
TimeoutError
|
||||
When motion takes longer than `timeout`
|
||||
ValueError
|
||||
On invalid positions
|
||||
On invalid positions or if the deadband exceeds the configured tolerance
|
||||
RuntimeError
|
||||
If motion fails other than timing out
|
||||
"""
|
||||
|
||||
if self._deadband is not None and abs(position - self._position) < self._deadband:
|
||||
return MoveStatus(self, position, done=True, success=True)
|
||||
if self._deadband is not None:
|
||||
tolerance = self.tolerance.get()
|
||||
if self._deadband > tolerance:
|
||||
raise ValueError(f"Deadband {self._deadband} must not exceed tolerance {tolerance}")
|
||||
if abs(position - self._position) < self._deadband:
|
||||
return MoveStatus(self, position, done=True, success=True)
|
||||
|
||||
if timeout is None:
|
||||
timeout = self._timeout
|
||||
|
||||
@@ -178,7 +178,7 @@ def mock_done_signal_positioner_with_tolerance():
|
||||
with patch.object(ophyd, "cl") as mock_cl:
|
||||
mock_cl.get_pv = MockPV
|
||||
mock_cl.thread_class = threading.Thread
|
||||
dev = DoneSignalPositionerWithTolerance(name=name, prefix=prefix, deadband=0.01)
|
||||
dev = DoneSignalPositionerWithTolerance(name=name, prefix=prefix, deadband=0.001)
|
||||
patch_dual_pvs(dev)
|
||||
dev.wait_for_connection()
|
||||
dev._set_position(0)
|
||||
@@ -287,3 +287,29 @@ def test_tolerance_checks_requested_target_even_if_setpoint_changes(
|
||||
assert st.target == 5
|
||||
with pytest.raises(RuntimeError, match="outside of tolerance"):
|
||||
st.wait(timeout=1)
|
||||
|
||||
|
||||
def test_move_rejects_tolerance_tighter_than_deadband_before_setpoint_write(
|
||||
mock_done_signal_positioner_with_tolerance,
|
||||
):
|
||||
dev = mock_done_signal_positioner_with_tolerance
|
||||
dev.tolerance.put(0.0005)
|
||||
|
||||
with patch.object(dev.user_setpoint, "put", wraps=dev.user_setpoint.put) as put:
|
||||
with pytest.raises(ValueError, match="tolerance"):
|
||||
dev.move(5, wait=False)
|
||||
put.assert_not_called()
|
||||
|
||||
|
||||
def test_equal_deadband_and_tolerance_allow_instant_success(
|
||||
mock_done_signal_positioner_with_tolerance,
|
||||
):
|
||||
dev = mock_done_signal_positioner_with_tolerance
|
||||
assert dev.tolerance.get() == dev._deadband
|
||||
|
||||
with patch.object(dev.user_setpoint, "put", wraps=dev.user_setpoint.put) as put:
|
||||
st = dev.move(0.0005, wait=False)
|
||||
put.assert_not_called()
|
||||
|
||||
assert st.done
|
||||
assert st.success
|
||||
Reference in new issue
Block a user