feat(ui): 3D stick figure visualization with COCO-17 joints + smooth animations

- Add ui/spatial.html: Three.js 3D renderer for spatial dashboard
- COCO-17 keypoint definitions inline; 18 bone pairs (STANDING_KEYPOINTS)
- Three pose variants: standing (green), sitting (yellow), lying (blue)
- Persistent figure map (no recreate-on-every-frame) via FigureState class
- Position lerp (factor 0.1) for smooth interpolation between ticks
- Posture-transition keypoint blending over ~1s (poseBlend 0->1 at +0.03/frame)
- Breathing animation: torso Y-scale at detected BR rate from /api/v1/vital-signs
- Activity-based sway: still=0.01m, moderate=0.03m, active=0.08m
- Opacity fadeout for disappearing bodies (quality field decrements at -0.05/tick)
- WS subscription to spatial_update + body_cluster_update; falls back to polling
- Fallback: single standing figure from voxel centroid when no cluster data

Depends on /api/v1/spatial/clusters endpoint from body tracking PR (#487).
This commit is contained in:
Deploy Bot 2026-04-28 15:20:23 -04:00
parent 36e70bf229
commit 9746d255ff
2 changed files with 1285 additions and 0 deletions

View File

@ -8,6 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- **3D stick figure visualization for spatial dashboard** (`ui/spatial.html`) —
Renders COCO-17 keypoint skeletons from `/api/v1/spatial/clusters` body cluster
centroids using Three.js. Three pose variants: standing (green), sitting (yellow),
lying (blue). Persistent figure map with position lerp (factor 0.1), smooth
posture-transition keypoint blending (~1s), breathing-rate Y-scale animation,
activity-based sway (still=0.01m, moderate=0.03m, active=0.08m), and opacity
fadeout for disappearing bodies. Falls back to polling `/api/v1/spatial/clusters`
every 2s when WebSocket is unavailable. Depends on body tracking endpoints
provided by the body tracking PR (#487).
- **`nvsim` crate — deterministic NV-diamond magnetometer pipeline simulator** (ADR-089) —
New standalone leaf crate at `v2/crates/nvsim` modeling a forward-only
magnetic sensing path: scene → source synthesis (BiotSavart, dipole,

1276
ui/spatial.html Normal file

File diff suppressed because it is too large Load Diff