Documentation
Navigation Build and Deployment
Source:
docs/navigation_deployment.md
OpenRoadCode deliberately separates navigation software, vehicle-local configuration, and large generated map/routing data. This allows the vehicle computer to remain a lean runtime target while a separate build machine performs expensive map generation.
Filesystem contract
/opt/openroadcode/navigation/
installed software
├── bin/openroadcode-map-renderer
└── valhalla/
/etc/openroadcode/
navigation.toml
/srv/openroadcode/
build-manifest.json
maps/
├── search/openroadcode-search.sqlite
├── vector/openroadcode.mbtiles
└── styles/openroadcode.json
valhalla/
Ownership by purpose:
| Path | Owner/purpose |
|---|---|
/opt/openroadcode/navigation |
Installed navigation executables and libraries |
/etc/openroadcode/navigation.toml |
Vehicle-local runtime configuration |
/srv/openroadcode |
Versioned/deployable map and routing dataset |
/srv/openroadcode-update |
Temporary incoming dataset on the vehicle |
/srv/openroadcode-previous |
Previous dataset retained for rollback |
Map updates must not overwrite /etc/openroadcode.
Architecture
flowchart LR
subgraph build["Map build machine"]
osm["Geofabrik OSM extracts"] --> builder["tools/map_builder<br/>MBTiles + styles/glyphs + Valhalla tiles<br/>validation + build-manifest.json"]
end
builder -->|"SSH + rsync<br/>initiated by vehicle"| update["/srv/openroadcode-update"]
subgraph vehicle["Vehicle / Raspberry Pi"]
update --> validate["Validate"] --> promote["Atomic-ish promotion<br/>/srv/openroadcode"]
promote --> restart["Restart Valhalla"]
restart --> health{"Healthy?"}
health -->|yes| active["Updated navigation data active"]
health -->|no| rollback["Rollback"]
end
classDef orcApp fill:#dbeafe,stroke:#2563eb,color:#172554;
classDef orcService fill:#ede9fe,stroke:#7c3aed,color:#2e1065;
classDef orcController fill:#dcfce7,stroke:#16a34a,color:#14532d;
classDef orcMessage fill:#ffedd5,stroke:#ea580c,color:#7c2d12;
classDef orcAdapter fill:#fee2e2,stroke:#dc2626,color:#7f1d1d;
classDef orcExternal fill:#f3f4f6,stroke:#6b7280,color:#1f2937;
class osm orcExternal;
class builder,validate orcController;
class update,promote,restart,rollback orcService;
class active orcApp;
The map-build machine is the authoritative producer of navigation data. The vehicle controls when it consumes a new dataset.
1. Install navigation software on the vehicle
From the OpenRoadCode repository on the Raspberry Pi:
./scripts/installers/install_navigation_stack.sh --target rpi5
Preview without modifying the system:
./scripts/installers/install_navigation_stack.sh --target rpi5 --show-plan
The installer builds/installs MapLibre Native integration, the OpenRoadCode native renderer, and Valhalla software beneath /opt/openroadcode/navigation.
Chromium is not a navigation dependency. The Linux navigation installer uses
the native MapLibre renderer; add the separate browser feature only for
browser-backed OpenRoadCode applications.
It does not build map data. Map generation belongs on the map-build machine.
The installer seeds /etc/openroadcode/navigation.toml from config/navigation.toml only when the deployed file does not already exist. Existing local configuration is preserved.
If Valhalla map data are not present yet, service installation is deferred until data have been deployed.
2. Build map/routing data on the build machine
From tools/map_builder:
./scripts/build-image.sh
./scripts/run-builder.sh build --regions north-america/us/michigan
Or select regions interactively:
./scripts/run-builder.sh tui
Successful output is written under tools/map_builder/build-output/ using the same /srv/openroadcode paths expected by the vehicle.
The builder validates its output and writes build-manifest.json. A dataset without that manifest is not considered deployable.
See tools/map_builder/README.md for builder details and toolchain pinning.
3. Publish the dataset on the build machine
The vehicle pull script expects an SSH/rsync-readable directory containing the contents of the generated /srv/openroadcode tree.
A simple deployment on the build machine is:
cd tools/map_builder
./scripts/deploy-to-srv.sh
This makes /srv/openroadcode on the build machine the published dataset root.
SSH key authentication is recommended for unattended vehicle pulls. The vehicle only needs read access to the published tree.
4. Pull map data from the vehicle
First preview the transfer:
./scripts/runtime/pull_navigation_data.sh \
--source mapbuilder@MAP_HOST:/srv/openroadcode \
--dry-run
Then deploy:
./scripts/runtime/pull_navigation_data.sh \
--source mapbuilder@MAP_HOST:/srv/openroadcode
The updater:
- reads the remote
build-manifest.jsonbefore transfer; - skips the update when the local and remote manifests already match;
- downloads into
/srv/openroadcode-update; - preserves vehicle-owned
maps/routes/data; - validates the staged deployment contract, including the POI search index;
- verifies that the staged manifest is the same manifest checked before transfer;
- moves the previous dataset to
/srv/openroadcode-previous; - promotes the staged dataset to
/srv/openroadcode; - restarts Valhalla when its service is installed;
- restores the previous dataset if Valhalla fails after promotion.
Useful options:
--dry-run preview rsync changes
--force pull even when manifests match
--no-restart do not restart Valhalla after promotion
The source can also be provided through NAVIGATION_DATA_SOURCE.
Runtime renderer configuration
/etc/openroadcode/navigation.toml selects runtime behavior without changing the deployed dataset:
[map_renderer]
style = "/srv/openroadcode/maps/styles/openroadcode.json"
cache = "/var/cache/openroadcode/maplibre.db"
[vehicle_marker]
mode = "vehicle"
scale = 1.0
Supported marker modes are blue_dot, heading, and vehicle. Marker selection is local configuration; the style definitions themselves travel with the map package.
The intended vehicle presentation is a top-down red Hyundai Veloster. Until that artwork is added to the map/style asset package, the style uses a red placeholder marker.
Updating marker choice
Edit the vehicle-local config:
sudo editor /etc/openroadcode/navigation.toml
For example:
[vehicle_marker]
mode = "blue_dot"
scale = 1.0
Restart the renderer after changing startup configuration.
Validation and troubleshooting
Before first use after pulling repository changes:
bash -n scripts/installers/install_navigation_stack.sh
bash -n scripts/runtime/pull_navigation_data.sh
python3 -m pytest tools/map_builder/tests -v
Useful runtime checks on the vehicle include:
test -x /opt/openroadcode/navigation/bin/openroadcode-map-renderer
test -s /etc/openroadcode/navigation.toml
test -s /srv/openroadcode/build-manifest.json
test -s /srv/openroadcode/maps/styles/openroadcode.json
test -s /srv/openroadcode/maps/search/openroadcode-search.sqlite
test -s /srv/openroadcode/valhalla/valhalla.json
systemctl status valhalla.service
If a data promotion causes Valhalla to fail, pull_navigation_data.sh attempts automatic rollback. /srv/openroadcode-previous also provides an administrator-visible copy of the previous successful dataset until the next promotion.
Design rules
- Build expensive map/routing data off-vehicle.
- Install executable software under
/opt. - Keep machine/vehicle configuration under
/etc. - Keep generated navigation data under
/srv. - Do not bake region names such as
michigan-testinto renderer code. - Do not let map-data synchronization overwrite vehicle-local configuration.
- Treat
build-manifest.jsonas the deployment identity and validation boundary. - Preserve runtime-generated route/debug data across map updates.