Aporia

Validation report

26 October 2026, updated 27 October · JuPedSim 1.4.2 · configuration 2026-10-26.1

Aporia's network is only as good as the simulations it learned from. This report checks the simulator against real crowds: with its default settings, JuPedSim does not match the experiments. A calibrated configuration does, on data it was not fitted to. It has been the default since 26 October 2026.

0.76 → 0.46Corridor error on held-out widths (speed and density, relative RMS)
0.32 → 0.09 mError on where people pass a held-out 90° corner (W1)
9 / 9Independent bends where the new routing is better or equal
79 / 80Pilot runs accepted, 40 random bends × 2 seeds

Verdict

  • Defaults are off. With JuPedSim's defaults, pedestrians walk about 0.3 m/s too slowly at every density in the Jülich corridors, and cut a 90° corner too close to its inner wall.
  • The fix holds out. A shorter time gap (0.7 s), desired speeds measured on the same people, and lane routing match corridors, corners and an independent lab's bends that were never used to fit them.
  • Hugging the inner corner is partly real. Real crowds do pass close to it (60–98 % of passages in the inner half). Shortest-path routing exaggerates it; the candidate reproduces it. Peaks at the inner corner fall by up to 4× (90°, 4 m, q = 0.6: 3.10 → 0.79 ped/m²).
  • What is validated is speed and density in corridors and where people pass in bends. Not the full density maps of bends, and not how people react to a chamfered corner.
Validated envelope. Flow q ≤ 0.7 ped/(m·s) · width 1.5–3.0 m · angle ≤ 135° · density ≤ about 1.5 ped/m². The pilot suggested q ≤ 0.9; the 5,400 s runs of dataset v2 showed that wide (≥ 2.8 m) or sharp (≥ 96°) bends can break down from q = 0.76, so the envelope was tightened (measurements).

What changed in the simulator

The local model is JuPedSim's collision-free speed model. Two things were changed, and they must be chosen together: lane routing with the default model still jams sharp, wide bends.

SettingDefaultValidatedSource
Time gap T1.0 s0.7 sFitted, 2.4 m corridors
Desired speedN(1.34, 0.26) m/s (Weidmann)N(1.62, 0.16) m/sMeasured, 54 solo walks
Radius0.2 m0.2 mUnchanged
RoutingShortest pathLane routing: 3-point arc, bias 0.3, radius 0.6 mFitted, 2.4 m corner

Lane routing gives each walker waypoints that keep their lateral position through the turn, instead of steering everyone through the inner corner. It is a behavioural model with its own parameters, separate from the geometry.

Data and splits

Public experiments, converted to trajectories and measured with the same code as the simulations. Splits were fixed before any fitting; held-out sets were never used to make a choice.

ExperimentUsed forFit onHeld out
Jülich HERMES 2009, corridorsTime gap2.4 m, 6 runs1.8 m (6), 3.0 m (7)
Jülich 2009, 90° cornerRouting2.4 m, 6 runs3.0 m, 6 runs
Jülich 2009, individual walksDesired speeds54 walks–
Hannun et al. 2022, bendsIndependent check–45°, 90°, 135° at 1.5 m
DOIs: 10.34735/ped.2009.14, .8, .9 · 10.17605/OSF.IO/DYFJW. Corridor runs with a narrowed exit are bottlenecks and are excluded.

Walking speed in corridors

Each experiment is replayed: people enter where and when they were first seen. The loss adds the relative RMS difference of density and of speed, frame by frame, in a 2 m measurement area (Voronoi method).

Loss on held-out corridors · 1.8 and 3.0 m, lower is better

Default, T = 1.0 s
0.759
Stage 1, T = 0.7 s
0.459
Stage 2 (not kept)
0.370
ConfigurationFit loss, 2.4 mHeld-out lossSpeed error per density bin
Default: T = 1.0 s, v0 ~ N(1.34, 0.26)0.7870.759 ± 0.0500.33 m/s
Stage 1: T = 0.7 s, v0 ~ N(1.62, 0.16) measured0.4650.459 ± 0.0060.11 m/s
Stage 2: T = 1.1 s, r = 0.125 m, v0 mean 1.550.3490.370 ± 0.0050.06 m/s
± is the spread over 3 seeds. Desired speeds come from the solo walks, not from the fit.

Why not stage 2? It fits better, but the time gap and the radius trade off along a ridge: the best points differ by 1–2 seed spreads, so the two cannot be told apart. Stage 1 has a single, interior optimum. Remaining misfit: about 0.1 m/s too fast at low density, and a flatter speed–density relation than the data. Densities above about 1.5 ped/m² are outside the calibrated range.

