https://github.com/electrified/sheffield-supertram-simulator
https://github.com/electrified/sheffield-supertram-simulator
Last synced: 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/electrified/sheffield-supertram-simulator
- Owner: electrified
- Created: 2026-03-17T10:19:12.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-03-21T23:50:30.000Z (3 months ago)
- Last Synced: 2026-03-22T01:32:42.099Z (3 months ago)
- Language: C#
- Size: 4.42 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Sheffield Supertram Simulator
A Unity 6.3 LTS driving simulator for the Sheffield Supertram light rail network, using real-world terrain (Ordnance Survey) and route data (OpenStreetMap).
## Prerequisites
- **Unity 6000.3.x** (Unity 6.3 LTS) with Universal Render Pipeline
- **Python 3.10+** with venv
- **GDAL CLI tools**: `gdalbuildvrt`, `gdal_translate`, `gdalwarp`, `gdalinfo`
- **jq** (JSON processor)
Install GDAL and jq on Arch Linux:
```bash
sudo pacman -S gdal jq
```
## Quick Start
### 1. Set up Python environment
```bash
python3 -m venv .venv
.venv/bin/pip install -r tools/requirements.txt
```
### 2. Download and process terrain data
Download **OS Terrain 50** (ASCII Grid format) from:
https://osdatahub.os.uk/downloads/open/Terrain50
Extract the needed tile `.asc` files into `data/terrain_tiles/`. The required tiles are: SK28, SK29, SK38, SK39, SK48, SK49.
If you downloaded the full UK zip:
```bash
mkdir -p data/terrain_tiles
for tile in sk28 sk29 sk38 sk39 sk48 sk49; do
unzip -o -j "data/terrain_tiles/sk/${tile}_OST50GRID_*.zip" "*.asc" -d data/terrain_tiles/
done
```
Then run the terrain pipeline:
```bash
bash tools/terrain_pipeline.sh
```
This produces:
- `data/sheffield_terrain.raw` — 16-bit unsigned RAW heightmap (4097x4097)
- `data/terrain_metadata.json` — dimensions, elevation range, Unity settings
### 3. Fetch and process OSM data
```bash
# Fetch raw data from Overpass API (takes a few minutes, respects rate limits)
.venv/bin/python3 tools/fetch_osm.py
# Process into game-ready formats
.venv/bin/python3 tools/osm_to_json.py
```
This produces:
- `data/tram_routes.json` — route waypoints with Unity coordinates
- `data/stations.json` — all 50+ tram stops with Unity coordinates
- `data/buildings.geojson` — building footprints near tram routes
- `data/roads.geojson` — road centrelines near tram routes
- `data/road_network.json` — road network for detail zones
### 4. Import into Unity
Open the project in Unity, then either:
**GUI method:**
1. `Window > Sheffield Supertram > Import Terrain` — imports the heightmap
2. `Window > Sheffield Supertram > Import Routes` — imports tram routes and stations
**Batch method (command line):**
```bash
# Remove stale lock file if Unity isn't running
rm -f Temp/UnityLockfile
# Full import: terrain + scene setup + routes
Unity -projectPath . -executeMethod FullImport.Run -batchmode -quit -logFile -
```
Or run individual steps:
```bash
# Terrain + scene setup only
Unity -projectPath . -executeMethod BatchSetup.Run -batchmode -quit -logFile -
# Routes only (requires terrain scene to exist already)
Unity -projectPath . -executeMethod RouteImporter.BatchImport -batchmode -quit -logFile -
```
### 5. Open the scene and play
1. Open `Assets/Scenes/DevScene.unity`
2. Press Play — a test cube will follow the first tram route automatically
3. Use the **Dev Camera** (free-fly) to explore:
- **WASD** — move horizontally
- **Q/E** — move down/up
- **Right-click + mouse** — look around
- **Shift** — move faster
- **Scroll wheel** — adjust movement speed
## Tools Reference
| Tool | Purpose |
|------|---------|
| `tools/terrain_pipeline.sh` | Process OS Terrain 50 `.asc` tiles into Unity RAW heightmap |
| `tools/fetch_osm.py` | Download tram routes, stations, buildings, roads from OpenStreetMap |
| `tools/osm_to_json.py` | Convert raw OSM data into game-ready JSON and GeoJSON |
| `tools/coord_utils.py` | Coordinate conversion utility (WGS84 / OSGB36 / Unity) |
| `tools/config.json` | Central configuration for all pipeline parameters |
### Coordinate conversion examples
```bash
# WGS84 lat/lon to Unity coordinates
.venv/bin/python3 tools/coord_utils.py --lat 53.3826 --lon -1.4691 --unity
# OSGB36 easting/northing to Unity coordinates
.venv/bin/python3 tools/coord_utils.py --easting 435850 --northing 387100 --unity
# Run self-test
.venv/bin/python3 tools/coord_utils.py --test
```
## Coordinate System
- **OSGB36 / EPSG:27700** (British National Grid) — metres
- Unity axes: **X** = Easting, **Z** = Northing, **Y** = Up
- Origin: terrain SW corner (E 431000, N 380000) = Unity (0, 0, 0)
- Terrain extent: 15,000m x 15,000m (E 431000–446000, N 380000–395000)
- Elevation range: ~17m (Don Valley) to ~280m (western hills)
## Project Structure
```
README.md This file
PLAN.md Full implementation plan (13 milestones)
CLAUDE.md Project conventions for AI assistants
tools/
config.json Pipeline configuration (bounding box, tiles, zones)
terrain_pipeline.sh GDAL terrain processing pipeline
fetch_osm.py OSM data downloader (Overpass API)
osm_to_json.py OSM data processor
coord_utils.py Coordinate conversion (pyproj)
requirements.txt Python dependencies
data/
terrain_tiles/ OS Terrain 50 .asc source files (not in git)
intermediate/ GDAL intermediate files (not in git)
osm_raw/ Raw Overpass API responses
sheffield_terrain.raw Unity heightmap (generated)
terrain_metadata.json Terrain dimensions and settings (generated)
tram_routes.json Tram route waypoints (generated)
stations.json Tram station positions (generated)
buildings.geojson Building footprints (generated)
roads.geojson Road centrelines (generated)
Assets/
Editor/
BatchSetup.cs Batch terrain import + scene setup
RouteImporter.cs Batch route/station import
FullImport.cs Combined terrain + routes import
TerrainSetup.cs GUI terrain importer
SceneSetup.cs GUI scene setup
URPSetup.cs URP pipeline configuration
Scripts/
Tram/
TrackSegment.cs Spline wrapper with length, gradient, stations
TramRoute.cs Ordered list of track segments
SplineFollower.cs Moves transform along a route
TrackMeshGenerator.cs Generates visible track mesh from spline
Junction.cs Track junction switching
StationMarker.cs Station metadata component
Camera/
FreeFlyCamera.cs Developer fly camera (WASD + mouse)
Scenes/
DevScene.unity Main development scene
.venv/ Python virtual environment (not in git)
```
## Vehicle Profiles
Vehicle physics are configurable via ScriptableObject profiles, editable in the Unity Inspector. Create new profiles via **Create > Sheffield Supertram** in the Project window.
| Profile Type | Used By | Key Parameters |
|---|---|---|
| **Tram Profile** | `TramPhysics`, `TramArticulation` | Mass, power, max speed, braking forces, rolling/aero resistance, bogie geometry |
| **Car Profile** | `CarPhysics` | Torque, max speed, braking forces, steering angle |
| **AI Car Profile** | `AICarController` | Raycast interval/distances, stuck detection thresholds, speed variation |
Assign a profile to the `profile` field on the relevant component. If no profile is assigned, built-in defaults are used (matching the real Siemens-Duewag Supertram specs for trams, and sensible defaults for cars). This means existing scenes work unchanged.
To create a variant (e.g. a heavier loaded tram):
1. **Create > Sheffield Supertram > Tram Profile**
2. Adjust values in the Inspector
3. Assign to the `TramPhysics` and `TramArticulation` components on your tram
## Data Attribution
- Terrain: [OS Terrain 50](https://osdatahub.os.uk/downloads/open/Terrain50) — Open Government Licence v3.0
- Routes, stations, buildings, roads: [OpenStreetMap](https://www.openstreetmap.org/) — ODbL