Keep the 45-byte pose frame consistent across docs, simulator, and prototype, clarify MinIO is not peer sync, and state clearly that the repo is a from-scratch platform sketch with options rather than mandates.
47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
"""Pose broadcast frame encode/decode roundtrip."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from virtual_drone.broadcast import FRAME, decode_state, encode_state
|
|
from virtual_drone.flight import Pose
|
|
|
|
|
|
def test_frame_size_matches_wire_spec() -> None:
|
|
# Keep docs/04, the journey, and prototype/src/sim.ts POSE_BYTES in lockstep.
|
|
assert FRAME.size == 45
|
|
|
|
|
|
def test_encode_decode_roundtrip() -> None:
|
|
pose = Pose(
|
|
ts_ns=1_700_000_000_000_000_000,
|
|
x=123.456,
|
|
y=78.9,
|
|
z=60.0,
|
|
roll=1.5,
|
|
pitch=-2.0,
|
|
yaw=45.0,
|
|
vx=3.2,
|
|
vy=-1.1,
|
|
vz=0.05,
|
|
)
|
|
payload = encode_state("dr-01", pose, flags=0)
|
|
assert len(payload) == FRAME.size
|
|
|
|
decoded = decode_state(payload)
|
|
assert decoded is not None
|
|
assert decoded["peer_id"] == "dr-01"
|
|
assert decoded["ts_ns"] == pose.ts_ns
|
|
assert decoded["pos_x"] == pytest.approx(pose.x, abs=0.001)
|
|
assert decoded["pos_y"] == pytest.approx(pose.y, abs=0.001)
|
|
assert decoded["pos_z"] == pytest.approx(pose.z, abs=0.001)
|
|
assert decoded["roll"] == pytest.approx(pose.roll, abs=0.01)
|
|
assert decoded["pitch"] == pytest.approx(pose.pitch, abs=0.01)
|
|
assert decoded["yaw"] == pytest.approx(pose.yaw, abs=0.01)
|
|
|
|
|
|
def test_rejects_invalid_payload() -> None:
|
|
assert decode_state(b"short") is None
|
|
assert decode_state(b"XX" + b"\0" * (FRAME.size - 2)) is None
|