All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Firmware release cutting ADR-081 and the Timer Svc stack fix discovered during
on-hardware validation. Cut from main at commit pointing to this entry.
Tested on ESP32-S3 (QFN56 rev v0.2, MAC 3c:0f:02:e9:b5:f8), 30 s continuous
run: no crashes, 149 rv_feature_state_t emissions (~5 Hz), medium/slow ticks
firing cleanly, HEALTH mesh packets sent.
- Firmware: Timer Svc stack overflow on ADR-081 fast loop —
emit_feature_state()runs inside the FreeRTOS Timer Svc task via the fast-loop callback; it callsstream_sendernetwork I/O which pushes past the ESP-IDF 2 KiB default timer stack and panics ~1 s after boot. BumpedCONFIG_FREERTOS_TIMER_TASK_STACK_DEPTHto 8 KiB insdkconfig.defaults,sdkconfig.defaults.template, andsdkconfig.defaults.4mb. Follow-up (tracked separately): move heavy work out of the timer daemon into a dedicated worker task. - Firmware:
adaptive_controller.cimplicit declaration (#404) —fast_loop_cbcalledemit_feature_state()before its static definition, triggering-Werror=implicit-function-declaration. Added a forward declaration above the first use.
- CI: firmware build matrix (8MB + 4MB) —
firmware-ci.ymlnow matrix-builds both the default 8MB (sdkconfig.defaults) and 4MB SuperMini (sdkconfig.defaults.4mb) variants, uploading distinct artifacts and producing variant-named release binaries (esp32-csi-node.bin/esp32-csi-node-4mb.bin,partition-table.bin/partition-table-4mb.bin).
- ADR-081: Adaptive CSI Mesh Firmware Kernel — New 5-layer architecture
(Radio Abstraction Layer / Adaptive Controller / Mesh Sensing Plane /
On-device Feature Extraction / Rust handoff) that reframes the existing
ESP32 firmware modules as components of a chipset-agnostic kernel. ADR
in
docs/adr/ADR-081-adaptive-csi-mesh-firmware-kernel.md. Goal: swap one radio family for another without changing the Rust signal / ruvector / train / mat crates. - Firmware: radio abstraction vtable (
rv_radio_ops_t) — Newfirmware/esp32-csi-node/main/rv_radio_ops.{h}defines the chipset-agnostic ops (init, set_channel, set_mode, set_csi_enabled, set_capture_profile, get_health), profile enum (RV_PROFILE_PASSIVE_LOW_RATE/ACTIVE_PROBE/RESP_HIGH_SENS/FAST_MOTION/CALIBRATION), and health snapshot struct.rv_radio_ops_esp32.cprovides the ESP32 binding wrappingcsi_collector+esp_wifi_*. A second binding (mock or alternate chipset) is the portability acceptance test for ADR-081. - Firmware:
rv_feature_state_tpacket (magic0xC5110006) — New 60-byte compact per-node sensing state (packed, verified by_Static_assert) infirmware/esp32-csi-node/main/rv_feature_state.h: motion, presence, respiration BPM/conf, heartbeat BPM/conf, anomaly score, env-shift score, node coherence, quality flags, IEEE CRC32. Replaces raw ADR-018 CSI as the default upstream stream (~99.7% bandwidth reduction: 300 B/s at 5 Hz vs. ~100 KB/s raw). - Firmware: mock radio ops binding for QEMU — New
firmware/esp32-csi-node/main/rv_radio_ops_mock.c, compiled only whenCONFIG_CSI_MOCK_ENABLED. Satisfies ADR-081's portability acceptance test: a secondrv_radio_ops_tbinding compiles and runs against the same controller + mesh-plane code as the ESP32 binding. - Firmware: feature-state emitter wired into controller fast loop —
adaptive_controller.cnow emits one 60-byterv_feature_state_tper fast tick (default 200 ms → 5 Hz), pulling from the latest edge vitals and controller observation. This is the first end-to-end Layer 4/5 path for ADR-081. - Firmware:
csi_collector_get_pkt_yield_per_sec()/_get_send_fail_count()accessors — Expose the CSI callback rate and UDP send-failure counter so the ESP32 radio ops binding can populaterv_radio_health_t.pkt_yield_per_secand.send_fail_count, closing the adaptive controller's observation loop. - Firmware: host-side unit test suite for ADR-081 pure logic — New
firmware/esp32-csi-node/tests/host/(Makefile + 2 test files + shimesp_err.h). Exercisesadaptive_controller_decide()(9 test cases: degraded gate on pkt-yield collapse + coherence loss, anomaly > motion, motion → SENSE_ACTIVE, aggressive cadence, stable presence → RESP_HIGH_SENS, empty-room default, hysteresis, NULL safety) andrv_feature_state_*helpers (size assertion, IEEE CRC32 known vectors, determinism, receiver-side verification). 33/33 assertions pass. Benchmarks: decide() 3.2 ns/call, CRC32(56 B) 614 ns/pkt (87 MB/s), full finalize() 616 ns/call. Pure functionadaptive_controller_decide()extracted toadaptive_controller_decide.cso the firmware build and the host tests share a single source-of-truth implementation. - Scripts:
validate_qemu_output.pyADR-081 checks — Validator (invoked by ADR-061scripts/qemu-esp32s3-test.shin CI) gains three checks for adaptive controller boot line, mock radio ops registration, and slow-loop heartbeat, so QEMU runs regression-gate Layer 1/2 presence. - Firmware: ADR-081 Layer 3 mesh sensing plane — New
firmware/esp32-csi-node/main/rv_mesh.{h,c}defines 4 node roles (Anchor / Observer / Fusion relay / Coordinator), 7 on-wire message types (TIME_SYNC, ROLE_ASSIGN, CHANNEL_PLAN, CALIBRATION_START, FEATURE_DELTA, HEALTH, ANOMALY_ALERT), 3 authorization classes (None / HMAC-SHA256-session / Ed25519-batch),rv_node_status_t(28 B),rv_anomaly_alert_t(28 B),rv_time_sync_t,rv_role_assign_t,rv_channel_plan_t,rv_calibration_start_t. Pure-C encoder/decoder (rv_mesh_encode()/rv_mesh_decode()) with 16-byte envelope + payload + IEEE CRC32 trailer; convenience encoders for each message type. Controller now emitsHEALTHevery slow-loop tick (30 s default) andANOMALY_ALERTon state transitions to ALERT or DEGRADED. Host tests:test_rv_meshexercises 27 assertions covering roundtrip, bad magic, truncation, CRC flipping, oversize payload rejection, and encode+decode throughput (1.0 μs/roundtrip on host). - Rust: ADR-081 Layer 1/3 mirror module — New
crates/wifi-densepose-hardware/src/radio_ops.rsmirrors the firmware-siderv_radio_ops_tvtable as the RustRadioOpstrait (init, set_channel, set_mode, set_csi_enabled, set_capture_profile, get_health) and providesMockRadiofor offline testing. Also mirrors therv_mesh.htypes (MeshHeader,NodeStatus,AnomalyAlert,MeshRole,MeshMsgType,AuthClass) and ships byte-identicalcrc32_ieee(),decode_mesh(),decode_node_status(),decode_anomaly_alert(), andencode_health(). Exported fromlib.rs. 8 unit tests pass;crc32_matches_firmware_vectorsverifies parity with the firmware-side test vectors (0xCBF43926for"123456789",0xD202EF8Dfor single-byte zero), andmesh_constants_match_firmwareassertsMESH_MAGIC,MESH_VERSION,MESH_HEADER_SIZE, andMESH_MAX_PAYLOADmatchrv_mesh.hbyte-for-byte. Satisfies ADR-081's portability acceptance test: signal/ruvector/train/mat crates are untouched. - Firmware: adaptive controller — New
firmware/esp32-csi-node/main/adaptive_controller.{c,h}implements the three-loop closed-loop control specified by ADR-081: fast (~200 ms) for cadence and active probing, medium (~1 s) for channel selection and role transitions, slow (~30 s) for baseline recalibration. Pureadaptive_controller_decide()policy function is exposed in the header for offline unit testing. Default policy is conservative (enable_channel_switchandenable_role_changeoff); Kconfig surface added under "Adaptive Controller (ADR-081)".
provision.pyesptool v5 compat (#391) — Stalewrite_flash(underscore) syntax in the dry-run manual-flash hint now useswrite-flash(hyphenated) for esptool >= 5.x. The primary flash command was already correct.provision.pysilent NVS wipe (#391) — The script replaces the entirecsi_cfgNVS namespace on every run, so partial invocations were silently erasing WiFi credentials and causingRetrying WiFi connection (10/10)in the field. Now refuses to run without--ssid,--password, and--target-ipunless--force-partialis passed.--force-partialprints a warning listing which keys will be wiped.- Firmware: defensive
node_idcapture (#232, #375, #385, #386, #390) — Users on multi-node deployments reportednode_idreverting to the Kconfig default (1) in UDP frames and in thecsi_collectorinit log, despite NVS loading the correct value. The root cause (memory corruption ofg_nvs_config) has not been definitively isolated, but the UDP frame header is now tamper-proof:csi_collector_init()capturesg_nvs_config.node_idinto a module-locals_node_idonce, andcsi_serialize_frame()plus all other consumers (edge_processing.c,wasm_runtime.c,display_ui.c,swarm_bridge_init) read it via the newcsi_collector_get_node_id()accessor. A canary logsWARNifg_nvs_config.node_iddiverges froms_node_idat end-of-init, helping isolate the upstream corruption path. Validated on attached ESP32-S3 (COM8): NVSnode_id=2propagates through boot log, capture log, init log, and byte[4] of every UDP frame.
- CHANGELOG catch-up (#367) — Added missing entries for v0.5.5, v0.6.0, and v0.7.0 releases.
Model release (no new firmware binary). Firmware remains at v0.6.0-esp32.
- Camera ground-truth training pipeline (ADR-079) — End-to-end supervised WiFlow pose training using MediaPipe + real ESP32 CSI.
scripts/collect-ground-truth.py— MediaPipe PoseLandmarker webcam capture (17 COCO keypoints, 30fps), synchronized with CSI recording over nanosecond timestamps.scripts/align-ground-truth.js— Time-aligns camera keypoints with 20-frame CSI windows by binary search, confidence-weighted averaging.scripts/train-wiflow-supervised.js— 3-phase curriculum training (contrastive → supervised SmoothL1 → bone/temporal refinement) with 4 scale presets (lite/small/medium/full).scripts/eval-wiflow.js— PCK@10/20/50, MPJPE, per-joint breakdown, baseline proxy mode.scripts/record-csi-udp.py— Lightweight ESP32 CSI UDP recorder (no Rust build required).
- ruvector optimizations (O6-O10) — Subcarrier selection (70→35, 50% reduction), attention-weighted subcarriers, Stoer-Wagner min-cut person separation, multi-SPSA gradient estimation, Mac M4 Pro training via Tailscale.
- Scalable WiFlow presets —
lite(189K params, ~19 min) throughfull(7.7M params, ~8 hrs) to match dataset size. - Pre-trained WiFlow v1 model — 92.9% PCK@20, 974 KB, 186,946 params. Published to HuggingFace under
wiflow-v1/.
- 92.9% PCK@20 pose accuracy from a 5-minute data collection session with one $9 ESP32-S3 and one laptop webcam.
- Training pipeline validated on real paired data: 345 samples, 19 min training, eval loss 0.082, bone constraint 0.008.
- Pre-trained CSI sensing weights published — First official pre-trained models on HuggingFace.
model.safetensors(48 KB),model-q4.bin(8 KB 4-bit),model-q2.bin(4 KB),presence-head.json, per-node LoRA adapters. - 17 sensing applications — Sleep monitor, apnea detector, stress monitor, gait analyzer, RF tomography, passive radar, material classifier, through-wall detector, device fingerprint, and more. Each as a standalone
scripts/*.js. - ADRs 069-078 — 10 new architecture decisions covering Cognitum Seed integration, self-supervised pretraining, ruvllm pipeline, WiFlow architecture, channel hopping, SNN, MinCut person separation, CNN spectrograms, novel RF applications, multi-frequency mesh.
- Kalman tracker (PR #341 by @taylorjdawson) — temporal smoothing of pose keypoints.
- Security fix merged via PR #310.
- Presence detection: 100% accuracy on 60,630 overnight samples.
- Inference: 0.008 ms per sample, 164K embeddings/sec.
- Contrastive self-supervised training: 51.6% improvement over baseline.
- WiFlow SOTA architecture (ADR-072) — TCN + axial attention pose decoder, 1.8M params, 881 KB at 4-bit. 17 COCO keypoints from CSI amplitude only (no phase).
- Multi-frequency mesh scanning (ADR-073) — ESP32 nodes hop across channels 1/3/5/6/9/11 at 200ms dwell. Neighbor WiFi networks used as passive radar illuminators. Null subcarriers reduced from 19% to 16%.
- Spiking neural network (ADR-074) — STDP online learning, adapts to new rooms in <30s with no labels, 16-160x less compute than batch training.
- MinCut person counting (ADR-075) — Stoer-Wagner min-cut on subcarrier correlation graph. Fixes #348 (was always reporting 4 people).
- CNN spectrogram embeddings (ADR-076) — Treat 64×20 CSI as an image, produce 128-dim environment fingerprints (0.95+ same-room similarity).
- Graph transformer fusion — Multi-node CSI fusion via GATv2 attention (replaces naive averaging).
- Camera-free pose training pipeline — Trains 17-keypoint model from 10 sensor signals with no camera required.
- #348 person counting — MinCut correctly counts 1-4 people (24/24 validation windows).
- ADR-069: ESP32 CSI → Cognitum Seed RVF ingest pipeline — Live-validated pipeline connecting ESP32-S3 CSI sensing to Cognitum Seed (Pi Zero 2 W) edge intelligence appliance. 339 vectors ingested, 100% kNN validation, SHA-256 witness chain verified.
- Feature vector packet (magic 0xC5110003) — New 48-byte packet with 8 normalized dimensions (presence, motion, breathing, heart rate, phase variance, person count, fall, RSSI) sent at 1 Hz alongside vitals.
scripts/seed_csi_bridge.py— Python bridge: UDP listener → HTTPS ingest with bearer token auth,--validate(kNN + PIR ground truth),--stats,--compactmodes, hash-based vector IDs, NaN/inf rejection, source IP filtering, retry logic.- Arena Physica research — 26 research documents in
docs/research/covering Maxwell's equations in WiFi sensing, Arena Physica Studio analysis, SOTA WiFi sensing 2025-2026, GOAP implementation plan for ESP32 + Pi Zero. - Cognitum Seed MCP integration — 114-tool MCP proxy enables AI assistants to query sensing state, vectors, witness chain, and device status directly.
- Compressed frame magic collision — Reassigned compressed frame magic from
0xC5110003to0xC5110005to free0xC5110003for feature vectors. - Uninitialized
s_top_k[0]read — Guarded variance computation againsts_top_k_count == 0insend_feature_vector(). - Presence score normalization — Bridge now divides by 15.0 instead of clamping, preserving dynamic range for raw values 1.41-14.92.
- Stale magic references — Updated ADR-039, DDD model to reflect
0xC5110005for compressed frames.
- Credential exposure remediation — Removed hardcoded WiFi passwords and bearer tokens from source files. Added NVS binary/CSV patterns to
.gitignore. Environment variable fallback for bearer token. - NaN/Inf injection prevention — Bridge validates all feature dimensions are finite before Seed ingest.
- UDP source filtering —
--allowed-sourcesargument restricts packet acceptance to known ESP32 IPs.
- Wire format table now includes 6 magic numbers:
0xC5110001(raw),0xC5110002(vitals),0xC5110003(features),0xC5110004(WASM events),0xC5110005(compressed),0xC5110006(fused vitals).
- Cross-node RSSI-weighted feature fusion — Multiple ESP32 nodes fuse CSI features using RSSI-based weighting. Closer node gets higher weight. Reduces variance noise by 29%, keypoint jitter by 72%.
- DynamicMinCut person separation — Uses
ruvector_mincut::DynamicMinCuton the subcarrier temporal correlation graph to detect independent motion clusters. Replaces variance-based heuristic for multi-person counting. - RSSI-based position tracking — Skeleton position driven by RSSI differential between nodes. Walk between ESP32s and the skeleton follows you.
- Per-node state pipeline (ADR-068) — Each ESP32 node gets independent
HashMap<u8, NodeState>with frame history, classification, vitals, and person count. Fixes #249 (the #1 user-reported issue). - RuVector Phase 1-3 integration — Subcarrier importance weighting, temporal keypoint smoothing (EMA), coherence gating, skeleton kinematic constraints (Jakobsen relaxation), compressed pose history.
- Client-side lerp smoothing — UI keypoints interpolate between frames (alpha=0.15) for fluid skeleton movement.
- Multi-node mesh tests — 8 integration tests covering 1-255 node configurations.
wifi_denseposePython package —from wifi_densepose import WiFiDensePosenow works (#314).
- Watchdog crash on busy LANs (#321) — Batch-limited edge_dsp to 4 frames before 20ms yield. Fixed idle-path busy-spin (
pdMS_TO_TICKS(5)==0). - No detection from edge vitals (#323) — Server now generates
sensing_updatefrom Tier 2+ vitals packets. - RSSI byte offset mismatch (#332) — Server parsed RSSI from wrong byte (was reading sequence counter).
- Stack overflow risk — Moved 4KB of BPM scratch buffers from stack to static storage.
- Stale node memory leak —
node_statesHashMap evicts nodes inactive >60s. - Unsafe raw pointer removed — Replaced with safe
.clone()for adaptive model borrow. - Firmware CI — Upgraded to IDF v5.4, replaced
xxdwithod(#327). - Person count double-counting — Multi-node aggregation changed from
sumtomax. - Skeleton jitter — Removed tick-based noise, dampened procedural animation, recalibrated feature scaling for real ESP32 data.
- Motion-responsive skeleton: arm swing (0-80px) driven by CSI variance, leg kick (0-50px) by motion_band_power, vertical bob when walking.
- Person count thresholds recalibrated for real ESP32 hardware (1→2 at 0.70, EMA alpha 0.04).
- Vital sign filtering: larger median window (31), faster EMA (0.05), looser HR jump filter (15 BPM).
- Vendored ruvector updated to v2.1.0-40 (316 commits ahead).
| Metric | Baseline | v0.5.3 | Improvement |
|---|---|---|---|
| Variance noise | 109.4 | 77.6 | -29% |
| Feature stability | std=154.1 | std=105.4 | -32% |
| Keypoint jitter | std=4.5px | std=1.3px | -72% |
| Confidence | 0.643 | 0.686 | +7% |
| Presence accuracy | 93.4% | 94.6% | +1.3pp |
- Real hardware: COM6 (node 1) + COM9 (node 2) on ruv.net WiFi
- All 284 Rust tests pass, 352 signal crate tests pass
- Firmware builds clean at 843 KB
- QEMU CI: 11/11 jobs green
- RSSI byte offset in frame parser (#332)
- Per-node state pipeline for multi-node sensing (#249)
- Firmware CI upgraded to IDF v5.4 (#327)
- Watchdog crash on busy LANs (#321)
- No detection from edge vitals (#323)
wifi_denseposePython package import (#314)- Pre-compiled firmware binaries added to release
- 60 GHz mmWave sensor fusion (ADR-063) — Auto-detects Seeed MR60BHA2 (60 GHz, HR/BR/presence) and HLK-LD2410 (24 GHz, presence/distance) on UART at boot. Probes 115200 then 256000 baud, registers device capabilities, starts background parser.
- 48-byte fused vitals packet (magic
0xC5110004) — Kalman-style fusion: mmWave 80% + CSI 20% when both available. Automatic fallback to standard 32-byte CSI-only packet. - Server-side fusion bridge (
scripts/mmwave_fusion_bridge.py) — Reads two serial ports simultaneously for dual-sensor setups where mmWave runs on a separate ESP32. - Multimodal ambient intelligence roadmap (ADR-064) — 25+ applications from fall detection to sleep monitoring to RF tomography.
- Real hardware: ESP32-S3 (COM7) WiFi CSI + ESP32-C6/MR60BHA2 (COM4) 60 GHz mmWave running concurrently. HR=75 bpm, BR=25/min at 52 cm range. All 11 QEMU CI jobs green.
- Fall detection false positives (#263) — Default threshold raised from 2.0 to 15.0 rad/s²; normal walking (2-5 rad/s²) no longer triggers alerts. Added 3-consecutive-frame debounce and 5-second cooldown between alerts. Verified on real ESP32-S3 hardware: 0 false alerts in 60s / 1,300+ live WiFi CSI frames.
- Kconfig default mismatch —
CONFIG_EDGE_FALL_THRESHKconfig default was still 2000 (=2.0) whilenvs_config.cfallback was updated to 15.0. Fixed Kconfig to 15000. Caught by real hardware testing — mock data did not reproduce. - provision.py NVS generator API change —
esp_idf_nvs_partition_genpackage changed itsgenerate()signature; switched to subprocess-first invocation for cross-version compatibility. - QEMU CI pipeline (11 jobs) — Fixed all failures: fuzz test
esp_timerstubs, QEMUlibgcryptdependency, NVS matrix generator, IDF containerpippath, flash image padding, validation WARN handling, swarmip/cargomissing.
- 4MB flash support (#265) —
partitions_4mb.csvandsdkconfig.defaults.4mbfor ESP32-S3 boards with 4MB flash (e.g. SuperMini). Dual OTA slots, 1.856 MB each. Thanks to @sebbu for the community workaround that confirmed feasibility. --strictflag forvalidate_qemu_output.py— WARNs now pass by default in CI (no real WiFi in QEMU); use--strictto fail on warnings.
- QEMU ESP32-S3 testing platform (ADR-061) — 9-layer firmware testing without hardware
- Mock CSI generator with 10 physics-based scenarios (empty room, walking, fall, multi-person, etc.)
- Single-node QEMU runner with 16-check UART validation
- Multi-node TDM mesh simulation (TAP networking, 2-6 nodes)
- GDB remote debugging with VS Code integration
- Code coverage via gcov/lcov + apptrace
- Fuzz testing (3 libFuzzer targets + ASAN/UBSAN)
- NVS provisioning matrix (14 configs)
- Snapshot-based regression testing (sub-second VM restore)
- Chaos testing with fault injection + health monitoring
- QEMU Swarm Configurator (ADR-062) — YAML-driven multi-ESP32 test orchestration
- 4 topologies: star, mesh, line, ring
- 3 node roles: sensor, coordinator, gateway
- 9 swarm-level assertions (boot, crashes, TDM, frame rate, fall detection, etc.)
- 7 presets: smoke (2n/15s), standard (3n/60s), ci-matrix, large-mesh, line-relay, ring-fault, heterogeneous
- Health oracle with cross-node validation
- QEMU installer (
install-qemu.sh) — auto-detects OS, installs deps, builds Espressif QEMU fork - Unified QEMU CLI (
qemu-cli.sh) — single entry point for all 11 QEMU test commands - CI:
firmware-qemu.ymlworkflow with QEMU test matrix, fuzz testing, NVS validation, and swarm test jobs - User guide: QEMU testing and swarm configurator section with plain-language walkthrough
-
Firmware now boots in QEMU: WiFi/UDP/OTA/display guards for mock CSI mode
-
9 bugs in mock_csi.c (LFSR bias, MAC filter init, scenario loop, overflow burst timing)
-
23 bugs from ADR-061 deep review (inject_fault.py writes, CI cache, snapshot log corruption, etc.)
-
16 bugs from ADR-062 deep review (log filename mismatch, SLIRP port collision, heap false positives, etc.)
-
All scripts:
--helpflags, prerequisite checks with install hints, standardized exit codes -
Sensing server UI API completion (ADR-043) — 14 fully-functional REST endpoints for model management, CSI recording, and training control
- Model CRUD:
GET /api/v1/models,GET /api/v1/models/active,POST /api/v1/models/load,POST /api/v1/models/unload,DELETE /api/v1/models/:id,GET /api/v1/models/lora/profiles,POST /api/v1/models/lora/activate - CSI recording:
GET /api/v1/recording/list,POST /api/v1/recording/start,POST /api/v1/recording/stop,DELETE /api/v1/recording/:id - Training control:
GET /api/v1/train/status,POST /api/v1/train/start,POST /api/v1/train/stop - Recording writes CSI frames to
.jsonlfiles via tokio background task - Model/recording directories scanned at startup, state managed via
Arc<RwLock<AppStateInner>>
- Model CRUD:
-
ADR-044: Provisioning tool enhancements — 5-phase plan for complete NVS coverage (7 missing keys), JSON config files, mesh presets, read-back/verify, and auto-detect
-
25 real mobile tests replacing
it.todo()placeholders — 205 assertions covering components, services, stores, hooks, screens, and utils -
Project MERIDIAN (ADR-027) — Cross-environment domain generalization for WiFi pose estimation (1,858 lines, 72 tests)
HardwareNormalizer— Catmull-Rom cubic interpolation resamples any hardware CSI to canonical 56 subcarriers; z-score + phase sanitizationDomainFactorizer+GradientReversalLayer— adversarial disentanglement of pose-relevant vs environment-specific featuresGeometryEncoder+FilmLayer— Fourier positional encoding + DeepSets + FiLM for zero-shot deployment given AP positionsVirtualDomainAugmentor— synthetic environment diversity (room scale, wall material, scatterers, noise) for 4x training augmentationRapidAdaptation— 10-second unsupervised calibration via contrastive test-time training + LoRA adaptersCrossDomainEvaluator— 6-metric evaluation protocol (MPJPE in-domain/cross-domain/few-shot/cross-hardware, domain gap ratio, adaptation speedup)
-
ADR-027: Cross-Environment Domain Generalization — 10 SOTA citations (PerceptAlign, X-Fi ICLR 2025, AM-FM, DGSense, CVPR 2024)
-
Cross-platform RSSI adapters — macOS CoreWLAN (
MacosCoreWlanScanner) and Linuxiw(LinuxIwScanner) Rust adapters with#[cfg(target_os)]gating -
macOS CoreWLAN Python sensing adapter with Swift helper (
mac_wifi.swift) -
macOS synthetic BSSID generation (FNV-1a hash) for Sonoma 14.4+ BSSID redaction
-
Linux
iw dev <iface> scanparser with freq-to-channel conversion andscan dump(no-root) mode -
ADR-025: macOS CoreWLAN WiFi Sensing (ORCA)
- sendto ENOMEM crash (Issue #127) — CSI callbacks in promiscuous mode exhaust lwIP pbuf pool causing guru meditation crash. Fixed with 50 Hz rate limiter in
csi_collector.cand 100 ms ENOMEM backoff instream_sender.c. Hardware-verified on ESP32-S3 (200+ callbacks, zero crashes) - Provisioning script missing TDM/edge flags (Issue #130) — Added
--tdm-slot,--tdm-total,--edge-tier,--pres-thresh,--fall-thresh,--vital-win,--vital-int,--subk-counttoprovision.py - WebSocket "RECONNECTING" on Dashboard/Live Demo —
sensingService.start()now called on app init inapp.jsso WebSocket connects immediately instead of waiting for Sensing tab visit - Mobile WebSocket port —
ws.service.tsbuildWsUrl()uses same-origin port instead of hardcoded port 3001 - Mobile Jest config —
testPathIgnorePatternsno longer silently ignores the entire test directory - Removed synthetic byte counters from Python
MacosWifiCollector— now reportstx_bytes=0, rx_bytes=0instead of fake incrementing values
3.0.0 - 2026-03-01
Major release: AETHER contrastive embedding model, Docker Hub images, and comprehensive UI overhaul.
- Project AETHER — self-supervised contrastive learning for WiFi CSI fingerprinting, similarity search, and anomaly detection (
9bbe956) embedding.rsmodule:ProjectionHead,InfoNceLoss,CsiAugmenter,FingerprintIndex,PoseEncoder,EmbeddingExtractor(909 lines, zero external ML dependencies)- SimCLR-style pretraining with 5 physically-motivated augmentations (temporal jitter, subcarrier masking, Gaussian noise, phase rotation, amplitude scaling)
- CLI flags:
--pretrain,--pretrain-epochs,--embed,--build-index <type> - Four HNSW-compatible fingerprint index types:
env_fingerprint,activity_pattern,temporal_baseline,person_track - Cross-modal
PoseEncoderfor WiFi-to-camera embedding alignment - VICReg regularization for embedding collapse prevention
- 53K total parameters (55 KB at INT8) — fits on ESP32
- Published Docker Hub images:
ruvnet/wifi-densepose:latest(132 MB Rust) andruvnet/wifi-densepose:python(569 MB) (add9f19) - Multi-stage Dockerfile for Rust sensing server with RuVector crates
docker-compose.ymlorchestrating both Rust and Python services- RVF model export via
--export-rvfand load via--load-rvfCLI flags
- 33 use cases across 4 vertical tiers: Everyday, Specialized, Robotics & Industrial, Extreme (
0afd9c5) - "Why WiFi Wins" comparison table (WiFi vs camera vs LIDAR vs wearable vs PIR)
- Mermaid architecture diagrams: end-to-end pipeline, signal processing detail, deployment topology (
50f0fc9) - Models & Training section with RuVector crate links (GitHub + crates.io), SONA component table (
965a1cc) - RVF container section with deployment targets table (ESP32 0.7 MB to server 50+ MB)
- Collapsible README sections for improved navigation (
478d964,99ec980,0ebd6be) - Installation and Quick Start moved above Table of Contents (
50acbf7) - CSI hardware requirement notice (
528b394)
- UI auto-detects server port from page origin — no more hardcoded
localhost:8080; works on any port (Docker :3000, native :8080, custom) (3b72f35, closes #55) - Docker port mismatch — server now binds 3000/3001 inside container as documented (
44b9c30) - Added
/ws/sensingWebSocket route to the HTTP server so UI only needs one port - Fixed README API endpoint references:
/api/v1/health→/health,/api/v1/sensing→/api/v1/sensing/latest - Multi-person tracking limit corrected: configurable default 10, no hard software cap (
e2ce250)
2.0.0 - 2026-02-28
Major release: complete Rust sensing server, full DensePose training pipeline, RuVector v2.0.4 integration, ESP32-S3 firmware, and 6 security hardening patches.
- Full DensePose-compatible REST API served by Axum (
d956c30)GET /health— server healthGET /api/v1/sensing/latest— live CSI sensing dataGET /api/v1/vital-signs— breathing rate (6-30 BPM) and heartbeat (40-120 BPM)GET /api/v1/pose/current— 17 COCO keypoints derived from WiFi signal fieldGET /api/v1/info— server build and feature infoGET /api/v1/model/info— RVF model container metadataws://host/ws/sensing— real-time WebSocket stream
- Three data sources:
--source esp32(UDP CSI),--source windows(netsh RSSI),--source simulated(deterministic reference) - Auto-detection: server probes ESP32 UDP and Windows WiFi, falls back to simulated
- Three.js visualization UI with 3D body skeleton, signal heatmap, phase plot, Doppler bars, vital signs panel
- Static UI serving via
--ui-pathflag - Throughput: 9,520–11,665 frames/sec (release build)
VitalSignDetectorwith breathing (6-30 BPM) and heartbeat (40-120 BPM) extraction from CSI fluctuations (1192de9)- FFT-based spectral analysis with configurable band-pass filters
- Confidence scoring based on spectral peak prominence
- REST endpoint
/api/v1/vital-signswith real-time JSON output
wifi-densepose-traincrate with complete 8-phase pipeline (fc409df,ec98e40,fce1271)- Phase 1:
DataPipelinewith MM-Fi and Wi-Pose dataset loaders - Phase 2:
CsiToPoseTransformer— 4-head cross-attention + 2-layer GCN on COCO skeleton - Phase 3: 6-term composite loss (MSE, bone length, symmetry, joint angle, temporal, confidence)
- Phase 4:
DynamicPersonMatchervia ruvector-mincut (O(n^1.5 log n) Hungarian assignment) - Phase 5:
SonaAdapter— MicroLoRA rank-4 with EWC++ memory preservation - Phase 6:
SparseInference— progressive 3-layer model loading (A: essential, B: refinement, C: full) - Phase 7:
RvfContainer— single-file model packaging with segment-based binary format - Phase 8: End-to-end training with cosine-annealing LR, early stopping, checkpoint saving
- Phase 1:
- CLI:
--train,--dataset,--epochs,--save-rvf,--load-rvf,--export-rvf - Benchmark: ~11,665 fps inference, 229 tests passing
ruvector-mincut→DynamicPersonMatcherinmetrics.rs+ subcarrier selection (81ad09d,a7dd31c)ruvector-attn-mincut→ antenna attention inmodel.rs+ noise-gated spectrogramruvector-temporal-tensor→CompressedCsiBufferindataset.rs+ compressed breathing/heartbeatruvector-solver→ sparse subcarrier interpolation (114→56) + Fresnel triangulationruvector-attention→ spatial attention inmodel.rs+ attention-weighted BVP- Vendored all 11 RuVector crates under
vendor/ruvector/(d803bfe)
gate_spectrogram()— attention-gated noise suppression (18170d7)attention_weighted_bvp()— sensitivity-weighted velocity profilesmincut_subcarrier_partition()— dynamic sensitive/insensitive subcarrier splitsolve_fresnel_geometry()— TX-body-RX distance estimationCompressedBreathingBuffer+CompressedHeartbeatSpectrogramBreathingDetector+HeartbeatDetector(MAT crate, real FFT + micro-Doppler)- Feature-gated behind
cfg(feature = "ruvector")(ab2453e)
- ESP32-S3 firmware with FreeRTOS CSI extraction (
92a5182) - ADR-018 binary frame format:
[0xAD, 0x18, len_hi, len_lo, payload] - Rust
Esp32Aggregatorreceiving UDP frames on port 5005 bridge.rsconverting I/Q pairs to amplitude/phase vectors- NVS provisioning for WiFi credentials
- Pre-built binary quick start documentation (
696a726)
- 6 algorithms, 83 tests (
fcb93cc)- Hampel filter (median + MAD, resistant to 50% contamination)
- Conjugate multiplication (reference-antenna ratio, cancels common-mode noise)
- Phase sanitization (unwrap + linear detrend, removes CFO/SFO)
- Fresnel zone geometry (TX-body-RX distance from first-principles physics)
- Body Velocity Profile (micro-Doppler extraction, 5.7x speedup)
- Attention-gated spectrogram (learned noise suppression)
- MM-Fi and Wi-Pose dataset specifications with download links (
4babb32,5dc2f66) - Verified dataset dimensions, sampling rates, and annotation formats
- Cross-dataset evaluation protocol
- Multi-AP triangulation for through-wall survivor detection (
a17b630,6b20ff0) - Triage classification (breathing, heartbeat, motion)
- Domain events:
survivor_detected,survivor_updated,alert_created - WebSocket broadcast at
/ws/mat/stream
- Guided 7-step interactive installer with 8 hardware profiles (
8583f3e) - Comprehensive build guide for Linux, macOS, Windows, Docker, ESP32 (
45f8a0d) - 12 Architecture Decision Records (ADR-001 through ADR-012) (
337dd96)
- Sensing-only UI mode with Gaussian splat visualization (
b7e0f07) - Three.js 3D body model (17 joints, 16 limbs) with signal-viz components
- Tabs: Dashboard, Hardware, Live Demo, Sensing, Architecture, Performance, Applications
- WebSocket client with automatic reconnection and exponential backoff
- Complete Rust port of WiFi-DensePose with modular workspace (
6ed69a3)wifi-densepose-signal— CSI processing, phase sanitization, feature extractionwifi-densepose-core— shared types and configurationwifi-densepose-nn— neural network inference (DensePose head, RCNN)wifi-densepose-hardware— ESP32 aggregator, hardware interfaceswifi-densepose-config— configuration management
- Comprehensive benchmarks and validation tests (
3ccb301)
WindowsWifiCollector— RSSI collection vianetsh wlan show networksRssiFeatureExtractor— variance, spectral bands (motion 0.5-4 Hz, breathing 0.1-0.5 Hz), change pointsPresenceClassifier— rule-based 3-state classification (ABSENT / PRESENT_STILL / ACTIVE)- Cross-receiver agreement scoring for multi-AP confidence boosting
- WebSocket sensing server (
ws_server.py) broadcasting JSON at 2 Hz - Deterministic CSI proof bundles for reproducible verification (
v1/data/proof/) - Commodity sensing unit tests (
b391638)
- Rust hardware adapters now return explicit errors instead of silent empty data (
6e0e539)
- Review fixes for end-to-end training pipeline (
45f0304) - Dockerfile paths updated from
src/tov1/src/(7872987) - IoT profile installer instructions updated for aggregator CLI (
f460097) process.envreference removed from browser ES module (e320bc9)
- 5.7x Doppler extraction speedup via optimized FFT windowing (
32c75c8) - Single 2.1 MB static binary, zero Python dependencies for Rust server
- Fix SQL injection in status command and migrations (
f9d125d) - Fix XSS vulnerabilities in UI components (
5db55fd) - Fix command injection in statusline.cjs (
4cb01fd) - Fix path traversal vulnerabilities (
896c4fc) - Fix insecure WebSocket connections — enforce wss:// on non-localhost (
ac094d4) - Fix GitHub Actions shell injection (
ab2e7b4) - Fix 10 additional vulnerabilities, remove 12 dead code instances (
7afdad0)
1.1.0 - 2025-06-07
- Complete Python WiFi-DensePose system with CSI data extraction and router interface
- CSI processing and phase sanitization modules
- Batch processing for CSI data in
CSIProcessorandPhaseSanitizer - Hardware, pose, and stream services for WiFi-DensePose API
- Comprehensive CSS styles for UI components and dark mode support
- API and Deployment documentation
- Badge links for PyPI and Docker in README
- Async engine creation poolclass specification
1.0.0 - 2024-12-01
- Initial release of WiFi-DensePose
- Real-time WiFi-based human pose estimation using Channel State Information (CSI)
- DensePose neural network integration for body surface mapping
- RESTful API with comprehensive endpoint coverage
- WebSocket streaming for real-time pose data
- Multi-person tracking with configurable capacity (default 10, up to 50+)
- Fall detection and activity recognition
- Domain configurations: healthcare, fitness, smart home, security
- CLI interface for server management and configuration
- Hardware abstraction layer for multiple WiFi chipsets
- Phase sanitization and signal processing pipeline
- Authentication and rate limiting
- Background task management
- Cross-platform support (Linux, macOS, Windows)
- User guide and API reference
- Deployment and troubleshooting guides
- Hardware setup and calibration instructions
- Performance benchmarks
- Contributing guidelines