ADR-121 (Normal Mode) gave us distance and a passable breathing estimate but couldn't see the heartbeat โ cardiac chest displacement (~0.5 mm) is well below the cm quantisation of `distance:NNN`. Engineering Mode streams per-range-gate energy at the same 6 Hz cadence (15 motion + 15 micromotion gates, u32 LE each). The micromotion bin at the target's distance carries enough cardiac modulation for FFT peak-detection in the 0.8-2.0 Hz band. Live result, seated operator ~1.5 m from the radar: ๐ซ ๐ก 13.0 BPM ยท 37% ะฝะพัะผะฐ 12-20 ๐ ๐ก 76 BPM ยท 63% ะฝะพัะผะฐ 60-100 Implementation: - Send enable-config โ set-mode(0x04) โ disable-config on startup; fall back to Normal-Mode ASCII parsing if the sequence fails. - Binary frame parser: F4 F3 F2 F1 | len(2) | 0x01 | dist(2) | 8z | motion[15]รu32 LE | micro[15]รu32 LE | F8 F7 F6 F5. Gate the ASCII line-drain on the engineering_mode flag โ first cut ran both unconditionally and destroyed 80% of partial frames mid-buffer. - Target-gate selection: distance-bracketed gate first, mid-range micro-peak fallback, gate 1 default. Per-gate ring buffer of log-energies feeds a Hann + radix-2 FFT. - /api/v1/mmwave/vitals now returns real `heart_rate_bpm`. - raw.html: ๐ ๐ก pill now shows real values (no more "n/a" placeholder). - New probe script v2/scripts/probe_ld2402_engineering.py used to reverse-engineer the wire format; kept in tree for next time. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| components | ||
| config | ||
| mobile | ||
| observatory | ||
| pose-fusion | ||
| services | ||
| tests | ||
| utils | ||
| README.md | ||
| TEST_REPORT.md | ||
| app.js | ||
| index.html | ||
| observatory.html | ||
| pose-fusion.html | ||
| raw.html | ||
| start-ui.sh | ||
| style.css | ||
| viz.html | ||
README.md
WiFi DensePose UI
A modular, modern web interface for the WiFi DensePose human tracking system. Provides real-time monitoring, WiFi sensing visualization, and pose estimation from CSI (Channel State Information).
Architecture
The UI follows a modular architecture with clear separation of concerns:
ui/
โโโ app.js # Main application entry point
โโโ index.html # HTML shell with tab structure
โโโ style.css # Complete CSS design system
โโโ config/
โ โโโ api.config.js # API endpoints and configuration
โโโ services/
โ โโโ api.service.js # HTTP API client
โ โโโ websocket.service.js # WebSocket connection manager
โ โโโ websocket-client.js # Low-level WebSocket client
โ โโโ pose.service.js # Pose estimation API wrapper
โ โโโ sensing.service.js # WiFi sensing data service (live + simulation fallback)
โ โโโ health.service.js # Health monitoring API wrapper
โ โโโ stream.service.js # Streaming API wrapper
โ โโโ data-processor.js # Signal data processing utilities
โโโ components/
โ โโโ TabManager.js # Tab navigation component
โ โโโ DashboardTab.js # Dashboard with live system metrics
โ โโโ SensingTab.js # WiFi sensing visualization (3D signal field, metrics)
โ โโโ LiveDemoTab.js # Live pose detection with setup guide
โ โโโ HardwareTab.js # Hardware configuration
โ โโโ SettingsPanel.js # Settings panel
โ โโโ PoseDetectionCanvas.js # Canvas-based pose skeleton renderer
โ โโโ gaussian-splats.js # 3D Gaussian splat signal field renderer (Three.js)
โ โโโ body-model.js # 3D body model
โ โโโ scene.js # Three.js scene management
โ โโโ signal-viz.js # Signal visualization utilities
โ โโโ environment.js # Environment/room visualization
โ โโโ dashboard-hud.js # Dashboard heads-up display
โโโ utils/
โ โโโ backend-detector.js # Auto-detect backend availability
โ โโโ mock-server.js # Mock server for testing
โ โโโ pose-renderer.js # Pose rendering utilities
โโโ tests/
โโโ test-runner.html # Test runner UI
โโโ test-runner.js # Test framework and cases
โโโ integration-test.html # Integration testing page
Features
WiFi Sensing Tab
- 3D Gaussian-splat signal field visualization (Three.js)
- Real-time RSSI, variance, motion band, breathing band metrics
- Presence/motion classification with confidence scores
- Data source banner: green "LIVE - ESP32", yellow "RECONNECTING...", or red "SIMULATED DATA"
- Sparkline RSSI history graph
- "About This Data" card explaining CSI capabilities per sensor count
Live Demo Tab
- WebSocket-based real-time pose skeleton rendering
- Estimation Mode badge: green "Signal-Derived" or blue "Model Inference"
- Setup Guide panel showing what each ESP32 count provides:
- 1 ESP32: presence, breathing, gross motion
- 2-3 ESP32s: body localization, motion direction
- 4+ ESP32s + trained model: individual limb tracking, full pose
- Debug mode with log export
- Zone selection and force-reconnect controls
- Performance metrics sidebar (frames, uptime, errors)
Dashboard
- Live system health monitoring
- Real-time pose detection statistics
- Zone occupancy tracking
- System metrics (CPU, memory, disk)
- API status indicators
Hardware Configuration
- Interactive antenna array visualization
- Real-time CSI data display
- Configuration panels
- Hardware status monitoring
Data Sources
The sensing service (sensing.service.js) supports three connection states:
| State | Banner Color | Description |
|---|---|---|
| LIVE - ESP32 | Green | Connected to the Rust sensing server receiving real CSI data |
| RECONNECTING | Yellow (pulsing) | WebSocket disconnected, retrying (up to 20 attempts) |
| SIMULATED DATA | Red | Fallback to client-side simulation after 5+ failed reconnects |
Simulated frames include a _simulated: true marker so code can detect synthetic data.
Backends
Rust Sensing Server (primary)
The Rust-based wifi-densepose-sensing-server serves the UI and provides:
GET /healthโ server healthGET /api/v1/sensing/latestโ latest sensing featuresGET /api/v1/vital-signsโ vital sign estimates (HR/RR)GET /api/v1/model/infoโ RVF model container infoWS /ws/sensingโ real-time sensing data streamWS /api/v1/stream/poseโ real-time pose keypoint stream
Python FastAPI (legacy)
The original Python backend on port 8000 is still supported. The UI auto-detects which backend is available via backend-detector.js.
Quick Start
With Docker (recommended)
cd docker/
# Default: auto-detects ESP32 on UDP 5005, falls back to simulation
docker-compose up
# Force real ESP32 data
CSI_SOURCE=esp32 docker-compose up
# Force simulation (no hardware needed)
CSI_SOURCE=simulated docker-compose up
Open http://localhost:3000/ui/index.html
With local Rust binary
cd v2
cargo build -p wifi-densepose-sensing-server --no-default-features
# Run with simulated data
../../target/debug/sensing-server --source simulated --tick-ms 100 --ui-path ../../ui --http-port 3000
# Run with real ESP32
../../target/debug/sensing-server --source esp32 --tick-ms 100 --ui-path ../../ui --http-port 3000
Open http://localhost:3000/ui/index.html
With Python HTTP server (legacy)
# Start FastAPI backend on port 8000
wifi-densepose start
# Serve the UI on port 3000
cd ui/
python -m http.server 3000
Pose Estimation Modes
| Mode | Badge | Requirements | Accuracy |
|---|---|---|---|
| Signal-Derived | Green | 1+ ESP32, no model needed | Presence, breathing, gross motion |
| Model Inference | Blue | 4+ ESP32s + trained .rvf model |
Full 17-keypoint COCO pose |
To use model inference, start the server with a trained model:
sensing-server --source esp32 --model path/to/model.rvf --ui-path ./ui
Configuration
API Configuration
Edit config/api.config.js:
export const API_CONFIG = {
BASE_URL: window.location.origin,
API_VERSION: '/api/v1',
WS_CONFIG: {
RECONNECT_DELAY: 5000,
MAX_RECONNECT_ATTEMPTS: 20,
PING_INTERVAL: 30000
}
};
Testing
Open tests/test-runner.html to run the test suite:
cd ui/
python -m http.server 3000
# Open http://localhost:3000/tests/test-runner.html
Test categories: API configuration, API service, WebSocket, pose service, health service, UI components, integration.
Styling
Uses a CSS design system with custom properties, dark/light mode, responsive layout, and component-based styling. Key variables in :root of style.css.
License
Part of the WiFi-DensePose system. See the main project LICENSE file.