§1Objective
I wanted a hands-on understanding of digital twins of cities - take the tools practitioners actually use and point them at a problem that is grounded and potentially worth something. My brother Pranav came at it from the other side. He was exploring the digital-twin space broadly, looking for a theme valuable enough to build a startup around, and wanted to see what a small team could credibly ship. We did this build together: my hands on the pipeline, his eye on whether the result was something a planner or a council would pay attention to.
Olympics event egress seemed like a nice and timely problem. We did discuss flood evacuation, EV-charger placement problems as well (and we'll get to them). Event egress is pure demand plus geometry: a demand pulse released from one place onto a real road network. There is no overlay model needed. It is also squarely on the Brisbane 2032 thesis - the exact question the Games' transport planners are paid to answer, at the 63,000-seat stadium whose design was locked this year.
§2The stack: three tools, no cloud
Everything runs on a laptop-class machine from free, permissively licensed parts. Three tools do the work.
OpenStreetMap is the road network. We used a pre-built city extract of Brisbane - a 51 MB .osm.pbf file, ODbL-licensed, so a simulation built on it is legally ours to publish. osmium (the pyosmium bindings) crops that extract to a study area and keeps only drivable roads, dropping footways, service lanes and construction. Cropping matters: a whole-city network simulates slowly and adds nothing when the question is about one precinct - but the box must cover every plausible escape route. Our box runs from Toowong and Enoggera in the west to the Gateway Motorway in the east, and from Chermside down to Annerley: roughly 15 km by 16 km, every river crossing included.
SUMO - Simulation of Urban MObility, version 1.27.1 installed from its PyPI wheel - does the rest. Its netconvert turns the cropped map into a routable network: 35,027 directed road edges and 23,585 junctions, with guessed traffic signals, ramps and roundabouts, and street names preserved so that "Butterfield Street" can be found afterwards. Its duarouter assigns each trip a route. Its simulation core then moves every vehicle through the network, second by second, with 35% of vehicles allowed to re-route mid-trip when they hit a queue.
Three levels of detail, and why we sat in the middle
A traffic simulator has to decide what a vehicle is. Macroscopic models decide it is nothing in particular: traffic is a fluid, and each link carries a flow, a density and a mean speed. Microscopic models decide it is everything: every car, every second, obeying a car-following rule for the gap ahead and a lane-changing rule for the lane beside. Mesoscopic sits between the two. Vehicles stay individual and countable, but they move as tokens through queues on each hundred-metre stretch of road, without second-by-second physics.
We ran meso. Our reasons: a) microscopic simulation of fourteen thousand vehicles would be too slow, we are interested in ballparks. SUMO's documentation puts the mesoscopic engine at up to a hundred times faster. At that speed we can do many runs instead of one. b) Also our question is comparative. Rather than a forecast we are interested in the difference between two runs, and modelling error shared by both runs largely cancels in the difference.
Without lane-changing, a motorway merge is a capacity number on an edge rather than something that emerges from weaving, so ramps like Airport Link probably behave better in our runs than they would on the night. Meso does not model junctions at all by default; we ran with --meso-junction-control, which restores a simplified intersection model. That flag matters, because stadium egress is mostly an intersection problem rather than a road-length problem: whether the exit at Butterfield Street works is decided by the right-turn bay and the signal phase, and meso sees those only coarsely.
§3What we authored, and what SUMO computed
A traffic simulator moves vehicles. It does not know how many people came by car. Everything about demand is an input, and every input is an assumption we wrote down. Everything about what those vehicles then did is an output the engine computed.
| Who | What | Value used |
|---|---|---|
| we authored | Attendance | 40,000 · 63,000 · 80,000 |
| we authored | Share of attendees leaving by car (the rest by rail, bus, or on foot) | 45% ("car-heavy") · 25% ("transit-first") |
| we authored | People per car | 2.5 |
| we authored | Release profile - how fast the car park empties onto the street | all within 30 min · staggered over 90 min |
| we authored | Where cars start: six precinct car-park zones (Herston, Bowen Hills, Gregory Terrace east and south, Kelvin Grove, Countess Street) with shares | 12-22% each |
| we authored | Where cars go: ten outbound corridors (Gympie Rd, Sandgate Rd, Airport, Kingsford Smith Dr, Wynnum Rd, Old Cleveland Rd, Pacific Mwy, Ipswich Mwy, Western Fwy, Enoggera) with weights | 8-15% each |
| we authored | Background traffic on a late evening, so the event does not run on an empty city | random trips across the network, identical in every run |
| SUMO computed | When each car actually gets onto the street (the kerb queue), which route it takes, where it re-routes, how long every road segment takes, where queues form and dissolve | - |
| SUMO computed | Every number in §6 and on the map | - |
Two things are conspicuously not modelled, and the map cannot tell you about them. The crush at the gates and inside the concourse - the pedestrian phase before anyone reaches a car - is out of scope for this build. SUMO has a pedestrian model, but coupling it is its own project. And the transit riders are assumed to be absorbed by rail and bus without adding road load beyond the background level. Whether TransLink's stations can actually swallow forty thousand people in an hour is not something we expect to answer in this twin.
The numbers in the first column are plausible, not surveyed. They are the kind of values we expect a planner to replace for the 2032 transport plan's mode-split targets.
§4Twelve runs and a baseline - we already simulated these offline
A mesoscopic run of this network takes a bit, so we ran the whole variant grid offline - three attendance levels × two mode splits × two release profiles, twelve runs, plus one no-event baseline of the same evening - and baked all thirteen into the interactive twin below. The controls on the map switch between actual runs.
Each run simulates four hours from the moment the gates open at 21:30. For every road segment, SUMO reports the vehicles that entered it and their mean travel time in each five-minute interval; for a 12% sample of vehicles it also writes a position every 30 seconds, which is what the moving dots on the map replay.
§5The interactive twin - how to read it
Below is the artifact itself. A few things to know before you touch it.
- The controls pick a variant: attendance, mode split, release profile. Every combination is a separate, fully simulated run. The comparison table at the bottom of the side panel lists all twelve. Click a row to load it.
- The map colours each road by its delay factor - measured travel time divided by free-flow travel time - in the fifteen-minute window around the playhead. Drag the time scrub, or press Replay, to watch the pulse move outward. Orange dots are event vehicles, blue dots background traffic; both are a sampled subset. Hover any road for its numbers; scroll to zoom, drag to pan.
- "vs no event" switches the map to shade each road by how much slower it is than the same window in the no-event baseline, with a ±10% dead band so noise renders neutral. This is the comparison view - the twin's real output.
- Kerb-clear 95% is when 95% of event vehicles had left the car-park queue and were on the street. Corridor exit 95% is when 95% had reached their outbound corridor. p90 door-to-corridor counts the time in the car-park queue as well as on the road - the ninetieth-percentile leaver's whole experience.
- Trust p90 and throughput, not the median. In a congested system the median is dominated by whoever got out early; it goes down as things get worse. Part 1 called this survivor bias. Every tile on the panel shows the median next to the p90 so you can watch it lie.
§6What the runs say
Start at the default: 63,000 people, car-heavy split, everyone released within thirty minutes. That is 11,340 cars trying to leave one precinct at once. The precinct's roads are running at 8.2× free-flow thirty minutes after the gates open. It takes 110 minutes for 95% of cars to even get out of the car-park queue and 120 minutes for 95% to reach their outbound corridor. The p90 door-to-corridor time is 89.5 minutes - while the median is 17.5. The worst delay concentrates where you would expect if you know the area: Countess Street and North Quay feeding the CBD, Saul Street, and the precinct's own exits at Butterfield Street, Scott Street and Fleming Road.
Now stagger the release over ninety minutes and change nothing else. The p90 collapses to 13.9 minutes. The kerb queue effectively disappears: 95% of cars are on the street by 86 minutes, which is simply the end of the release window - the road network absorbs the trickle as fast as it arrives. The chokepoints move off the precinct streets and onto the corridors - Airport Link, Bramston Terrace, the Pacific Motorway. The precinct is never in crisis.
But look at the residual-congestion tiles and the story flips. At +60 and +90 minutes the staggered run shows the precinct at 3.5× and 3.7×, against 1.7× and 1.07× for the all-at-once run. Staggering does not remove the load; it spreads it thin over a longer period, and the metric that asks "how bad is the precinct an hour after the gates opened" is still looking at a precinct that is busy by design. Meanwhile the all-at-once run's precinct roads look calm at +90 because a chunk of the cars is not on them yet - it is still stuck in the car-park queue, which this metric does not see. The metric you choose decides which release policy looks better. A twin that reported one number would have hidden that.
Two more readings from the grid. The transit-first split at 63,000 - 6,300 cars - is roughly what the car-heavy split at 40,000 is: p90 of 41 minutes versus 53, precinct clear within the hour in both cases. Mode share buys you the same relief as cutting the crowd by a third. And at 80,000 with the car-heavy split, all at once, the system is genuinely broken: p90 of 122 minutes, kerb queue still draining at 148 minutes, Kelvin Grove Road carrying 41 vehicle-hours of delay on its own.
| Run | Vehicles | Kerb 95% | Exit 95% | p90 | Median | Delay +30/+60/+90 | Worst link |
|---|---|---|---|---|---|---|---|
| 40k · car-heavy · at once | 7,200 | 67′ | 76′ | 53′ | 12′ | 3.6× / 1.1× / 1.0× | Butterfield Street |
| 40k · car-heavy · staggered | 7,200 | 85′ | 94′ | 13′ | 9′ | 1.3× / 1.3× / 1.1× | Airport Link |
| 40k · transit-first · at once | 4,000 | 29′ | 40′ | 15′ | 9′ | 3.1× / 1.1× / 1.0× | Airport Link |
| 40k · transit-first · staggered | 4,000 | 85′ | 94′ | 13′ | 8′ | 1.1× / 1.1× / 1.0× | Airport Link |
| 63k · car-heavy · at once | 11,340 | 110′ | 120′ | 90′ | 18′ | 8.2× / 1.7× / 1.1× | Countess Street |
| 63k · car-heavy · staggered | 11,340 | 86′ | 96′ | 14′ | 9′ | 1.5× / 3.5× / 3.7× | Airport Link |
| 63k · transit-first · at once | 6,300 | 55′ | 64′ | 41′ | 11′ | 6.1× / 1.0× / 1.0× | Scott Street |
| 63k · transit-first · staggered | 6,300 | 86′ | 94′ | 13′ | 8′ | 1.2× / 1.1× / 1.1× | Airport Link |
| 80k · car-heavy · at once | 14,400 | 148′ | 158′ | 122′ | 26′ | 8.5× / 5.3× / 1.3× | Kelvin Grove Road |
| 80k · car-heavy · staggered | 14,400 | 108′ | 118′ | 44′ | 10′ | 3.7× / 3.4× / 3.4× | Airport Link |
| 80k · transit-first · at once | 8,000 | 75′ | 84′ | 60′ | 12′ | 5.1× / 1.0× / 1.0× | Butterfield Street |
| 80k · transit-first · staggered | 8,000 | 85′ | 94′ | 13′ | 9′ | 1.2× / 1.2× / 1.1× | Airport Link |
Sanity checks before quoting any of it
A results table is only as good as the checks behind it. These are the ones we ran, with verdicts.
- PASSThe baseline is healthy. Over the four-hour no-event run, the precinct's mean delay factor never exceeds 1.14× (average 1.02×). The background traffic is busy-but-moving, not a gridlocked starting point that would flatter every variant.
- PASSAll demand was served. In every one of the twelve runs, every event vehicle was inserted and reached its corridor within the four-hour window - zero unfinished trips. The comparisons are between complete populations, not between whoever survived.
- PASSVehicle counts reconcile. Each run's event-vehicle count equals attendance × car share ÷ 2.5, to within flow-rounding (e.g. 11,340 planned, 11,379 generated at 63k car-heavy).
- PASSThe kerb queue behaves. In all-at-once runs, the time for 95% of cars to reach the street far exceeds the 30-minute release window (67 min at 40k, 110 at 63k, 148 at 80k) and grows with attendance - the origin streets are saturated, as they should be. In staggered runs it sits at 85-86 minutes for every attendance level, i.e. the end of the 90-minute window: the network keeps up with a trickle.
- PASSChokepoints are capacity-plausible and geographically right. The worst streets in the all-at-once runs are the precinct's real exits (Butterfield St, Kelvin Grove Rd, Scott St, Fleming Rd) and the CBD approach (Countess St, North Quay). In staggered runs the worst links are the corridors themselves. No delay appears on a road the event traffic would not plausibly use.
- N/AClosed-link volume is zero. The standard check for a road-closure scenario. This scenario cuts no roads, so it does not apply - noted so that its absence is not mistaken for an omission.
§7Model caveats
Everything above is directional and uncalibrated. The demand is synthetic: the mode splits, the car occupancy, the release windows, the six origin zones and the ten corridor weights are our assumptions, not survey data. There is one random seed per run, so the spread of outcomes you would see across many draws of the same scenario is not shown - Part 1's fourth correction, and we knowingly broke it here to fit thirteen runs into a session. The engine is mesoscopic, so intersection capacity - the thing an egress usually turns on - is modelled coarsely, and lane-level behaviour like motorway weaving not at all (§2). Nothing has been calibrated against real Brisbane traffic counts. The car-park queue is represented by SUMO's insertion queue, a reasonable stand-in but not a model of a car park.
What this means for use: the twin is right for "shape of the impact" questions - does staggering help, where does it choke, how much does mode share buy - and wrong for forecasts. Nobody should read "p90 of 89.5 minutes" as a prediction of a night in 2032. They should read "staggering cuts the p90 by a factor of six under identical assumptions," because that is a comparison, and the shared errors largely cancel.
The upgrade path to defensible numbers is the same one every scenario on our list shares: the 2032 transport plan's mode-split targets and event-mode street closures as inputs, TransLink's station capacities for the transit side, real traffic counts to calibrate the background, and a sweep of seeds to put bands on every number. None of that changes the machine. All of it changes the first column of the table in §3.
Every state of the controls is a real, precomputed SUMO run. Results are directional and uncalibrated: synthetic demand, one seed, mesoscopic engine, no calibration. What is SUMO's is defensible with no assumptions beyond the demand being synthetic; what is ours is labelled as ours.
§8What we took from it
For me, the hands-on goal was met more completely than I expected. The stack is real and it is small: a map extract, a cropping tool, a simulator with a Python toolchain, and a few hundred lines of our own code to author demand, analyse output and bake the page. The whole loop from raw map to interactive comparison fits in a working session. I am reasonably sure that I will be able to leverage the network and pipeline used here for other scenarios like the flood evacuation, the EV chargers etc. as well.
For Pranav's question - is there something here to build on - the build sharpened rather than answered it. The valuable object was never the map. It was the precomputed grid with its provenance attached: which runs, which assumptions, which checks passed. That is what a planner could argue with. The map is how you look at it. A product in this space that sells the map without the ledger is selling a demo; a product that sells the ledger has to earn calibration data from the very agencies it wants as customers. That tension, more than any tooling gap, is what we keep coming back to.
And the smallest lesson is the one we would put first for anyone starting: pick the metric before you pick the policy. The same twelve runs make staggered release look like a triumph on one tile and a problem on the next. A twin does not resolve that. It makes it visible, which is the most a model should claim.
Sources & data
- OpenStreetMap data, © OpenStreetMap contributors, Open Database License - openstreetmap.org/copyright · pre-built city extracts from BBBike - download.bbbike.org
- pyosmium 4.3.1, Python bindings for libosmium - osmcode.org/pyosmium
- Eclipse SUMO 1.27.1 - eclipse.dev/sumo · mesoscopic model - sumo.dlr.de/docs/Simulation/Meso.html · netconvert - sumo.dlr.de/docs/netconvert.html · duarouter - sumo.dlr.de/docs/duarouter.html
- Brisbane Stadium at Victoria Park, 63,000 seats - GIICA, Games Independent Infrastructure and Coordination Authority - giica.au · Brisbane 2032 delivery updates - delivering2032.com.au (verified Aug 2026)
- Study-area network: OSM Brisbane extract cropped to 152.975-153.128 °E, 27.528-27.385 °S; netconvert with
--geometry.remove --ramps.guess --junctions.join --roundabouts.guess --tls.guess-signals --keep-edges.by-vclass passenger; 35,027 edges, 23,585 junctions. Runs:sumo --mesosim --meso-junction-control, 4 h, edge data at 300 s, 35% rerouting every 120 s, 12% FCD sample at 30 s.