Environment

A real walkable floor — the 135 m² `living-0` of `resplan-12439-floor-0` (or the `fiit-library` floor) — walked by a JuPedSim crowd whose trajectory drives per-frame ray-traced CSI on the same geometry.

Motivation

The static study (csi-static-occlusion) deliberately froze the crowd — and its own "next steps" flagged that the variance feature actually lives in motion: real CSI counting (Choi/Ling) uses temporal statistics over a sliding window, not per-snapshot spread. This is the first coupled experiment: a JuPedSim trajectory supplies time-varying body positions to the ray tracer, producing a CSI time series rather than per-N snapshots. It is also the first exercise of the exp-csi-crowd chain end-to-end on a real floor.

Design

  • Simulation: exp-csi-crowd (walk-notebook (from_floor) → sionna-csi-runner, wired 2026-06-04). The baked floor_walk.py walks N agents across the real floor; trajectory_frame_stride subsamples frames for the RT pass.
  • Sweep: crowd size (e.g. 5 / 10 / 20 agents) × band {2.4, 5.0} GHz; fixed floor + link.
  • Outputs: per-frame links.parquet (now a time axis) + csi.hdf5 [frame, link, …].

Evaluation

  • Temporal CV over sliding windows vs crowd size; dynamic-to-noise ratio (variance of consecutive-frame CSI differences) ∝ flow — the EasyCount-style operationalisation.
  • Static↔temporal gap: compare the per-frame amplitude distribution here against the static csi-static-occlusion bundles at matched occupancy — does motion widen the bundle beyond placement variance?
  • Trajectory-conditioned attenuation: link attenuation vs instantaneous occluder count per frame.

Prerequisite

A furnished floor (occupiable seats) + a Tx/Rx device layout. Everything else is part of the chain since 2026-06-04: the launcher stages inputs/floor_geometry.json (walker) and inputs/scene.json (channel) from the same PostGIS floor, the walk-notebook image dispatches geometry: from_floor to the baked floor_walk.py, and its trajectory.parquet feeds sionna-csi-runner in the shared workdir. Driven by c-csi-crowd-temporal.

Results (first coupled run, 2026-06-04; multi-agent analysed + adversarially verified)

One coupled run executed on resplan-12439-floor-0 (12 agents → 16 analysis-placed seats, 120 s, RT every 24th frame → 100 frames × 5 links). Two platform notes up front: the registered exp-csi-crowd upstream is parametric-only, so the run was assembled from platform components (gis export-floorfloor_walk.py → staged scene + trajectory → sionna-csi-runner coupled mode); and floor_walk.py needed a spawn-distribution fix (distribute_by_number) before JuPedSim would accept a 12-agent crowd.

  • Coupled plumbing — MET. Frame-indexed links.parquet + csi.hdf5[frame,…] + the carried-through trajectory, no NaN/Inf — the first time-resolved synthetic CSI on a real dataset floor.
  • Body-loss in the time domain — demonstrated. The persistently-occluded rx-bed2 link (99/100 frames) carries a sustained −12.8 dB median dip, corr(occluders, amp) = −0.88.
  • Motion-variance / static↔temporal gap — NOT TESTABLE on this run. Adversarial re-computation found the trajectory never settles: per-frame displacement pinned at 0.060 m/frame (≈1.2 m/s) for all 120 s, all 12 agents still moving at the last frame, net displacement 0.6–9 m against 143 m walked — contradicting the run's own walk-metrics.json ("10 seated, 3.0 s mean time-to-seat"). Root cause: floor_walk bookkeeps "arrival" at 0.4 m but never terminates/parks the JuPedSim journey (dwell_units parsed, unused) — agents orbit their seats indefinitely. Additionally the milling geometry missed the in-room LOS sliver entirely (zero occlusion on rx-living), inverting the expected in-room-dominant signature.

