Consume UART motion samples once per USB report like the AIO

The bridge now forwards each SDL sensor sample once instead of re-sending
its last window at 500 Hz, and the firmware pools pending samples per slot
until a USB report retires them. A stalled or slow sensor stream can no
longer be re-integrated as continuous rotation in quaternion mode.
--debug-imu reports the sample rate, |a| in g and bias lock state.
This commit is contained in:
Joey Yakimowich-Payne 2026-09-22 16:56:45 -06:00
commit 6c27e601d9
5 changed files with 69 additions and 9 deletions

View file

@ -98,7 +98,10 @@ def test_sensor_buffer_retains_latest_three_samples() -> None:
]
def test_service_republishes_latest_imu_window(monkeypatch: MonkeyPatch) -> None:
def test_service_forwards_each_imu_window_once(monkeypatch: MonkeyPatch) -> None:
"""A stalled sensor stream must not keep re-sending its last window: the
firmware pools samples per USB report, so a repeat would be integrated as
continuous rotation."""
uart = RecordingUART()
controller = cast(sdl3.SDL_Gamepad, object())
ctx = bridge.ControllerContext(controller, 7, 0, "dualsense", "/dev/null")
@ -124,6 +127,8 @@ def test_service_republishes_latest_imu_window(monkeypatch: MonkeyPatch) -> None
console = Console(file=StringIO())
bridge.service_contexts(1.0, args, config, contexts, links, console)
bridge.service_contexts(2.0, args, config, contexts, links, console)
ctx.imu_samples.append(IMUSample(19, 20, 21, 22, 23, 24))
bridge.service_contexts(3.0, args, config, contexts, links, console)
assert uart.sent_imu == [tuple(samples), tuple(samples)]
assert ctx.imu_samples == samples
assert uart.sent_imu == [tuple(samples), (), (IMUSample(19, 20, 21, 22, 23, 24),)]
assert ctx.imu_samples == []