fix(sensing): live-CSI presence/motion tuning for display-less S3 nodes - #1717
Open
davidwajch wants to merge 1 commit into
Open
fix(sensing): live-CSI presence/motion tuning for display-less S3 nodes#1717davidwajch wants to merge 1 commit into
davidwajch wants to merge 1 commit into
Conversation
Field-tuning the WiFi-CSI sensing pipeline against two ESP32-S3-DevKitC-1 nodes so a single occupant reads cleanly instead of as phantom "teleporting" detections. Changes span firmware and the sensing server. Firmware (esp32-csi-node): - sdkconfig.defaults: set CONFIG_DISPLAY_ENABLE=n. On display-less DevKitC-1 boards the boot panel probe false-positives (no TCA9554 -> "assume direct wiring"), leaving has_display=true so csi_collector_enable_data_capture() (the MGMT->MGMT+DATA promiscuous upgrade) is never applied and CSI yield collapses to 0 pps. Disabling the display fixes yield (0 -> ~40 pps) and drops LVGL from the build. - csi_collector.c: lower the self-ping CSI traffic source from 50 Hz to 10 Hz. The 50 Hz flood dominated the channel and raised the empty-room CSI noise floor to the magnitude of a moving occupant, destroying presence SNR; 10 Hz still exceeds the Nyquist rate for human motion/breathing while cutting the self-induced RF churn ~5x (empty-room variance floor ~175 -> ~90). Sensing server (wifi-densepose-sensing-server): - csi.rs: the `variance` feature returned intra_variance.max(temporal_variance), i.e. the spatial spread across subcarriers (~constant whether empty or occupied), masking the motion signal. Publish temporal variance instead, and redefine motion_band_power as the frame-to-frame amplitude delta (a real temporal motion metric) rather than a spatial spread of the upper subcarriers. - main.rs (attach_field_positions): add an adaptive empty-room presence gate. Per-node quiet baselines with asymmetric tracking (fast-down to find the floor and recover from a bad seed, slow-up so a moving occupant is not absorbed); occupancy is the BEST ratio across nodes so a well-placed crossing node is not diluted by a noisy near-router one; hysteresis holds "occupied" through the gaps between movements. When unoccupied the skeleton is dropped (no phantom) and estimated_persons is pinned to 1 when occupied. Also EMA-smooth the primary occupant's field-peak position to stop the frame-to-frame "teleport", and clamp the rendered skeleton count to the calibrated person count at the single publish choke point. Known limitation: at boards-next-to-router geometry the occupant signal is comparable to ambient RF noise; reliable detection needs the boards placed so the router link crosses the room with the person in the middle. Co-Authored-By: claude-flow <ruv@ruv.net>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Field-tuning the WiFi-CSI sensing pipeline against two ESP32-S3-DevKitC-1 nodes so a single occupant reads cleanly instead of as phantom "teleporting" detections. Changes span firmware and the sensing server, developed and validated live against real hardware in this session.
Firmware (
esp32-csi-node)sdkconfig.defaults:CONFIG_DISPLAY_ENABLE=n. On display-less DevKitC-1 boards the boot panel probe false-positives (no TCA9554 → "assume direct wiring"), leavinghas_display=truesocsi_collector_enable_data_capture()(the MGMT→MGMT+DATA promiscuous upgrade) is never applied and CSI yield collapses to 0 pps. Disabling the display fixes yield (0 → ~40 pps) and drops LVGL from the build.csi_collector.c: self-ping lowered 50 Hz → 10 Hz. The 50 Hz flood dominated the channel and raised the empty-room CSI noise floor to the magnitude of a moving occupant, destroying presence SNR. 10 Hz still exceeds the Nyquist rate for human motion/breathing while cutting self-induced RF churn ~5x (empty variance floor ~175 → ~90).Sensing server (
wifi-densepose-sensing-server)csi.rs: fix spatial-vs-temporal feature bug.variancereturnedintra_variance.max(temporal_variance)— the spatial spread across subcarriers (~constant whether empty or occupied), masking motion. Now publishes the temporal variance, and redefinesmotion_band_poweras the frame-to-frame amplitude delta (a real temporal motion metric).main.rs(attach_field_positions): adaptive empty-room presence gate. Per-node quiet baselines with asymmetric tracking (fast-down to find the floor / recover from a bad seed, slow-up so a moving occupant is not absorbed); occupancy = best ratio across nodes so a well-placed crossing node is not diluted by a noisy near-router one; hysteresis holds "occupied" through gaps between movements. Unoccupied → skeleton dropped (no phantom); occupied →estimated_personspinned to 1. Also EMA-smooths the primary occupant's field-peak position to stop frame-to-frame "teleport", and clamps rendered skeleton count to the calibrated person count at the single publish choke point.Known limitation
At boards-next-to-router geometry the occupant signal is comparable to ambient RF noise; reliable detection needs the boards placed so the router link crosses the room with the person in the middle.
🤖 Generated with claude-flow