This model simulates the movement of pedestrians across the street network of large urban areas. The novelty of the model lies on the inclusion of cognitive representations of space (cognitive maps) in the behavioural architecture of the pedestrian agents.
More specifically, a computational approach to Kevin Lynch's The Image of the City (see related paper in Cities) is employed to incorporate salient urban elements in the cognitive maps of the agents - alongside perception of distances and angular relationships between road segments. It is argued that the include of certain urban elements in one’s cognitive map shapes their route choice behaviour, that is how they formulate a route between an origin and a destination.
The ABM has been built following a stepwise approach, so as to explore and assess the effect of the inclusion in the cognitive map of the agents of different urban elements (1. landmarks, 2. regions and barriers).
The impact of element-based route choice models within the model was assessed in comparison with minimisation-based route choice models (i.e. distance shortest path, least cumulative angular change). The inclusion of these urban elements has been tested, in combination with existing route choice models:
- Landmark-based navigation: London - Methods, results and evaluation are documented in Modelling the effect of landmarks on pedestrian dynamics, published in Computers, Environment and Urban Systems.
- Region- and barrier-based navigation: London and Paris - Methods and results, along with a validation are documented in Perception of urban subdivisions in pedestrian movement simulation, published in PLoS ONE.
The ABM allows executing these experiments Testing Landmarks and Testing Urban Subdivisions.
In addition, the ABM, can be run as an empirical-based model where the interaction between the effects of the different urban elements is regulated and calibrated on the basis of empirical data (“Empirical ABM”). The ABM, the qualitative study conducted to calibrate it, and its evaluation are documented in Empirical characterisation of agents’ spatial behaviour in pedestrian movement simulation, published in Journal of Environmental Psychology.
Testing Urban Subdivisions: Pedestrian Volumes after elaboration in Python (London, UK)
PedSimCity is built on:
Along with:
How to run:
- Install Java (JDK 21) on your machine.
- Download the jar file pedsimcity1.23-jar-with-dependencies.jar wherever it is convenient.
- Open the command prompt in the directory where the .jar file is placed.
- Run
java -jar pedsimcity1.23-jar-with-dependencies.jar --cityName=Torino --days=1. - The run starts immediately and logs to the terminal. Add
--websitefor the browser dashboard.
This is the recommended option for running PedSimCity and it does not require the user to take any other step or to manually install the dependencies.
There is no desktop GUI. A run is configured by two things, both of which leave a record it can be reproduced from:
src/main/resources/<City>/<City>.propertiesfor per-city parameters, and--key=valueon the command line for everything else. Resources are read from the classpath, so no path has to be given. For a live view of a run, use the browser dashboard (--website).
To work on the sources in an IDE instead:
- Clone the repository (it uses Git LFS for the GIS data;
git lfs pullif the .gpkg files look like 133-byte text). - Open the folder as a Maven project; the dependencies in
pom.xmlresolve automatically. - Run
mvn -Pall-modules compileto build every module — the default profile builds fewer than half. - Run any launcher's
main:pedsim.night.launcher.NightLauncher,pedsim.activity.launcher.ActivityLauncher,pedsim.core.launcher.CoreLauncher, and so on.
How to run in an editor such as Cursor or VS Code:
- Ensure Maven and Java (JDK 21) are installed on your computer.
- Open the project folder in your editor (e.g. VS Code or Cursor).
- Open the terminal and ensure you are in the project folder with the
pom.xmlfile. - The fastest way to run the simulation after making changes is:
mvn compile exec:java(core) ormvn compile exec:java@night(night module). Both run headless; add@night-websitefor the browser dashboard. Note: Only usemvn clean compile exec:javaif you are experiencing caching issues or have changed your dependencies inpom.xml. Skippingcleanmakes incremental builds much faster. - Alternatively, use your IDE's run button on
NightLauncher.java(pedsim.night.launcher).
The city-image module runs the simulation with three different configurations:
- Testing Landmarks (
London_landmarks, Muenster). - Testing Urban Subdivisions (
London_subdivisions, Paris, Muenster). - Testing Specific Route Choice Models (Muenster).
- Empirical ABM (Muenster).
Each design carries the jobs, numAgents and numberTripsPerAgent used to produce the results in
the papers above, and --stringMode selects between them:
mvn -Pcityimage-empirical compile exec:java \
-Dexec.mainClass=pedsim.cityimage.launcher.CityImageLauncher \
-Dexec.args="--headless --cityName=Muenster --stringMode='Testing Urban Subdivisions'"--numberTripsPerAgent and --jobs override the design's own defaults. For specific
origin-destination pairs, pass --testingSpecificOD=true with --originsTmp and --destinationsTmp
as comma-separated node IDs. Under "Testing Specific Route Choice Models" one agent walks the matrix
per route-choice model.
"Testing Landmarks" needs <City>_distances.csv, which no bundled city currently ships.
core is shared infrastructure: the engine and day loop, routing and path finding, the
cognitive-map machinery, the REST server and dashboard state. It models no behaviour — no census, no
personas, no agendas — so a bare core run releases agents at a flat rate and sends them somewhere
they know; it exists as the skeleton the domain models extend, and as a smoke test. Each module has
its own README under src/main/java/pedsim/<module>/:
| Module | Role |
|---|---|
core |
shared infrastructure: engine, routing, cognition, REST/dashboard |
activity |
activity-based 24h foundation: census home/work, workplace/night POI destinations, day/night clock |
night |
extends activity — vulnerability + lighting-aware night routing |
learning |
extends activity — incremental, decaying cognitive map |
empirical |
extends core — empirical ABM: behaviour calibrated on empirical data |
cityImage |
extends core — route-choice experiments: effect of landmarks / regions / barriers |
The dependency layering is core → activity → {night, learning}; empirical and cityImage extend
core directly. The REST API/dashboard live in core, but /api/modules lists only registered
runnable modules and /api/start routes to them.
Each runnable module has Maven exec profiles (headless run, and REST + browser dashboard); see its README for parameters:
| Module | headless | REST + dashboard |
|---|---|---|
| night (default) | mvn compile exec:java@night |
mvn compile exec:java@night-website |
| activity | mvn compile exec:java@activity |
mvn compile exec:java@activity-website |
| learning | mvn -Plearning compile exec:java@learning |
mvn -Plearning compile exec:java@learning-website |
| cityImage / empirical | mvn -Pcityimage-empirical compile … |
— |
mvn test runs the unit suite (JUnit 5, under a second). Checks that need a city carry
@Tag("slow") and are excluded by default.
| Path | Contents |
|---|---|
src/main/java/pedsim/<module>/ |
Java source, one folder per module (each with a README) |
src/test/java/ |
unit tests; anything needing a city is tagged slow |
scripts/ |
build, publish and dashboard launchers (build_city.bat, publish_site.py, …) |
src/main/resources/<City>/ |
per-city GIS input layers read by the simulation (<City>_*.gpkg) |
inputData/<City>/ |
raw preparation material (DTM/DEM rasters, detailed building layers, source notes); 00_city_preparation.py searches it automatically after the resources folder |
pipeline/ |
Python data-prep scripts + build_lighting*.py orchestrators — see pipeline/README.md |
analysis/ |
Jupyter notebooks + scripts for post-hoc analysis of results |
outputs/ |
all simulation results (gitignored) |
.githooks/ |
Git LFS guard + spotless formatting hooks — copy them in once per clone, see .githooks/README.md |
Code formatting is automatic, once the hooks are installed. Java is formatted with
spotless + google-java-format; pre-commit applies it to
what you staged and pre-push refuses a push that is not clean. mvn spotless:apply does it by
hand. The hooks are not installed by cloning — cp .githooks/pre-commit .git/hooks/ and likewise for
pre-push.
Every launcher prompts for the city; no script names one. A city is a folder under
src/main/resources/ and a <City>_ filename prefix, and that is the only place the name lives.
Preparing a city's data — on Windows double-click scripts/build_city.bat (base layers +
POIs), scripts/build_census.bat (ISTAT census) or scripts/build_lighting.bat (street lighting from
the lamp inventory) and enter the city; or run e.g.
python pipeline/build_lighting.py --city <City>. Raw material goes in
inputData/<City>/; the pipeline writes what the sim reads to src/main/resources/<City>/.
See pipeline/README.md for the steps and the <City>_… filename
conventions.
Results — every run writes under outputs/: structured exports (volumes, routes, cognitive
maps) under outputs/<appName>/, with trip diagnostics and the HTML dashboard at the outputs/
root.
Publishing results — the result pages under outputs/results/ are self-contained HTML.
python scripts/publish_site.py (or scripts/publish_site.bat) stages them into outputs/site/ — an overview
page plus one sub-page per city — and deploys to Cloudflare Pages (project pedsimcity),
served at pedsimcity.inclusivestreets.org, with each
city at pedsimcity.inclusivestreets.org/<City>. Use --no-deploy to only stage the folder
(drag-and-drop it in the Pages dashboard instead), or --open to preview it locally. One-time
toolchain setup (per machine): npm install -g wrangler, wrangler login,
wrangler pages project create pedsimcity; the subdomain is then attached once in the
Cloudflare dashboard (Workers & Pages → pedsimcity → Custom domains). Where wrangler is
installed outside PATH, point $WRANGLER at the executable.
The apex is a second Pages project, deliberately. A Pages project serves the same
deployment on every domain attached to it, so inclusivestreets.org and
pedsimcity.inclusivestreets.org cannot differ inside one project. The umbrella site —
project inclusivestreets, apex + www — is a container that links to the projects under it,
and it lives outside this repository, in ../inclusivestreets/. Nothing here deploys it.
Per-city web data — outputs/site_data/<City>/ is staged to <City>/data/ and published
with the site. It holds the street network as WGS84 GeoJSON
(scripts/export_network_geojson.py) and one aggregated file per season
(scripts/aggregate_season_volumes.py); publish_site.py indexes them into
data/seasons/summary.json and ships scripts/site/seasons.html, the map that reads them, as
<City>/seasons. A city with that data but no exported run page is published for the data
alone.
How to use the Web Dashboard:
PedSimCity features a browser-based dashboard for real-time simulation monitoring via a REST API.
The REST server runs on http://localhost:8081; the dashboard is opened automatically as a local
HTML file (dashboard.html).
To start the night-module REST server and dashboard:
mvn compile exec:java@night-websiteWhen the startup menu appears, select Option 2 (Browser/HTML Dashboard). The REST API starts
on port 8081 and dashboard.html opens in your browser automatically.
Endpoints available once the server is running:
| Endpoint | Description |
|---|---|
GET /api/state |
Live simulation state (agents, stats, module info) |
GET /api/roads |
GeoJSON road network |
GET /api/modules |
Registered runnable modules with parameter schemas |
POST /api/start |
Start a simulation run (body: {"module":"night","cityName":"Torino",…}) |
To start a simulation from the command line once the server is running:
curl -X POST http://localhost:8081/api/start \
-H "Content-Type: application/json" \
-d '{"module":"night","cityName":"Torino","days":1}'