fix(edge): gate multi-person count on presence — no phantom persons (#803, #496)#892
fix(edge): gate multi-person count on presence — no phantom persons (#803, #496)#892markt-heximal wants to merge 1 commit into
Conversation
…phantom persons update_multi_person_vitals() marked top_k/2 persons active unconditionally every frame, so the reported n_persons was a fixed artifact of the subcarrier count (never 0) regardless of occupancy — an empty room reported e.g. 4 people. The firmware already computes s_presence_detected (earlier in the same process_frame pass, currently used only for a packet flag); gate person activation on it so an empty room reports 0 persons. Addresses ruvnet#803 and ruvnet#496. Scope: bounds the count to presence; true multi-person separation is out of scope.
|
Independently verified — this fix is correct, and the call ordering it relies on checks out against current
Before this, Worth noting this is the edge/firmware half of the over-count. The server heuristic path has a complementary cap on LGTM to merge. (Happy to run an ESP-IDF build to confirm it compiles if that's useful before merge — it only touches existing symbols, so it should be clean.) |
Addresses #803 and #496.
Problem
update_multi_person_vitals()(edge_processing.c) setspv->active = trueunconditionally forn_persons = s_top_k_count / 2(= 4 at the defaultEDGE_TOP_K=8) every frame. So the reportedn_personsis a fixed function of the subcarrier count — never 0, regardless of how many people are actually present. An empty room reports 4; users see a constant phantom count.Root cause behind:
The firmware already computes presence (
s_presence_detected, set earlier in the sameprocess_frame()pass) — but the multi-person path never consults it.Fix
Gate person activation on
s_presence_detected: when no presence is detected, mark all persons inactive and return →n_persons = 0in an empty room; persons activate only once presence crosses the (adaptive) threshold.Scope / honest limitations
This bounds the count to presence (0 when empty, ≥1 when someone is there). It does not attempt true multi-person separation — when present, the count is still the subcarrier-derived
top_k/2. Real counting/separation from a single link is a larger DSP problem; this PR just removes the "always N phantom people" behavior everyone is hitting.Testing
idf.py set-target esp32s3 && idf.py build.presence_score(=motion_energy) /s_presence_detectedread ~0 at idle and rise with movement, so the gate yields 0 when empty and activates on presence. The pre-fix constant count (4 attop_k=8) was observed directly on an ESP32-S3.🤖 Generated with Claude Code