fix: 按复位请求目标确认参考版本并隔离复位状态
防止在途旧帧提前触发归零,并保留旧 reset 用法。SDK 101 项针对性回归与 lint 通过。
This commit is contained in:
@@ -155,6 +155,33 @@ def collect_baseline(session, source, *, start=1, count=30, reference_id="ref-1"
|
||||
]
|
||||
|
||||
|
||||
def test_external_zero_waits_for_the_requested_target_reference_version():
|
||||
source = FakeMeasurementSource(raw_for=lambda _: (10.0, 20.0, 30.0))
|
||||
session = make_session(source)
|
||||
session.request_zero_external_reset(
|
||||
reference_id="second-reset", declared_unloaded=True, target_reference_version=2
|
||||
)
|
||||
outputs = []
|
||||
for frame_id, version in enumerate([0, 1, 1, 2, 2]):
|
||||
row = source.read_measurement_frame(None, frame_id=frame_id)
|
||||
outputs.append(session.process_measurement(row, stamp(frame_id), tracker_reset_seq=version))
|
||||
assert [o.measurement.zero.phase for o in outputs] == [
|
||||
"resetting", "resetting", "resetting", "collecting", "collecting"
|
||||
]
|
||||
assert outputs[-1].measurement.zero.collected_frames == 2
|
||||
assert outputs[-1].measurement.zero.first_frame_id == 3
|
||||
|
||||
|
||||
@pytest.mark.parametrize("target", [0, -1, True])
|
||||
def test_external_zero_rejects_invalid_target_reference_version(target):
|
||||
session = make_session(FakeMeasurementSource())
|
||||
with pytest.raises(ValueError, match="target_reference_version"):
|
||||
session.request_zero_external_reset(
|
||||
reference_id="invalid-target", declared_unloaded=True,
|
||||
target_reference_version=target,
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# T1: executable fake chain, one model call, cached reads, missing is not zero
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -1210,3 +1237,39 @@ def test_old_readout_entry_keeps_filter_then_convert_order() -> None:
|
||||
# is exactly the recorded historical behaviour.
|
||||
assert outputs[-1] == pytest.approx(4.0)
|
||||
assert readout.raw_unfiltered == (250.0, 0.0, 0.0)
|
||||
|
||||
|
||||
def test_readout_reset_halves_clear_only_their_own_state() -> None:
|
||||
"""The flow EMA is image-side state; the readout history is force-side state."""
|
||||
from orisys.force_readout import ForceReadout
|
||||
|
||||
flow = np.zeros((2, 2, 2), dtype=np.float32)
|
||||
|
||||
readout = ForceReadout({"flow_ema_alpha": 0.5, "force_median_window": 3},
|
||||
config_fps=30.0)
|
||||
readout.apply_flow_ema(flow)
|
||||
readout.apply((10.0, 1.0, 2.0))
|
||||
filtered = readout.filtered_raw
|
||||
raw_unfiltered = readout.raw_unfiltered
|
||||
unfiltered_newton = readout.unfiltered_newton
|
||||
|
||||
readout.reset_flow_ema()
|
||||
assert readout._ema_flow is None
|
||||
# The force-side history survives a reset that only rebases the image stage.
|
||||
assert readout.filtered_raw == filtered
|
||||
assert readout.raw_unfiltered == raw_unfiltered
|
||||
assert readout.unfiltered_newton == unfiltered_newton
|
||||
|
||||
readout = ForceReadout({"flow_ema_alpha": 0.5, "force_median_window": 3},
|
||||
config_fps=30.0)
|
||||
readout.apply_flow_ema(flow)
|
||||
readout.apply((10.0, 1.0, 2.0))
|
||||
readout.reset_readout()
|
||||
assert readout._ema_flow is not None
|
||||
assert readout.filtered_raw is None
|
||||
assert readout.raw_unfiltered is None
|
||||
assert readout.unfiltered_newton is None
|
||||
|
||||
readout.reset()
|
||||
assert readout._ema_flow is None
|
||||
assert readout.filtered_raw is None
|
||||
|
||||
Reference in New Issue
Block a user