You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
WiFi-based activity classification using ESP32 Channel State Information (CSI) relies on hand-tuned thresholds to distinguish between activity states (absent, present_still, present_moving, active). These static thresholds are brittle — they don't account for:
Environment-specific signal patterns: Room geometry, furniture, wall materials, and ESP32 placement all affect how CSI signals respond to human activity.
Temporal noise characteristics: Real ESP32 CSI data at ~10 FPS has significant frame-to-frame jitter that causes classification to jump between states.
Vital signs estimation noise: Heart rate and breathing rate estimates from Goertzel filter banks produce large swings (50+ BPM frame-to-frame) at low confidence levels.
The existing threshold-based approach produces noisy, unstable classifications that degrade the user experience in the Observatory visualization and the main dashboard.
Decision
1. Three-Stage Signal Smoothing Pipeline
All CSI-derived metrics pass through a three-stage pipeline before reaching the UI:
Stage 1: Adaptive Baseline Subtraction
EMA with α=0.003 (~30s time constant) tracks the "quiet room" noise floor
Only updates during low-motion periods to avoid inflating baseline during activity
50-frame warm-up period for initial baseline learning
Subtracts 70% of baseline from raw motion score to remove environmental drift
Stage 2: EMA + Median Filtering
Motion score: Blended from 4 signals (temporal diff 40%, variance 20%, motion band power 25%, change points 15%), then EMA-smoothed with α=0.15
Vital signs: 21-frame sliding window → trimmed mean (drop top/bottom 25%) → EMA with α=0.02 (~5s time constant)
Dead-band: HR won't update unless trimmed mean differs by >2 BPM; BR needs >0.5 BPM
Outlier rejection: HR jumps >8 BPM/frame and BR jumps >2 BPM/frame are discarded
Stage 3: Hysteresis Debounce
Activity state transitions require 4 consecutive frames (~0.4s) of agreement before committing
Prevents rapid flickering between states
Independent candidate tracking resets on new direction changes