Interpretation (sober). The run validates the coupled pipeline and shows per-body blockage as a time-series signal; the campaign's core question stays open pending the floor_walk dwell fix (terminate or park agents on arrival), a geometric pre-check that the crowd actually crosses the in-room link, and seed/crowd-size replication. The metrics-vs-trajectory contradiction was caught by independent re-computation — the scalar floor alone would have passed. Full deep-dive (environment overlay, crowd animation, CSI time series): notebooks/experiments/csi-crowd-temporal/01_temporal_csi_analysis.ipynb. Rendered artefacts in _attachments/experiments/csi-crowd-temporal/.

Re-run (2026-06-04, dwell + door physics fixed)

Both fidelity defects were fixed in floor_walk.py and the campaign re-run at three crowd sizes:

  1. Dwell/parking — on arrival an agent is parked at its seat: removed from the JuPedSim integrator (mark_agent_for_removal) but kept in the trajectory as a stationary scatterer (a seated person must keep occluding the channel). Exactly one row per (agent, frame): live before arrival, seat after.
  2. Sealed doors — the walkable derivation buffered walls by wall_depth/2 + 20 cm clearance, double-counting the agent body (JuPedSim enforces the radius itself) and squeezing 80 cm doors to ~13 cm — the actual root cause of the original "milling" (agents were stuck en route). Fixed: clearance 5 cm + explicit agent_radius_m = 0.10, plus an optional scenario.spawn_bbox_cm so the crowd enters from the east side and genuinely traverses the floor (the first run's agents spawned next to their seats).

Corrected runs (seed 0, 180 s, east-entry, two-rate RT sampling — every 6th frame in the 0–30 s walking window, every 60th seated; 150 RT frames × 5 links each):

crowd seated note
4 4/4 clean
8 8/8 clean
14 11/14 3 stragglers on tight-door routes keep wandering — documented, slightly inflate seated-phase CV

The walking→seated phase split is now derived from the trajectory itself (settle = last frame after which an agent never moves; flagship: 11/14 settled, last arrival t = 22.8 s, stragglers = agents {21, 22, 23}).

Measured outcomes (criteria verdicts — canonical numbers from the wired-chain sweep 01KT8WCGV890DBW7E7WF8EFZSZ, uniform stride 24 / 1.2 s sampling; the two-rate prototype numbers were consistent and are superseded):

  • C1 plumbing — MET at all six cells as single platform runs of the wired chain (launcher-staged floor bundle + scene; frame-indexed links + carried trajectory; no NaN/Inf; gate_passed=true).
  • C2 motion variance ∝ crowd size — MET, now seed- and band-replicated: walking-phase temporal CV is monotone in crowd size in every independent series — Spearman ρ(size, CV) = +1.0 for each of seeds {0, 1, 2} at 2.4 GHz (sweep 01KT8X6N…) and +1.0 at 5.0 GHz (seed 0). Seed-0 magnitudes: mean-over-links 0.068 → 0.276 → 0.370, living-link 0.036 → 0.230 → 0.478 for 4 → 8 → 14 agents; cross-seed mean ± std in the campaign report. The in-room living link genuinely participates (east-entry traversal).
  • C3 static↔temporal gap — measured, with a structural caveat: walking-phase CV per link 0.036–0.706 vs seated-phase CV ≈ 10⁻⁷–10⁻¹⁶ — the parked crowd produces a literally constant channel (deterministic RT, no micro-motion), so the measured gap is the upper bound of the static-crowd confound. Real seated crowds (breathing, fidgeting) sit between these extremes — modelling parked-body micro-motion is the identified next fidelity step, and exactly the regime where BLE anchoring earns its keep.

The 5 GHz cells (3 runs) are in the same sweep, unanalysed in the notebook's flagship pass — the band axis is the ready-made follow-up.

Remaining caveats (re-run): single seed per size; per-body loss uncalibrated. exp-csi-crowd still needs the from-floor walker wired indone 2026-06-04: the chain is now walk-notebook (from_floor) → sionna-csi-runner with launcher-staged floor bundle + scene from one PostGIS floor (verified end-to-end via sim run exp-csi-crowd).

Campaigns & sessions

Campaign Session State Runs Started Report
c-csi-crowd-temporal planned

Provenance

Data origin
simulated
GIS experiment
csi-link-resplan-12439-multiroom

Data types

  • csi-amplitude
  • rician-k
  • trajectory
  • per-link-summary