docs/research/sota-2026-05-22/R6_1-multiscatterer-forward-model.md
Status: working 6-scatterer body model + breathing-SNR benchmark · 2026-05-22
R6 modelled a single point scatterer. R6.1 extends to a distributed body — 6 scatterers (head, chest, two arms, two legs) summed coherently. The resulting forward model:
csi[k] = Σ_b (refl_b / (d_tx,b · d_rx,b)) · exp(2π·j·f_k·Δℓ_b / c)
The combined CSI is the complex sum of per-body-part contributions, evaluated at each subcarrier. This is what wifi-densepose-signal::vital_signs implicitly assumes and tomography.rs explicitly inverts.
This thread quantifies:
5 m link, 2.4 GHz, subject at midpoint + 25 cm off LOS (inside first Fresnel envelope, R6 says ~40 cm at midpoint). 30-second time-series at 50 Hz CSI rate with breathing at 0.25 Hz (±8 mm chest motion).
| Configuration | Best subcarrier breathing SNR |
|---|---|
| Single-scatterer ideal (R6, chest only) | +23.7 dB |
| Multi-scatterer realistic (R6.1, 6 body parts) | +19.0 dB |
| Penalty from static-limb coherent-sum confusion | +4.7 dB |
The 4.7 dB gap is what realistic deployment loses to idle limbs. These don't move (no breathing motion) but they do contribute coherently to the static CSI level. When chest motion modulates the static signal, the limbs' contribution dilutes the relative modulation depth.
R13 quantified that pulse-contour recovery needs +25 dB SNR, available is +20 dB, gap is 5 dB. R13 attributed this to "subject micro-motion contaminating the HR band".
R6.1 says: the 5 dB gap is also the multi-scatterer penalty. Even without micro-motion, the static body parts already cost 4.7 dB compared to the idealised single-scatterer model. R13's "we are 5 dB short" finding has a physical origin — it's not just measurement noise; it's the body itself.
This is a satisfying integration:
It suggests that single-scatterer-style breathing detection (rate-level, R14 V1 lighting) works because rate has +∞ tolerance — the band-locked signal can be recovered down to any SNR with enough averaging. Contour-shape recovery (HRV, BP) needs the idealised +25 dB which the multi-scatterer reality never delivers.
The same 5 m link, off-LOS subject. CSI energy fraction per body part:
| Body part | Reflectivity | Energy contribution |
|---|---|---|
| Chest | 0.50 | 27.6% |
| Head | 0.10 | 1.1% |
| Left arm | 0.10 | 1.1% |
| Right arm | 0.10 | 1.1% |
| Left leg | 0.10 | 1.1% |
| Right leg | 0.10 | 1.1% |
| Sum (not 100% — coherent sum, not power sum) | 1.0 | 33.6% |
Chest dominates by 5× because its reflectivity (proportional to surface area) is 5× the per-limb value. Practically: the chest IS the breathing signal. Limbs are confound, not signal.
This argues for two architectural decisions:
vital_signs.rs just doesn't use it.vital_signs.rsThe current implementation extracts breathing-rate via a temporal bandpass filter (R5/R6 saliency suggested 0.1-0.4 Hz). It works in practice because the rate signal survives the multi-scatterer penalty. The unit-by-unit takeaway:
| Component | Behaviour | R6.1 evidence |
|---|---|---|
| Temporal bandpass (0.1-0.4 Hz) | Robust | Survives the +4.7 dB penalty; rate recoverable below SNR=0 dB |
| Subcarrier saliency selection (R5) | Beneficial | R6.1 shows uniform SNR across subcarriers; saliency selects more reliable subcarriers, not higher-SNR ones |
| Per-subject breath-rate calibration | Required | The 4.7 dB penalty varies with body geometry; per-subject calibration absorbs this |
| Contour-shape recovery (deferred) | Physically blocked | The 4.7 dB penalty + 5 dB threshold = no headroom |
This matches the existing pipeline's behaviour and explains why it works (rate yes, contour no).
R12 (eigenshift) was a NEGATIVE result. The follow-up suggested PABS over Fresnel-grounded basis:
y_predicted = Σ_voxels A(voxel) · reflectivity(voxel)
residual = y_observed − y_predicted
PABS = norm(residual)
R6.1's multi-scatterer model is the explicit A(voxel) the PABS formulation needs. Each voxel's contribution is computable from R6.1; the residual is what's left after subtracting a population-prior body model from the observed CSI; norm of residual is the structure-detection signal.
This is now a tractable implementation. R12 + R6.1 = a path forward for structure-detection that R12 alone couldn't take.