Speed against density: Jülich data with error bars, the default model about 0.3 m/s too slow, stage 1 close above the data, stage 2 closest.
Speed against density, fit (left) and held out (right). The default (dashed red) is too slow everywhere; stage 1 (blue) sits just above the data.

Turning a corner

Statistic: where each person crosses the apex of the turn, as distance from the inner corner. Simulated and measured distributions are compared by the 1-Wasserstein distance (W1): roughly, how far in metres the crossings must move on average to match the data.

In the data, inner-corner concentration is real: 60–98 % of passages lie in the inner half, more at low flow; the median distance is 0.4–1.25 m. Shortest path sends people within 0.2 m of the corner at low flow, where the data are at 0.4–0.6 m.

W1 on the held-out 3.0 m corner · metres, lower is better

Shortest path
0.315 m
Lane, apex, 0.3 / 0.3 m
0.085 m
Lane, apex, 0.0 / 0.6 m
0.066 m
Lane, arc, 0.3 / 0.6 m
0.091 m
Routing, T = 0.7 sW1 fit, 2.4 mW1 held out, 3.0 m
Shortest path (JuPedSim)0.204 m0.315 m
Lane, apex point, bias 0.3, radius 0.3 m0.052 m0.085 m
Lane, apex point, bias 0.0, radius 0.6 m0.051 m0.066 m
Lane, arc (3 points), bias 0.3, radius 0.6 m0.061 m0.091 m
Why the arc, not the lowest number. The best single-apex variant on the fit runs clogged 150°, 4 m bends at q = 0.6 (peaks above 6 ped/m², 4 failures in 12 runs): outer lanes were forced into a hairpin. A constraint was then added: among ten variants, the lowest fit W1 with no failure in a 12-run stress set. That is the arc. Held-out results were printed, never used to choose. The constraint came after seeing a failure, and is recorded as such.
Cumulative share of passages against distance from the inner corner, four Jülich corner runs: lane routing follows the data closely; shortest path runs left of it, too close to the corner.
Where people cross the apex, two fit and two held-out runs. Black: data. Red: shortest path, too close to the corner. Blue: lane routing.

Independent bends: Hannun et al.

Another lab, another population, a 1.5 m corridor, and angles never used (45°, 135°). Their data have one clock per person, so only paths are compared. Geometry was inferred from the paths (angles within 3° of nominal). The protocol is replayed: 55 people start together from a 6 × 6 m holding area.

W1 of apex passages · m, lower is better

Share of passages in the inner half · at the apex

AngleShortest path, approach 4 / 6 / 8 mLane routing, approach 4 / 6 / 8 m
45°0.160 / 0.151 / 0.1500.143 / 0.134 / 0.138
90°0.118 / 0.139 / 0.1350.120 / 0.111 / 0.105
135°0.125 / 0.131 / 0.1420.121 / 0.114 / 0.115
W1 in metres, 5 seeds (spread 0.002–0.022 m). The approach length is not published, so three were tested. Charts above use 6 m.

Lane routing is better or equal in all nine settings, but by a small margin: in a crowded 1.5 m corridor the crowd fills the width whatever the route. The clearer signal is the inner-half share at 90° and 135°, where shortest path overshoots the data and lane routing does not.

Which runs are accepted

A 60-run grid (angles 0, 90, 150°; widths 1.5 and 4 m; sharp and fully chamfered; q = 0.2 and 0.6; 3 seeds), run with four configurations: the two changes, alone and together.

PassInconclusiveFail
  • The default's six failures are all 150°, 4 m bends at q = 0.6: arrivals refused, the bend is over capacity.
  • Its low-flow runs are mostly inconclusive: about 5 people in view cannot resolve a 10 % change within 1,200 s. Inconclusive is never counted as a pass.
  • All seven inconclusive candidate runs come from one small region (the inside of the turn) in 1.5 m bends.

What it changes in the maps

The training targets change materially. In wide bends at moderate flow, the default piles the crowd against the inner wall; the candidate spreads it across the width.

Density maps, default above, candidate below, for three bends. Peaks: 3.09 to 0.79, 1.46 to 0.83, 1.12 to 0.26 people per square metre.
Mean density, ped/m². Top: default (T = 1 s, shortest path). Bottom: candidate. Peaks 3.09 → 0.79 (90°, 4 m, q = 0.6), 1.46 → 0.83 (150°, 1.5 m), 1.12 → 0.26 (90°, 4 m, chamfered, q = 0.2).

Diagnostics

Before fitting anything, four questions about the simulation itself.

