fix(presence): derive the empty-room boundary from the reference quiet floor - #1917
Open
jingilibili wants to merge 1 commit into
Open
fix(presence): derive the empty-room boundary from the reference quiet floor#1917jingilibili wants to merge 1 commit into
jingilibili wants to merge 1 commit into
Conversation
…t floor Calibration finalization stores p95(calibration window residuals) x 1.5 as the empty-room boundary. Any disturbance during the ten minute hold - a person, an animal, a door, an appliance, motion in an adjacent room - lands in that upper tail, and the boundary then sits far above the settled empty level. MEASURED on a three node ESP32-S3 rig (192 subcarriers, channel 11): calibration 1 reference median 6.7, p95 15.86, stored boundary 23.79 settled empty room minutes later 3.70 - 5.50 person sitting still on the floor 3.25 - 35.03 (median 14.4) The occupant stayed inside the learned boundary, person_count remained 0 for the whole still phase, and the publication gate - which requires exactly one occupant - could not open even though the detectors kept producing estimates. Boundary sweep over the recorded labelled windows, with no false positive in the recorded empty window (3.70-5.50, 70 s): 6.0 -> 98%, 7.5 -> 93%, 9.0 -> 87%, 10.05 -> 81%, 15.61 -> 38%, 23.79 -> 3% Changes: - EmptyRoomReferenceStats derives p25/p50/p75/p95 and 1.4826 x MAD from the retained reference windows. - effective_empty_room_threshold() applies the tighter of the learned boundary and p25 x EMPTY_ROOM_RESIDUAL_MARGIN. The lower quartile estimates the quiet floor of the room and is not moved by a still occupant or a transient during calibration. It can only tighten the learned suppression range, never widen it. - field_bridge::perturbation_occupancy uses the same effective boundary as empty_room_match, so the occupancy count and the empty-room match cannot disagree. Tests: cargo test -p wifi-densepose-signal --lib ruvsense::field_model (36 tests) including disturbed_calibration_reference_tightens_the_effective_boundary and quiet_calibration_reference_is_not_flagged_contaminated.
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.
Symptom
A three node ESP32-S3 rig (192 subcarriers, channel 11) reported zero
occupants for a whole still phase while a person sat motionless on the floor,
so
person_countstayed 0 and the publication gate, which requires exactly oneoccupant, never opened. The vitals detectors kept producing estimates the whole
time; they were simply never allowed out.
Root cause
finalize_calibrationstoresp95(calibration window residuals) * 1.5as theempty-room boundary. Any disturbance during the ten minute hold - a person, an
animal, a door, an appliance, motion in an adjacent room - lands in that upper
tail, and the boundary then sits far above the settled empty level.
MEASURED on that rig:
The occupant stayed inside the learned boundary for the entire still phase.
The same inflated boundary also feeds
field_bridge::perturbation_occupancy, sothe count path and the empty-room match were wrong together.
Boundary sweep over the recorded labelled windows
Detection of the still occupant, with no false positive in the recorded empty
window (3.70-5.50, 70 s):
Change
EmptyRoomReferenceStatsderives p25/p50/p75/p95 and1.4826 * MADfrom theretained reference windows.
effective_empty_room_threshold()applies the tighter of the learned boundaryand
p25 * EMPTY_ROOM_RESIDUAL_MARGIN. The lower quartile estimates the quietfloor of the room and is not moved by a still occupant or by a transient
during calibration. It can only tighten the learned suppression range, never
widen it, so a quiet calibration keeps exactly the boundary it had.
field_bridge::perturbation_occupancyuses the same effective boundary asempty_room_match, so the occupancy count and the empty-room match cannotdisagree.
empty_room_matchnow also reports the stored boundary, the reference p50 androbust scale, and a contamination flag, so a disturbed calibration is visible
instead of being inferred from an invisible occupant.
Tests
Limits, stated plainly
means no crossing in that window, not a measured false-alarm rate over a long
empty period. A longer verified-empty capture is still needed.
reference median (6.7) sat above the settled empty level measured minutes
later (3.70-5.50). A boundary learned once is therefore a weak detector on
this rig, and a tracked quiet floor is the next step.
failure (a calibrated model still reporting presence in an empty home), which
is the same boundary-versus-settled-floor question from the other side.