Add --debug-rumble frame tracing to UART bridge
This commit is contained in:
parent
b7b2041e3d
commit
8d9bb74c7d
2 changed files with 36 additions and 12 deletions
|
|
@ -202,12 +202,15 @@ def apply_rumble(
|
|||
controller: sdl3.SDL_Gamepad,
|
||||
low_frequency: float,
|
||||
high_frequency: float,
|
||||
) -> bool:
|
||||
"""Apply normalized low/high rumble magnitudes to an SDL controller."""
|
||||
) -> Tuple[bool, bool]:
|
||||
"""Apply normalized low/high rumble magnitudes to an SDL controller.
|
||||
|
||||
Returns (motor active, SDL accepted the request).
|
||||
"""
|
||||
low = int(max(0.0, min(1.0, low_frequency)) * 0xFFFF)
|
||||
high = int(max(0.0, min(1.0, high_frequency)) * 0xFFFF)
|
||||
sdl3.SDL_RumbleGamepad(controller, low, high, RUMBLE_DURATION_MS)
|
||||
return low != 0 or high != 0
|
||||
accepted = bool(sdl3.SDL_RumbleGamepad(controller, low, high, RUMBLE_DURATION_MS))
|
||||
return low != 0 or high != 0, accepted
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -247,6 +250,8 @@ class ControllerContext:
|
|||
gyro_bias_samples: int = 0
|
||||
gyro_bias_locked: bool = False
|
||||
last_debug_imu_print: float = 0.0
|
||||
last_debug_rumble: Optional[Tuple[float, float]] = None
|
||||
debug_rumble_frames: int = 0
|
||||
|
||||
|
||||
def capture_stick_offsets(controller: sdl3.SDL_Gamepad) -> Dict[int, int]:
|
||||
|
|
@ -758,6 +763,11 @@ def build_arg_parser() -> argparse.ArgumentParser:
|
|||
action="store_true",
|
||||
help="Print raw IMU sensor readings and converted values for debugging.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--debug-rumble",
|
||||
action="store_true",
|
||||
help="Print every decoded rumble frame received from the Pico and whether SDL accepted it.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-imu",
|
||||
action="store_true",
|
||||
|
|
@ -815,6 +825,7 @@ class BridgeConfig:
|
|||
swap_abxy_ids: set[str]
|
||||
swap_abxy_global: bool
|
||||
debug_imu: bool = False
|
||||
debug_rumble: bool = False
|
||||
no_imu: bool = False
|
||||
gyro_scale: float = 1.0
|
||||
|
||||
|
|
@ -907,6 +918,7 @@ def build_bridge_config(console: Console, args: argparse.Namespace) -> BridgeCon
|
|||
swap_abxy_ids=set(swap_abxy_guids), # filled later once stable IDs are known
|
||||
swap_abxy_global=bool(args.swap_abxy),
|
||||
debug_imu=bool(args.debug_imu),
|
||||
debug_rumble=bool(args.debug_rumble),
|
||||
no_imu=bool(args.no_imu),
|
||||
gyro_scale=float(args.gyro_scale),
|
||||
)
|
||||
|
|
@ -1602,13 +1614,24 @@ def service_contexts(
|
|||
if rumble is None:
|
||||
break
|
||||
latest_rumble = rumble
|
||||
ctx.debug_rumble_frames += 1
|
||||
|
||||
if latest_rumble is not None:
|
||||
# Apply only the freshest rumble command seen during this tick.
|
||||
ctx.rumble_active = apply_rumble(
|
||||
ctx.rumble_active, accepted = apply_rumble(
|
||||
ctx.controller, latest_rumble[0], latest_rumble[1]
|
||||
)
|
||||
ctx.last_rumble_at = now
|
||||
if config.debug_rumble and (
|
||||
latest_rumble != ctx.last_debug_rumble or not accepted
|
||||
):
|
||||
ctx.last_debug_rumble = latest_rumble
|
||||
error = "" if accepted else f" sdl_error={sdl3.SDL_GetError().decode(errors='ignore')!r}"
|
||||
print(
|
||||
f"[RUMBLE idx={ctx.controller_index}] frame#{ctx.debug_rumble_frames} "
|
||||
f"low={latest_rumble[0]:.3f} high={latest_rumble[1]:.3f} "
|
||||
f"accepted={accepted}{error}"
|
||||
)
|
||||
elif (
|
||||
ctx.rumble_active
|
||||
and (now - ctx.last_rumble_at) > RUMBLE_IDLE_TIMEOUT
|
||||
|
|
|
|||
|
|
@ -46,17 +46,18 @@ def test_apply_rumble_maps_low_and_high_with_50ms_duration(
|
|||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
calls: list[tuple[int, int, int]] = []
|
||||
monkeypatch.setattr(
|
||||
bridge.sdl3,
|
||||
"SDL_RumbleGamepad",
|
||||
lambda _controller, low, high, duration: calls.append((low, high, duration)),
|
||||
)
|
||||
|
||||
def fake_rumble(_controller, low, high, duration):
|
||||
calls.append((low, high, duration))
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(bridge.sdl3, "SDL_RumbleGamepad", fake_rumble)
|
||||
controller = cast(sdl3.SDL_Gamepad, object())
|
||||
|
||||
assert bridge.apply_rumble(controller, 1.0, 0.5)
|
||||
assert bridge.apply_rumble(controller, 1.0, 0.5) == (True, True)
|
||||
assert calls[-1] == (0xFFFF, 0x7FFF, 50)
|
||||
|
||||
assert not bridge.apply_rumble(controller, 0.0, 0.0)
|
||||
assert bridge.apply_rumble(controller, 0.0, 0.0) == (False, True)
|
||||
assert calls[-1] == (0, 0, 50)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue