feat(iphone): store topology + 2d validity

Add arkit_joint_names, arkit_parents, persons_arkit_2d_valid
to State. Wire TAG_TOPOLOGY=7 dispatch in IphoneUSBSource:
decode_topology stored under lock; TAG_SKELETON2D branch now
also stores per-joint validity bool array (91,) alongside pts.
This commit is contained in:
clement
2026-06-30 22:05:32 +02:00
parent b00b6dfbda
commit 04eb182fab
3 changed files with 33 additions and 2 deletions
+16 -2
View File
@@ -21,10 +21,12 @@ from data_only_viz.scripts.iphone_usb_bridge import (
connect_device, decode_skeleton, decode_skeleton2D,
iter_frames, TAG_SKELETON, TAG_SKELETON2D,
)
from data_only_viz.arkit_topology import decode_topology
from data_only_viz.state import PoseKp
TAG_VIDEO = 2
TAG_HANDS = 4
TAG_TOPOLOGY = 7
LOG = logging.getLogger("iphone_usb_source")
_HAND_BYTES = 1 + 21 * 12 # chirality:u8 + 21 × (x,y,z) × 4 bytes BE f32
@@ -152,10 +154,22 @@ class IphoneUSBSource:
elif tag == TAG_SKELETON2D and self.state is not None:
pts = decode_skeleton2D(payload)
if pts is not None:
arr = np.array([[x, y] for (x, y, _v) in pts], dtype=np.float32)
arr = np.array([[x, y] for (x, y, _v) in pts],
dtype=np.float32)
valid = np.array([v for (_x, _y, v) in pts],
dtype=bool)
with self.state.lock():
self.state.persons_arkit_2d[pid] = arr
self.state.persons_arkit_2d_t[pid] = time.perf_counter()
self.state.persons_arkit_2d_valid[pid] = valid
self.state.persons_arkit_2d_t[pid] = \
time.perf_counter()
elif tag == TAG_TOPOLOGY and self.state is not None:
topo = decode_topology(payload)
if topo is not None:
names, parents = topo
with self.state.lock():
self.state.arkit_joint_names = names
self.state.arkit_parents = parents
elif tag == TAG_HANDS:
hands = _decode_hands(payload)
if hands is not None and self.state is not None:
+3
View File
@@ -148,6 +148,9 @@ class State:
# screen coords 0..1) per pid. Updated by IphoneUSBSource on TAG_SKELETON2D.
persons_arkit_2d: dict[int, "np.ndarray"] = field(default_factory=dict)
persons_arkit_2d_t: dict[int, float] = field(default_factory=dict)
persons_arkit_2d_valid: dict = field(default_factory=dict)
arkit_joint_names: list = field(default_factory=list)
arkit_parents: list = field(default_factory=list)
# ---- LiDAR / ICP mesh fusion (Task 8 - 2026-05-14) ----
# Set by the LidarTCPReader poller; consumed by FusionWorker.run_once.
@@ -0,0 +1,14 @@
"""State carries ARKit topology + 2D validity for the renderer."""
from data_only_viz.state import State
def test_state_has_topology_fields():
s = State()
assert s.arkit_joint_names == []
assert s.arkit_parents == []
assert s.persons_arkit_2d_valid == {}
def test_topology_tag_constant():
from data_only_viz.iphone_usb_source import TAG_TOPOLOGY
assert TAG_TOPOLOGY == 7