Is the run long enough?
Not always with the default: 4 m bends at q = 0.6 are still filling up after 600 s (90°: drift 0.149 against noise 0.027 ped/m², occupancy 97 → 107). With the candidate, every case is stationary after 200 s (drift ≤ 1.5 × noise).
Do the corridor ends matter?
Barely. Lengthening the legs from 18/21 m to 24/27 m moves maps by at most 0.041 ped/m² (default) and 0.028 (candidate), far below the narrowest Fruin band (0.12). The shorter legs are kept.
Does the measurement bias the result?
Recording every 0.1 s instead of 0.5 s leaves density maps identical (≤ 0.003). Speeds in turns are biased low at 0.5 s, by up to 23 %: chords cut the arcs. The p99 peak depends on the smoothing width: σ = 0.3 m raises it 5–12 %, σ = 0.5 m lowers it 2–10 %; σ = 0.4 m is used throughout.
Routing or local model?
Both, together. Lane routing with the default model still jams 150°, 4 m bends at q = 0.6 (peaks 3.7–4.8 ped/m²).

How a run is judged

Every run goes through the same measurements and checks, whether simulated or real. 206 tests cover them.

Density map
Positions counted on a 0.25 m grid, smoothed with a Gaussian (σ = 0.4 m) that cannot see through walls, and divided by the exact walkable area of each pixel. Near walls the estimate is 0.989–1.014 of the true density (a simple pixel mask gives 0.968–1.014).
Consistency
Exact bookkeeping: everyone inside the walls, every arrival accounted for (requested = spawned + refused + waiting), the map's integral equal to the mean head count.
Load
Zero refused arrivals, and the measured outflow within 5 % of the requested flow.
Stationarity
The two halves of the window must agree within a tolerance fixed in advance: 10 % for the whole view, 20 % or 0.1 ped/m² for small regions. Standard errors are corrected for autocorrelation. A pass needs |difference| + 2 se ≤ tolerance; too few independent samples can only fail or stay inconclusive.
Outcome
Each check ends pass, fail, inconclusive or not applicable, with its value, threshold and reason. Rejected runs are kept.

Gate and pilot

Large-scale generation was allowed only once every condition below held. The gate opened on 26 October 2026.

ConditionStatus
Numerical tests pass206 tests
Accepted runs pass consistency, load and stationarity; rates reported by angle, width, loadYes, rejected runs kept
Routing and local model have independent supportHeld-out widths, plus an independent lab and angles
Versions and settings pinnedaporia.validated, checked by a test
Demand restricted to a range verified for bendsq ≤ 0.9 by the pilot, then q ≤ 0.7 (dataset v2)
Pilot, two seeds per geometry, worst cases inspected79 / 80 accepted

Pilot: 40 random bends over the full range (θ 30–150°, w 1.5–4 m, chamfer 0–w, q 0.1–1.1), two seeds each. All 68 runs below q = 0.9 pass, and 11 of 12 between 0.9 and 1.1. The one failure (θ = 103°, w = 3.5 m, q = 1.05) jams at 4.9 ped/m² while its other seed passes: q ≈ 1 is the edge of a bend's capacity. Two seeds of the same bend differ by 0.016 ped/m² RMS (median, max 0.032), so a two-seed mean is known to about 0.008.

Nine pilot density maps: one jammed bend at q 1.05 with densities up to 5, eight smooth maps at flows from 0.11 to 0.69.
Pilot maps, seed 0. Top left, the only failure (note its 0–5 scale). The others show no stripes or funnels.

Limits

  • Extrapolation. Widths above 3.0 m, angles above 135°, densities above about 1.5 ped/m², and other populations: the speeds are those of German students in 2009 (1.62 ± 0.16 m/s). Older or mixed crowds walk slower (Weidmann: 1.34 m/s).
  • Model. The speed–density relation is flatter than observed; the model gridlocks at narrow exits; lane routing is a surrogate, validated on where people pass, not on full density maps of bends; a chamfer's effect on real walkers is untested.
  • Selection. The routing constraint was added after a failure was seen. Held-out sets were not used for any choice.
  • Measurement. Speeds in turns from 0.5 s recordings are too low; the p99 peak depends on σ. Low-flow or small-region stationarity often cannot be certified in affordable runs: such runs are inconclusive, never silently accepted.
  • Hannun replay. Approach length, speed spread and holding-area layout are assumptions (sensitivity to the approach shown above).
  • Scope. One-way, steady flow below capacity. No counter-flow, pushing or evacuation.

Reproduce

Every number on this page comes from one of these commands of the Aporia pipeline. The resulting training bends are public: aporia-bends on Hugging Face.

uv run aporia fetch-data            # datasets, checksums verified
uv run aporia calibrate             # corridors, corner, Hannun (~8 min, 10 cores)
uv run aporia experiment baseline   # 60-run grid, default configuration
uv run aporia experiment crossed    # the three other configurations
uv run aporia experiment diagnostics
uv run aporia experiment pilot && uv run aporia report pilot
uv run pytest                       # 206 tests