docs/adr/ADR-113-multistatic-placement-strategy.md
Status: Proposed · Date: 2026-05-22 · Author: SOTA research loop tick-31 · Amends: ADR-029 (RuvSense multistatic sensing mode)
ADR-029 (RuvSense multistatic) introduced multi-anchor CSI sensing but did not specify how many anchors, where to place them, or how zones depend on the target cog. The SOTA research loop (2026-05-22) produced 9 ticks in the R6 family that quantitatively answer these questions:
This ADR consolidates the findings into a single placement specification, parameterised by dimension × zone-mode × occupant-count × cog.
Adopt the 4-axis placement decision matrix below as the binding RuView installation specification.
| Cog category | Dimension | Zone mode | Occupants | Recommended N | Anchor heights | Expected coverage |
|---|---|---|---|---|---|---|
| Presence / occupancy | 2D | body | 1 | 3 | walls @ 0.8 m | 63% |
| Person count | 2D | body | 1-4 | 4 | walls @ 0.8-1.5 m mixed | 86% |
| Pose estimation | 2D | body | 1-2 | 5 | walls @ 0.8/1.5 m mixed | 97% |
| Vital signs | 2D | chest | 1-4 | 5 | walls @ 0.8/1.5 m | 100% |
| Pose estimation (3D) | 3D | body | 1-2 | 7-8 | mixed: 0.8/1.5/2.4 m | 65%+ |
| Vital signs (3D) | 3D | chest | 1-4 | 6 | walls @ 0.8/1.5 m, NO ceiling | 82% |
| Maritime cabin | 2D | chest | 1-3 | 4 | low (0.5-0.8 m) | 80%+ |
| Wildlife sensing | 1D linear | full-corridor | 1-5 species | 4 (along corridor) | tree-mount mixed | 70%+ |
The R6.2 CLI tool surfaced through the family ticks:
wifi-densepose plan-antennas
--room W H [Z] # 2D or 3D
--target NAME X Y W H [DX DY DZ] # repeatable
--target-mode {body, chest} # R6.2.3
--freq-ghz F # 2.4, 5.0, 6.0
--n-anchors N # auto-saturate if omitted
--restarts K # 4 default
--cog COG_NAME # auto-select target-mode + N
Total LOC for productisation: ~100 LOC on top of the R6.2.5 reference implementation.
ruview_placement_recommend(
room: {width, depth, ceiling?},
targets: [{name, position, size}],
cog: str // auto-configures target-mode + N
) -> {
anchors: [{x, y, z, height_category}],
expected_coverage: float,
placement_rationale: str
}
Status: rejected. Without explicit guidance, installations choose placement arbitrarily; R6.2 measured 93× spread between optimal and median placement. Silence is a 93× implicit loss.
Status: rejected. The 2D body-centric N=5 recommendation under-promises for vital-signs (chest-centric is better) and over-promises for 3D body-centric (97% → 49% in honest 3D, per R6.2.2.1).
Status: rejected. R6.2.2.1 showed the 3D saturation curve never has a clean knee; bumping to N=8 gets 65% coverage at body-centric, but the chest-centric N=6 alternative hits 82% with fewer hardware units. Per-cog decision is the right granularity.
Status: rejected. R6.2.1 + R6.2.2.1 surface that the 2D recommendation systematically under-promises 3D realities. The dimension axis must be explicit.
Placement strategy is not a security-critical decision in itself; coverage gaps create functional risk, not adversarial risk. The 4-axis matrix ensures:
| Risk | Mitigation |
|---|---|
| Vital-signs coverage gap | chest-centric + N=5 (or N=6 in 3D) at recommended heights |
| Sleep-monitoring miss | both anchors low (0.5-0.8 m), opposite sides of bed |
| Multi-subject failure | use multi-subject-aware placement (--target repeated) |
| Adversarial single-link spoofing | R7 mincut needs N ≥ 4 — placement matrix ensures this for all multi-feature cogs |
| Per-installation variance from documented baseline | CLI tool gives reproducible deterministic placement |
wifi-densepose plan-antennas in 2 minutes and get a placement diagram.ruview_placement_recommend programmatically.--cog flag absorbs this.ruview_placement_recommend becomes a new MCP tool.The --cog flag in the CLI looks up the cog category and maps to matrix row:
| Cog | Category | Target mode | Heights | N |
|---|---|---|---|---|
cog-presence | presence | body | low | 3 |
cog-person-count | count | body | mixed low | 4 |
cog-pose-estimation | pose | body | mixed | 5 (2D) / 7 (3D) |
cog-vital-signs | vital signs | chest | low+mid | 5 (2D) / 6 (3D) |
cog-breathing | vital signs | chest | low+mid | 5 (2D) / 6 (3D) |
cog-heart-rate | vital signs | chest | low+mid | 5 (2D) / 6 (3D) |
cog-intruder | structure detection | body | mixed | 5 |
cog-maritime-watch | maritime | chest | low | 4 |
cog-wildlife | wildlife | linear | tree-mount | 4 |
| Step | LOC | Owner |
|---|---|---|
1. CLI --cog flag with category lookup | 60 | TBD |
2. MCP tool ruview_placement_recommend | 80 | TBD |
| 3. Per-cog category metadata in cog manifests | 30 | per-cog |
| 4. 3D ellipsoid extension to CLI tool | 50 | TBD |
| 5. Multi-target union to CLI tool | 40 | TBD |
| 6. Integration tests against the R6 family numpy reference | — | TBD |
Total ~260 LOC. Combined with R6.2 productisation (~100 LOC), placement-strategy budget is ~360 LOC.
The multistatic placement question that ADR-029 left open. After this ADR, ADR-029 + ADR-113 + the R6.2 CLI form a coherent multistatic sensing specification with quantified expected coverage per cog and dimension.
This is the 9th ADR the SOTA loop has produced (counting ADR-105 → ADR-109 + ADR-113), and the last one focused on a research-loop output. Future ADRs (ADR-110/111/112) are operational, not research-driven.
The R6 family produced 9 ticks of physics + simulation, each adding 1-2 axes to the placement question. ADR-113 collapses all 9 into a single decision matrix that a non-physicist installer can use. The loop's most ship-relevant integrative output.