Skip to content

Installation

This guide covers what Valdrada needs, how to install it on Windows and on Linux, how to run it on a Linux server without a display, the errors people meet most often, and how to build the release archive. For the shortest path to a first frame, see the quick start.

Requirements

Component Requirement
GPU WebGL2 through Direct3D 11 (Windows) or Vulkan (Linux); a discrete GPU is recommended. The server used about 3 GB of GPU memory at 1280 × 720. Tested on an NVIDIA RTX 3060 Laptop GPU (Windows 11) and an RTX 6000 Ada (Ubuntu 22.04)
Driver A current vendor driver. On Linux the NVIDIA driver must provide its Vulkan ICD (tested with driver 580)
Memory 16 GB of RAM; the page's JavaScript heap may grow to 8 GB
Disk Release archive 2.0 GB, 4.3 GB extracted. Source checkout with the downloaded tiles, models and textures 3.8 GB more; compiling the tiles needs about 2.4 GB of raw downloads
Node.js 22.12 or later with npm, for a source checkout and for the Linux server (tested with 24.19)
Python 3.8 or later for the valdrada package; numpy is optional and used by most examples
Downloads huggingface_hub 1.0 or later for the hf command: pip install -U "huggingface_hub>=1.0"

The Python package has no required dependencies and runs on any machine that can reach the server over TCP.

Windows

Release. Download Valdrada-0.3.1-win64.zip from the releases page and extract it anywhere. The folder contains:

Path Contents
Valdrada.exe the server: a window, or no window with --headless; TCP API on port 2000
StartServer.bat, StartServer_Headless.bat launchers that pass their arguments on to Valdrada.exe
Content/ the built client and the compiled city
PythonAPI/ the valdrada package (source and wheel) and the examples
Docs/ getting started, the Python API reference and the wire protocol

Start the server by double-clicking StartServer.bat, or from a terminal with options:

Valdrada.exe --port 2000 --res 1280x720 --time day --pedestrians procedural

Install the Python package from the same folder:

pip install PythonAPI\dist\valdrada-0.1.0-py3-none-any.whl numpy

On laptops with two GPUs the server requests the discrete one. If Windows asks whether Valdrada.exe may use the network, local connections work without allowing it; allow it only to accept clients from other machines (--host 0.0.0.0).

Source. Install Node.js 22.12 or later and Git for Windows, then follow option B of the quick start in Git Bash.

Linux

The release archive contains a Windows executable only. On Linux the server runs from a source checkout: npm installs the Electron runtime, which loads either the release's built Content/ or a development server.

git clone https://github.com/mkturkcan/valdrada.git
cd valdrada
(cd server && npm install)
ls server/node_modules/electron/dist/electron        # the runtime; if missing: (cd server && node node_modules/electron/install.js)
pip install -U "huggingface_hub>=1.0"
hf download mehmetkeremturkcan/valdrada --repo-type dataset --revision v0.3.1 --include "Content/*" --local-dir .
cd server
env -u ELECTRON_RUN_AS_NODE npx electron . --content ../Content

The arguments after . are the server's options (port, resolution, time of day; see below) and Chromium flags. To work on the code instead, install the client as in option B of the quick start and pass --dev-url=http://127.0.0.1:5219 instead of --content ../Content.

Running headless on a Linux server

A server without a display runs the same command with Chromium's headless platform and ANGLE on Vulkan. The GPU still renders every frame.

cd server
nohup env -u ELECTRON_RUN_AS_NODE npx electron . --content ../Content --headless \
    --ozone-platform=headless --use-angle=vulkan --enable-features=Vulkan \
    --port 2000 --res 1280x720 --pedestrians procedural > server.log 2>&1 &

What you should see in server.log: listening on 127.0.0.1:2000 at once, then world ready in 52.9 s (api 0.1.0) or similar. A line vkCreateInstance() failed: -7 may appear before it; it is harmless when the check below names your GPU. To confirm that the GPU renders:

python -c "import valdrada; print(valdrada.Client('127.0.0.1', 2000).get_server_info()['gpu'])"

The answer should name the GPU, for example ANGLE (NVIDIA, Vulkan 1.4.312 (NVIDIA NVIDIA RTX 6000 Ada Generation ...)). SwiftShader means the page fell back to software rendering, which works but is far too slow for data collection; check the driver's Vulkan support (vulkaninfo --summary).

Choosing a GPU. On a machine with several GPUs, Chromium takes the first Vulkan device in the list of the Mesa device-select layer. DRI_PRIME with the PCI address of a GPU puts that GPU first:

