Skip to content

fix: IDF v6.0 ESP-NOW callback compat (#944) + occupancy noise-floor anchor (#942)#945

Merged
ruvnet merged 2 commits into
mainfrom
fix/issues-942-944
Jun 4, 2026
Merged

fix: IDF v6.0 ESP-NOW callback compat (#944) + occupancy noise-floor anchor (#942)#945
ruvnet merged 2 commits into
mainfrom
fix/issues-942-944

Conversation

@ruvnet
Copy link
Copy Markdown
Owner

@ruvnet ruvnet commented Jun 4, 2026

Summary

Two unrelated reporter-submitted bugs from yesterday's queue, both small, both in this PR:

Closes #944idf build failed for esp32-csi-node

ESP-IDF v6.0 changed esp_now_send_cb_t from (const uint8_t *mac, ...) to (const esp_now_send_info_t *tx_info, ...). The C6 sync ESP-NOW recv path was already version-guarded; the send path missed the equivalent guard. Mirroring the pattern (#if ESP_IDF_VERSION_MAJOR >= 6) — both branches just inspect status so the body is identical.

Closes #942ruvsense::field_model::tests::test_estimate_occupancy_noise_only failing

FieldModel::estimate_occupancy recomputes a Marcenko-Pastur threshold from each estimation window. With a 50-frame calibration but a 20-frame window, the MP factor differs ((1 + √0.16)² ≈ 1.96 vs (1 + √0.40)² ≈ 2.66) AND the local noise_var from 20 samples can be smaller than calibration's — so the test's noise-only window can flip eigenvalues on/off the "significant" line in a sample-size-dependent way and report phantom occupancy.

Fix: persist calibration's noise_var on FieldNormalMode (new field baseline_noise_var: f64) and use max(local, baseline) as the estimation noise floor. Anchors the threshold to the calibration scale without changing behavior when the local window's noise legitimately dominates (real motion case).

baseline_noise_var = 0.0 in the diagonal-fallback paths; the estimation code treats 0.0 as "no anchored floor available" and preserves pre-#942 behavior — old serialised modes still work.

Test plan

  • cargo test --workspace --no-default-features → 413 lib tests pass in wifi-densepose-signal, no other workspace regressions.
  • The eigenvalue-gated test requires BLAS (not buildable on Windows host); CI's Linux job exercises it. Fix is verified by tracing the four numerical anchors in the commit message.
  • idf build failed for esp32-csi-node #944 firmware fix matches the recv-side pattern at c6_sync_espnow.c:102-112; CI's existing IDF v5.4 build is unchanged (its branch fires identically to before), and the new branch enables IDF v6.0+ builds for the reporter.

Hardware

No reflash needed. #944 is a compile-time guard; #942 is host-side signal-processing only.

🤖 Generated with claude-flow

ruvnet added 2 commits June 4, 2026 08:05
)

ESP-IDF v6.0 changed `esp_now_send_cb_t` from
  void (*)(const uint8_t *mac, esp_now_send_status_t status)
to
  void (*)(const esp_now_send_info_t *tx_info, esp_now_send_status_t status)

The C6 sync ESP-NOW path's `on_recv` was already version-guarded with
`#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)` (lines 102-112)
but the `on_send` sibling missed the equivalent guard. CI runs against
IDF v5.4 so the regression slipped through; the reporter on IDF v6.0.1
with xtensa-esp-elf esp-15.2.0_20251204 hit:

  c6_sync_espnow.c:182:30: error: passing argument 1 of
  'esp_now_register_send_cb' from incompatible pointer type
  [-Wincompatible-pointer-types]

Fix: mirror the recv guard with `#if ESP_IDF_VERSION_MAJOR >= 6` since
the send-callback signature change happened at IDF v6.0 (not v5.x like
the recv-callback). Both branches ignore the address-side argument
since `on_send` only inspects `status` to bump the TX-fail counter.

Adds `#include "esp_idf_version.h"` so the macro is in scope.

Closes #944

Co-Authored-By: claude-flow <ruv@ruv.net>
…oses #942)

`test_estimate_occupancy_noise_only` asserts that 20 noise-only frames
fed through a 50-frame calibrated `FieldModel` yield 0 occupancy.
Failure reported on the upstream Linux + BLAS build.

Root cause

Calibration and estimation each compute their own Marcenko-Pastur
threshold:

  threshold = noise_var · (1 + sqrt(p / N))²

with `noise_var` = median of the bottom half of positive eigenvalues
from their own covariance. The MP ratio differs across the two phases:

  calibration  (50 frames, p=8): ratio = 0.16, factor ≈ 1.96
  estimation   (20 frames, p=8): ratio = 0.40, factor ≈ 2.66

On a small estimation window the local `noise_var` estimate can also
be smaller than the calibration's (fewer samples → bottom-half median
hits lower-magnitude eigenvalues). The combination of a smaller
noise_var on estimation and the larger MP factor can flip eigenvalues
on/off the "significant" line in a sample-size-dependent way, so an
identical-distribution test window scores `significant >
baseline_eigenvalue_count` and reports phantom persons.

Fix

Persist the calibration `noise_var` on `FieldNormalMode` (new field
`baseline_noise_var: f64`) and use `max(local_noise_var,
baseline_noise_var)` as the noise floor inside `estimate_occupancy`.
This anchors the threshold to the calibration scale and prevents the
short-window collapse without changing behavior when the local
window's own noise dominates (the real-motion case).

`baseline_noise_var` defaults to 0.0 in the diagonal-fallback paths;
the estimation code treats 0.0 as "no anchored floor available" and
preserves the pre-#942 single-window behavior — so older `FieldNormalMode`
instances deserialised from disk continue to work unchanged.

Test results

  cargo test --workspace --no-default-features
  → 413 lib tests pass (signal crate), 0 fail, 1 ignored.

The actual `eigenvalue`-gated test still requires BLAS (not buildable
on Windows). Logic-trace via the four numerical anchors above shows
the fix flips `noise_var` from the smaller local value back up to the
calibration scale, dropping `significant` to or below
`baseline_eigenvalue_count` so the saturating subtraction returns 0.

Closes #942

Co-Authored-By: claude-flow <ruv@ruv.net>
@ruvnet ruvnet merged commit 872d759 into main Jun 4, 2026
50 checks passed
@ruvnet ruvnet deleted the fix/issues-942-944 branch June 4, 2026 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

idf build failed for esp32-csi-node ruvsense::field_model::tests::test_estimate_occupancy_noise_only

1 participant