Skip to content

Deterministic Spatiotemporal Transport Network Simulator

DSTNS selects a city district from OpenStreetMap using a seed and simulates a virtual day of traffic, signals, demand, weather, flooding and incidents on one authoritative clock. The same seed gives the same world and the same day, on any machine.

181cities in the catalogue

3,000junctions per district

1 sfixed physics step

96checkpoints per day

0.25 to 5xplayback speed

The DSTNS observer showing a district of Dar es Salaam, with the road network coloured by congestion, a telemetry panel and playback controls

Explore the documentation

Getting started

Install, run with Docker, and take your first simulation.

Quick start Docker

User guide

The operator CLI, the observer, playback, seeds and configuration.

Operator CLI Seeds

Concepts

How a seed becomes a world and a day, with the equations.

Architecture Maths

API

Playback, control, view and streaming routes, schemas and examples.

Reference Errors

Deployment

Containers, TLS, security, logging and operations.

Security Operations

Reference

Commands, variables, paths and limits; component internals; release notes.

Limits Components

Design

The decisions behind the system, and its formal specifications.

Decisions Foundation

Help

Symptoms and remedies, common questions, known limitations, a glossary.

FAQ Limitations

Start in one minute

git clone https://github.com/varunkarthic/DSTNS.git && cd DSTNS
docker compose up --pull always

Open http://localhost:8090. The container picks a seed, downloads that city's map the first time, and starts the day.

git clone https://github.com/varunkarthic/DSTNS.git && cd DSTNS
./launcher start --seed 382923

The launcher builds what changed, starts the server, opens the observer and starts a run from seed 382923.

curl -s http://127.0.0.1:8090/api/v1/playback/status
curl -s -X POST http://127.0.0.1:8090/api/v1/playback/seek \
     -d '{"target_time": "08:00:00"}'

The first command reads the run's state; the second jumps to the morning peak. Seeking is exact: the engine restores a checkpoint and replays.

How it works

flowchart LR
    Seed(["Seed"]) --> Place["City and district<br/>181-city catalogue"]
    Place --> OSM[("OpenStreetMap")]
    OSM --> Graph["Road graph<br/>true metres, canonical IDs"]
    Seed --> Sched["Signals, demand,<br/>weather, incidents"]
    Graph --> Engine["Simulation engine<br/>1-second physics"]
    Sched --> Engine
    Engine --> API["HTTP API"]
    API --> Observer["Observer<br/>browser"]
    API --> Client["Your code"]
    CLI["Operator CLI"] -- "starts runs" --> API

Every random choice is derived from the seed through SHA-256, one stream per subsystem. With \( s \) the seed and \( \ell \) a subsystem label, the sub-seed is the first 128 bits of

\[ s_\ell = \operatorname{SHA\text{-}256}\big(\operatorname{hex}(s) \,\Vert\, \texttt{":"} \,\Vert\, \ell\big) \]

so changing how one subsystem draws numbers never moves another's. Physics then advances in fixed one-second steps, so playing to a time and seeking to it reach identical state. Deterministic seeding works the whole path through for a real seed, and Reproducibility states exactly what is guaranteed.

What is in the box

Component What it is Documentation
Core (dstns_server) C++20 engine and HTTP server. Compiles a scenario from a seed, runs the virtual day, serves the API and the observer on one port Architecture, Simulation engine
Operator CLI (./launcher) Builds what changed, starts and supervises the server, starts runs, saved seeds, logs, tests Operator CLI
Observer (ui-engine/) React application: map, telemetry, playback, notifications, PDF report Observer interface
Container image One 234 MB multi-architecture image with a TLS gateway profile Docker deployment
SUMO adapter Exports a world to Eclipse SUMO as a microscopic cross-check SUMO adapter

Model scope

The live model is aggregate: flows and queues per directed road segment, not individual vehicles. That is what makes a whole day of a 3,000-junction district cheap enough to scrub back and forth interactively. The moving dots in the observer show modelled flow. SUMO is a separate batch job and never writes back into a live run.

Find what you need