nvidia-smi --query-gpu=index,pci.bus_id --format=csv,noheader     # e.g. "0, 00000000:01:00.0"
DRI_PRIME=pci-0000_01_00_0 nohup env -u ELECTRON_RUN_AS_NODE npx electron . --content ../Content --headless \
    --ozone-platform=headless --use-angle=vulkan --enable-features=Vulkan --port 2000 > server.log 2>&1 &

Several servers can share a machine with different --port values, one GPU each.

Clients on other machines. The API has no authentication. Prefer an SSH tunnel from the client machine, ssh -N -L 2000:127.0.0.1:2000 user@server, and connect to 127.0.0.1:2000. --host 0.0.0.0 accepts connections from any address and is only for trusted networks.

Stopping. kill <pid> with the process id that nohup printed (or pgrep -af "electron . --content").

Server options

Option Default Meaning
--port, --host 2000, 127.0.0.1 the API socket
--res WxH 1280x720 render size, and the size of every RGB camera
--time day day, golden, dusk or night at start
--quality high medium renders cheaper frames
--start-lat, --start-lon 40.80955, -73.95905 where the city streams in first (W 120th St and Amsterdam Ave)
--pedestrians photoreal procedural uses the built-in pedestrians. Use it for datasets and for training or testing models: the photoreal set contains MetaHuman-derived components whose licence forbids those uses (licensing)
--headless off no window
--content DIR Content/ next to the executable the built client and the city to serve
--dev-url=URL load the client from a development server; a URL must use the = form
--log FILE, --verbose write the server log to a file; print the page's messages

Common errors

Symptom Cause and fix
ConnectionError: no Valdrada server on 127.0.0.1:2000 The server is not running, listens on another port, or a firewall blocks the port. Check the server log for listening on.
TimeoutError: the server did not finish loading within 300 s The first start compiles shaders; start the client again once the server log shows world ready. If it never does, check the GPU (see above) and run with --verbose.
Electron prints Node.js output or exits at once ELECTRON_RUN_AS_NODE is set in the environment (some editors set it in their terminals). Start with env -u ELECTRON_RUN_AS_NODE (Linux, Git Bash) or set ELECTRON_RUN_AS_NODE= first (Windows cmd); the release launchers clear it.
server/node_modules/electron/dist/ is missing after npm install npm skipped Electron's install script: run node node_modules/electron/install.js in server/.
Electron exits with an error about a missing shared library Install the system package that provides that library (the usual Chromium runtime libraries).
The server window shows the wrong page, or --dev-url is ignored The URL was passed as --dev-url http://...; Chromium opens a bare URL as a page. Use --dev-url=http://127.0.0.1:5219.
KeyError: "no blueprint 'walker.pedestrian.0003'" The server runs with --pedestrians procedural, which has one walker blueprint. Pick walkers with lib.filter("walker.pedestrian.*").
TimeoutError: world.tick: no answer from the simulator within 60 s Many or large label cameras make a step slow. Raise the limit with client.set_timeout(120.0).
TypeError: float() argument must be a string or a real number, not 'NoneType' right after set_autopilot(True) A defect of the 0.2.0 server, fixed in 0.2.1: a vehicle spawned through the API lost its position when switched to autopilot. Use the 0.2.1 release or the current source; with 0.2.0, drive API vehicles with apply_control.
hf: command not found pip install -U "huggingface_hub>=1.0"; older versions call the command huggingface-cli.
The client shows an empty city, the browser console lists 404s for /tiles/ The tiles, models and textures are not in client/public/: repeat the download and the mv of option B.
JavaScript heap out of memory while compiling the tiles Give Node more memory: NODE_OPTIONS=--max-old-space-size=6144 npm run compile -- --boro 1,2,3,4.
Address already in use Another server holds the port: pick another with --port.

Building the release archive

server/build.mjs assembles the release folder: it packages the Electron server, runs the production build of the client into Content/ with every runtime asset, copies PythonAPI/ and builds its wheel when uv is installed, and writes the launchers, Docs/ and the legal files. It needs the compiled tiles in client/public/tiles/, npm install in the top folder, client/ and server/, and access to github.com, from which the packager downloads the Electron runtime of the target platform.

node server/build.mjs --platform win32 --link --zip
Option Effect
--platform win32 or linux the target; linux builds a Linux x64 server, which has not been tested for a release
--link hardlink Content/ instead of copying it (same volume only)
--skip-content keep Content/ from the previous build
--zip also write release/Valdrada-<version>-<platform>.zip
--out DIR the output directory (default release/)

For 0.2.0 the folder held 4,689 files (4.3 GB) and the archive was 2,050,959,101 bytes. GitHub accepts release assets up to 2 GiB, so watch the size when the city grows. To check a Windows build on Linux, serve its Content/ with the Linux runtime, as in the headless section, and run an example against it.