feat(sensing-server): adaptive person count — RollingP95 + dedup_factor runtime API#491
Open
schwarztim wants to merge 1 commit intoruvnet:mainfrom
Open
feat(sensing-server): adaptive person count — RollingP95 + dedup_factor runtime API#491schwarztim wants to merge 1 commit intoruvnet:mainfrom
schwarztim wants to merge 1 commit intoruvnet:mainfrom
Conversation
…or runtime API
RollingP95 adaptive normalizer (ADR-044 §5.2):
- Streaming P95 estimator (600-sample / ~30 s window) replaces fixed-scale
denominators (variance/300, motion/250, spectral/500) that saturated against
live ESP32 values, collapsing dynamic range to zero.
- Cold-start (<60 samples) falls back to legacy denominators — day-0 behaviour
is preserved.
- Three new fields on AppStateInner: p95_variance, p95_motion_band_power,
p95_spectral_power (all RollingP95::new(600, 60)).
- compute_person_score() refactored to accept &AppStateInner; all three call
sites (wifi, wifi-fallback, simulated) updated.
- 5 unit tests in rolling_p95_tests module.
dedup_factor runtime API (ADR-044 §5.3):
- New field dedup_factor: f64 (default 3.0) on AppStateInner.
- fuse_or_fallback() gains dedup_factor param; fallback switches from max() to
sum/dedup_factor (ceiling), matching the fork's sum-based aggregation.
- RuntimeConfig struct + load/save_runtime_config() for data/config.json
persistence across restarts.
- Three new REST endpoints:
GET /api/v1/config/dedup-factor
POST /api/v1/config/dedup-factor
POST /api/v1/config/ground-truth (auto-tune from known person count)
Explicitly NOT included:
- lambda=5.0 (upstream keeps its 0.1 default — deployment-specific tuning)
- CC intensity threshold 0.3 and min-cluster-size 4 hardcodes
- max_cc_size filter removal
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.
Motivation
Person counting in
v2/uses fixed-scale feature normalization which works well in calibrated environments but degrades when signal characteristics drift across rooms, interference levels, or hardware. Two improvements here are deployment-neutral:1.
RollingP95adaptive normalizercompute_person_score()previously normalized features with hard-coded denominators (variance/300,motion_band_power/250,spectral_power/500). When live ESP32 values exceed those limits the normalized inputs clamp to 1.0 and dynamic range collapses.RollingP95is a streaming P95 estimator (600-sample / ~30 s sliding window) that self-calibrates to whatever feature distribution the deployment produces. Cold-start (< 60 samples) falls back to the legacy denominators so day-0 behaviour is fully preserved.2.
dedup_factorruntime APIExposes the multi-node cluster deduplication divisor via REST so deployments can tune to their environment without rebuilding. Includes an auto-tune endpoint that derives the optimal
dedup_factorfrom a known person count (calibration mode). Config persists across restarts indata/config.json.Explicitly NOT included
This fork also has additional ISTA
lambdatuning (specificallylambda=5.0) for its local 8×8×4 babycube grid. Those values are deployment-specific and intentionally not included in this PR — they would degrade person-count quality on different room geometries. This PR keeps upstream's existinglambda: 0.1default.Changes
v2/crates/wifi-densepose-sensing-server/src/main.rsRollingP95struct +impl(ADR-044 §5.2)RuntimeConfigstruct +load_runtime_config/save_runtime_config(ADR-044 §5.3)AppStateInner: addedp95_variance,p95_motion_band_power,p95_spectral_power,dedup_factor,data_dirfieldscompute_person_score()signature:&FeatureInfo→&AppStateInner + &FeatureInfo(adaptive denominators)config_get_dedup_factor,config_set_dedup_factor,config_set_ground_truthGET/POST /api/v1/config/dedup-factor,POST /api/v1/config/ground-truthrolling_p95_testsmodulev2/crates/wifi-densepose-sensing-server/src/multistatic_bridge.rsfuse_or_fallback()gainsdedup_factor: f64parameter; fallback switches frommax()toceil(sum / dedup_factor)Test results
cargo test --workspace --no-default-features: 1636 passed, 0 failed (includes 5 newRollingP95unit tests)python archive/v1/data/proof/verify.py: VERDICT: FAIL — pre-existing onorigin/main(numpy/scipy version drift); not caused by this PRNotes
dedup_factorto match observed cluster count. Useful for calibration during install.RollingP95is a generic primitive — could be reused for other adaptive thresholds in future.lambda: 0.1intomography.rsis untouched.