Question
On real OPERAnet CSI (OPERAnet cross-modal motion validation § leakage probe) WiFi activity recognition is environment-confounded: raw CSI identifies the room at 0.83 (leave-one-file-out, chance 0.5) and a high-capacity HAR keeps only 0.73 of its accuracy across rooms (LORO 0.51 vs random 0.70) while staying flat across persons. So the real, deployment-relevant generalization boundary is the environment. Does our ray-traced synthetic-CSI pipeline (
sionna-csi-runner) reproduce that environment fingerprint — a comparable cross-room separability and cross-room degradation — when the same occupancy signal is simulated across several distinct room geometries (ResPlan floors)?
Framing discipline. A sim-to-real calibration probe, not a hypothesis test. The honest
deliverable is the head-to-head fingerprint comparison (synthetic floor-ID vs real 0.83; synthetic
occupancy retention vs real 0.73). A match validates the ray-tracer's environment coding and
licenses synthetic-CSI pretraining for cross-environment recalibration (the ble-periodic-calibration
direction); a mismatch localises the defect (scene diversity / wall-material palette / body prior)
into a refit target for exp-csi-calibration. No accuracy headline against self-authored synthetic noise.
What we already know
- OPERAnet cross-modal motion validation (real, CC0): the leakage probe — raw-CSI room-ID LOFO
0.83, HAR cross-room retention 0.73, person axis flat. These are the dimensionless targets
(
REAL_TARGETSinoperanet_sim2real.py). - c-csi-band-calibration / c-csi-roomscale-calibration established the "reproduce a real-measured statistic" calibration-probe pattern (vs WiMANS). This mirrors it against OPERAnet.
- c-csi-cross-geometry-resplan validated
exp-csi-staticacross these exact ResPlan floors — the known-goodsim_paramsshape reused here. - Methodology (2026-06-24 audit) MUST be used:
monad_knowledge/sim/reduction_stats.py(PHYSICAL_BOUNDS, bootstrap CIs) and the explicitsim_campaign_attach_runloop after CLI fan-out.
What the supervisor does
- Smoke first: one cell (
resplan-12439-floor-0, n_agents=0, 5 GHz) locally to confirm the runner stagesfloor_geometry.json+scene.jsonand emits a validlinks.parquet. - Fan out
exp-csi-staticover the 4 floors × 4 n_agents × 2 seeds grid (32 runs, 5 GHz). Systematic on CI for the full grid (fan-out → project key, not the operator's laptop). - Attach each run explicitly (
sim_campaign_attach_runloop). - Run
operanet_sim2real.py(config = per-runlinks.parquetpaths grouped by floor/n_agents): synthetic floor-ID (LORO, all-floors + 2-floor), cross-floor occupancy retention, and the head-to-head table vsREAL_TARGETS. - Synthesise the calibration verdict: reproduces / under-codes / over-codes the environment fingerprint.
Figure render request
operanet_sim2real — two bars: (a) environment-ID accuracy, real OPERAnet room-ID (0.83) vs
synthetic 2-floor floor-ID, with chance line; (b) cross-room accuracy retention, real HAR (0.73) vs
synthetic occupancy, with the no-degradation line.
Dispatch
Fan-out → CI (project key) per the local-vs-remote rule. After committing this brief + the reduction:
/campaign-systematic c-operanet-sim2real-fingerprint # or: gh workflow run sim-campaign.yml -f campaign_id=c-operanet-sim2real-fingerprint
A single local smoke cell (/campaign-curious, or sim_run_launch sim_id=exp-csi-static where=local
with n_placements small) is fine to confirm the chain before the CI fan-out.
Smoke passed (2026-07-13): exp-csi-static on resplan-12439-floor-0 (n_agents=0, n_placements=6,
5 GHz), run 01KXD2QMMSH3DRDW7EBMEK2EQ6, gate_passed, exit 0, 98 s wall-clock (GHCR image reused,
no local build). Emitted valid links.parquet (6 frames × 5 links; mean_amp_db ≈ −68 dB) + csi.hdf5
scene.json;operanet_sim2real.py:_frame_featuresingests it cleanly. Chain sim→reduction confirmed; ready for the CI fan-out (4 floors × 4 n_agents × 2 seeds).
Results — local fan-out (2026-07-13)
Deterministic-supervisor fan-out: 4 exp-csi-static sweeps (one per floor) × n_agents{0,2,4,6}
× seed{0,1}, 5 GHz, n_placements=24 → 31 runs collected (744 per-frame samples), reduced by
operanet_sim2real.py. (First attempt failed when the PostGIS tunnel dropped mid-fan-out;
re-run after restore succeeded.)
| probe | synthetic | real target | verdict |
|---|---|---|---|
| environment fingerprint (2-floor room-ID, chance 0.5) | 0.98 | 0.83 | reproduced, OVER-codes |
| environment fingerprint (4-floor, chance 0.25) | 0.95 | — | strong |
| occupancy signal (within-floor, chance 0.25) | 0.13 | — | at chance |
| occupancy (cross-floor) | 0.24 | — | at chance |
| cross-room retention | undefined | 0.73 | inconclusive (occupancy at chance) |
Verdict (calibration probe).
- Environment fingerprint is reproduced — and over-coded. Ray-traced synthetic CSI identifies
the floor at 0.95 (4-way) / 0.98 (2-floor) vs the real 0.83. The direction matches the real
finding (synthetic CSI is strongly environment-confounded, confirming environment as the hard
generalization axis) but the sim signature is near-deterministic because it lacks real nuisance
variability (hardware noise, temporal drift, furniture change). Refit target: apply the
exp-csi-statichardware-impairment layer + per-run nuisance so the synthetic fingerprint drops toward the measured 0.83 before using synthetic CSI to pretrain cross-environment recalibration — otherwise sim-pretrained transfer will read optimistic. - Occupancy signal is at chance in the static config (within-floor 0.13, cross-floor 0.24 vs
0.25) — random-placement body attenuation does not survive into per-frame link-stat features, so
cross-room retention is undefined. This mirrors the real result (occupancy/activity needed
temporal dynamics, not a static snapshot): the retention arm must be re-run on the coupled
exp-csi-crowd(JuPedSim→Sionna) chain, notexp-csi-static.
Figure: operanet_sim2real.png (a) environment-ID real vs synth; (b) synthetic occupancy at chance.
Runs labelled campaign_id=c-operanet-sim2real-fingerprint.
Occupancy arm re-run on the coupled exp-csi-crowd chain (2026-07-13)
The static occupancy null (0.13) was a static-snapshot artefact, so the arm was re-run on the
coupled walk-notebook(JuPedSim)→sionna chain — temporal motion, per-frame occlusion. On
resplan-12439-floor-0 (the one floor with a proven seek_and_occupy/seat + east-entry
spawn_bbox_cm=[1900,0,2489,1857] config; a first attempt with target_subtype: room and no
spawn bbox turned all agents away → empty trajectory), crowd size {2,4,8,14} × 2 seeds = 8 coupled
runs (150 RT frames each, 1200 frames total), classifying n_agents from per-frame link features
under leave-one-run-out RandomForest:
| config | within-floor occupancy accuracy | chance |
|---|---|---|
static exp-csi-static (random placements) |
0.13 | 0.25 |
coupled exp-csi-crowd (temporal motion) |
0.60 ± 0.39 | 0.25 |
Temporal coupling recovers the occupancy signal — 0.60 (≈2.4× chance) vs the static 0.13. The
crowd-count information lives in the temporal CSI dynamics of moving bodies, not in a static
placement snapshot. This mirrors the real OPERAnet finding (activity/occupancy needed temporal
dynamics) and validates the coupled chain as the correct substrate for the occupancy/retention
question. (High fold variance — 8 leave-one-run-out folds, 2 runs/count — so the point estimate is
directional; a seeded ladder with more runs/count would tighten it.) Figure: operanet_crowd_occupancy.png.
Cross-floor retention — floor-2 tuned (resplan-7421), 2026-07-13
A second floor was tuned for the coupled chain: only resplan-7421-floor-0 has seats (6, all in
bedroom-0; resplan-1374/147440 have zero → seek_and_occupy/seat impossible). Spawn placed in the
living-0 corridor (spawn_bbox_cm=[600,150,1400,900]) so agents walk SE to the seats; smoke
confirmed motion (150 frames, occluders 0–2). Fan-out: crowd {2,4,8,14} × 2 seeds = 8 coupled runs,
matched to the 12439 set. Cross-floor reduction (collect_crossfloor.py, train-one/test-other):
| quantity | value | note |
|---|---|---|
| within-floor occupancy — resplan-12439 | 0.60 | graded regime |
| within-floor occupancy — resplan-7421 | 0.02 | saturated regime (below chance) |
| cross-floor occupancy | 0.25 | = chance |
| nominal retention (cross ÷ mean-within) | 0.81 | confounded — see below |
| real HAR cross-room retention | 0.73 | not apples-to-apples here |
The finding is a mechanism, not a clean retention number. Mean link occlusion vs crowd size: 12439 rises monotonically (0.003→0.003→0.196→0.401 for n=2/4/8/14; amp-std 4.7→12.4) — a graded regime where occupancy is observable (0.60). 7421 is flat at ~0.32 for every crowd size (amp-std ~13.4) — a saturated regime: even 2 agents block the auto-placed link as much as 14, so it is count-blind (within-floor 0.02). Cross-floor transfer is therefore at chance (0.25) and the nominal 0.81 retention is an artefact of averaging a working floor with a saturated one — not a valid analogue of the real 0.73.
Why this matters. Synthetic CSI reproduces the graded-vs-saturated occupancy-observability
dichotomy — whether a link resolves graded crowd count depends on its geometry relative to the
crowd path (the same phenomenon behind the real environment confound and the BLE-anchor saturation
finding c-ble-csi-coregistration). A clean cross-floor retention number vs the real 0.73 requires
both floors' links to be in the graded regime; 7421's auto-placed link is saturated. Next step:
place/select the floor-2 link for a graded response (link-placement tuning, gis place-device), then
re-run — a link-geometry design task, not a pipeline gap. Figure: operanet_crossfloor.png.
Link-placement retune on 7421 → clean cross-floor retention (2026-07-13)
The 7421 saturation was a link-placement artefact: the auto-placed Rx sat in bedroom-0 buried in the
parked-seat cluster, so 1–2 bodies blocked it regardless of total. New experiment
csi-link-resplan-7421-graded places Tx + all 3 Rx in the living-0 corridor spanning the
spawn→bedroom-0 walk path (mirrors 12439's graded living-0 link; primary Rx at [1027,1146] = a 500 cm
vertical link). Re-ran crowd {2,4,8,14}×2 seeds.
| quantity | saturated link | graded link (retuned) |
|---|---|---|
| within-floor occupancy — 7421 | 0.02 | 0.72 |
| within-floor occupancy — 12439 | — | 0.60 |
| cross-floor occupancy | — | 0.37 |
| chance (4 counts) | 0.25 | 0.25 |
| cross-floor retention (sim) | — | 0.57 |
| real HAR cross-room retention | — | 0.73 |
Clean cross-floor retention = 0.57 (sim) vs 0.73 (real). With both floors individually observable (within-floor 0.60 and 0.72, both ≫ chance), the synthetic occupancy model transfers across environments at retention 0.57 — a steeper drop than the real 0.73. Consistent with and reinforcing the environment-fingerprint verdict (sim floor-ID 0.98 vs real room-ID 0.83): because the ray-tracer over-codes environment, a count model learned on one floor generalizes worse to another than real activity does across real rooms. Same refit target: add hardware-impairment / per-run nuisance to soften the synthetic environment signature toward reality.
Sub-finding. On the retuned 7421 corridor link, direct LoS occlusion stays ~0 (mean 0.002→0.007 across counts) yet occupancy is classifiable at 0.72 — the crowd signal arrives via multipath / channel statistics (amp/K/delay-spread), not blockage. On 12439 the graded link does get LoS occlusion (0.003→0.40). Two distinct routes to observability, both defeating the saturated-placement failure. Caveat: 2 floors, 8 runs/floor, leave-one-run-out fold std ~0.30–0.39 → 0.57 is directional, not tight.
Figure: operanet_crossfloor_graded.png.
Impairment / nuisance layer — does it close the gap? (2026-07-13)
Re-ran both graded crowd floors with the commodity-NIC impairment_profile (SNR 20 dB, CFO 200 Hz,
STO 0.5, IQ 0.3 dB/2°, phase-noise 1° RMS, 10-bit quantization, per-run noise draws). Each run keeps
the clean csi.hdf5 oracle + emits csi_impaired.hdf5; features recomputed identically from both
raw tensors (collect_impairment.py) so the comparison isolates the impairment.
| metric | clean | impaired | real |
|---|---|---|---|
| environment fingerprint (2-floor ID) | 0.999 | 1.000 | 0.83 |
| within-floor occupancy | 0.364 | 0.312 | — |
| cross-floor occupancy | 0.257 | 0.194 | — |
| cross-floor retention | 0.708 | 0.623 | 0.73 |
The impairment does NOT close the gap — and the reason is the finding.
- The environment fingerprint is unchanged (~1.0). Commodity-NIC noise does not soften it, because the over-coding is structural — deterministic ray-traced geometry/materials — not a noise-floor effect. Thermal/phase noise can't blur a per-floor geometry signature. (Caveat: on only 2 very dissimilar floors, floor-ID is saturated at ~1.0 even clean; the sensitive test is the 4-floor static setup where clean floor-ID was 0.95 — a proper softening test would re-run that under impairment.)
- The impairment degrades occupancy (retention 0.71→0.62, within-floor 0.36→0.31) — noise erodes the fragile count signal, moving retention away from the real 0.73, not toward it.
Conclusion / corrected refit target. Hardware impairment is the wrong knob for the environment
over-coding: it answers the orthogonal "does occupancy survive a commodity NIC?" question (answer: it
degrades) but leaves the structural fingerprint intact. To soften the synthetic environment signature
toward the real 0.83 the sim needs structural/material nuisance — furniture-layout variation,
wall-material randomization, multi-scene averaging — not measurement noise. That reframes the
exp-csi-calibration refit from a noise-model fit to a scene-diversity fit. Figure:
operanet_impairment.png. (Feature set here is the 4-dim raw-tensor stat, so absolute occupancy
numbers differ from the links.parquet-based 0.57; the clean-vs-impaired delta is the valid signal.)
Scene-diversity nuisance — the right knob (2026-07-13)
Implemented the corrected refit via SceneOverrides.furniture (host-side box-scatterer injection, no
image rebuild): per-run randomized metal-box layouts (5 layouts/floor, 6 boxes, positions inside each
floor's rooms, meters per the cm→m gotcha) on the 4-floor static setup, n_agents=0. Floor-ID
(leave-one-run-out) over the furniture-diverse runs:
| setup | environment-ID (3 floors, chance 0.33) |
|---|---|
| empty scene (deterministic baseline) | ~0.97–1.0 |
| + impairment layer (SNR 20 dB) | ~1.0 (no change) |
| + scene-diversity (metal furniture) | 0.67 ± 0.47 |
| real room-ID | 0.83 |
Scene diversity blurs the fingerprint; measurement noise does not. Per-run furniture randomization
drops synthetic environment-ID from the deterministic ~1.0 to 0.67 — the over-coding is structural,
softened by scene/material variability, not hardware impairment. Metal furniture is aggressive (may
overshoot past the real 0.83) → furniture material/density is the tunable to calibrate to 0.83, making
exp-csi-calibration a scene-diversity fit not a noise fit. Caveats: resplan-7421's 5 runs failed
(metal box clipped a wall on the small floor), so 3 floors; fold std 0.47 → directional. Figure:
operanet_scene_diversity.png.