Turn-by-Turn Routing
Offline vehicle navigation powered by Valhalla and OpenStreetMap.
7 min readOverview
GroundWave provides offline turn-by-turn navigation using
Valhalla, an open-source routing
engine that runs on OpenStreetMap (OSM) data. The routing engine runs as an optional
Docker container (groundwave-router) and supports vehicle, bicycle, and
pedestrian profiles.
Key design decisions:
- Fully offline — once OSM PBF data is imported and tiles are built, routing works without any internet connection.
-
Optional container — enabled via Docker Compose profiles
(
--profile router). Not started by default. -
Feature toggle gated — routing UI only appears when
routingis inFEATURES_ENABLEDand the Valhalla engine reports ready status. - Server-side proxy — the GroundWave app server proxies route requests to Valhalla, adding authentication and RBAC enforcement.
Setup
1. Enable the Router Container
Start GroundWave with the router profile to include the Valhalla container:
# Start with routing enabled
docker compose --profile router up -d
# Or add to your existing docker-compose command
docker compose -f docker-compose.yml --profile router up -d
2. Import OSM Data
Download an OpenStreetMap PBF extract for your region from Geofabrik or Protomaps, then import it via the Admin Dashboard.
- Open the Admin Dashboard and navigate to the Routing tab.
- Click Import PBF and select your
.osm.pbffile. - Wait for the upload and tile building to complete. The status will show progress.
- Once tiles are built, the routing engine is ready. Routes can be requested immediately.
PBF file size determines import time and disk usage. A state-level extract (e.g., Colorado, ~300 MB) takes a few minutes. A country-level extract can take longer. The Nginx proxy allows uploads up to 5 GB with a 30-minute timeout.
3. Enable the Feature Toggle
Add routing to the FEATURES_ENABLED environment variable:
# .env or docker-compose.yml environment
FEATURES_ENABLED=chat,markers,files,overlays,voice,video,routing
Vehicle Profiles
Three routing profiles are available, each optimized for different travel modes:
- Auto — vehicle routing using roads, highways, and motorways. Respects turn restrictions, one-way streets, and road classifications.
- Bicycle — cycling routes preferring bike lanes, paths, and low-traffic roads. Avoids highways and motorways.
- Pedestrian — walking routes using sidewalks, footpaths, trails, and crosswalks. Can traverse pedestrian-only areas.
The profile can be switched at any time from the RoutePanel. Changing profiles automatically re-requests the route with the new travel mode.
User Interface
"Route to" Actions
"Route to" buttons appear alongside "Navigate to" throughout the interface:
- User markers — route to another team member's position
- Markers — route to a marker (uses centroid for polygons/lines)
- Roster panel — route to a user from the roster list
RoutePanel
The RoutePanel is a slide-out panel that appears when a route is active. It contains:
- Profile selector — switch between auto, bicycle, and pedestrian
- Route summary — total distance and estimated travel time
- Turn-by-turn instructions — step-by-step maneuver list with distance to each turn
- Cancel route — clear the active route
ManeuverHUD
While a route is active, a floating ManeuverHUD overlay appears on the map showing the next upcoming maneuver — direction, street name, and distance to the turn. The HUD automatically advances as you progress along the route.
Route Layer
The route is rendered on the map as a blue route line with a darker casing for contrast. Start and end markers indicate the route endpoints. The line follows the actual road geometry returned by Valhalla.
Auto-Reroute
When your GPS position deviates more than 50 meters from the route line, the system automatically requests a new route from your current position to the original destination. This ensures the instructions stay relevant even if you take a different path.
REST API
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/route |
Any authenticated | Request a route between two points |
GET |
/api/route/status |
Any authenticated | Check routing engine status (ready, building, unavailable) |
POST |
/api/route/admin/import |
Admin | Upload OSM PBF file for tile building |
GET |
/api/route/admin/status |
Admin | Detailed import/tile build status |
DELETE |
/api/route/admin/data |
Admin | Delete imported routing data |
Permissions
| Capability | Observer | Operator | Admin |
|---|---|---|---|
| Request routes | Yes | Yes | Yes |
| View routing status | Yes | Yes | Yes |
| Import PBF data | No | No | Yes |
| Delete routing data | No | No | Yes |
Admin Dashboard
The Routing tab in the Admin Dashboard provides data management:
- Status indicator — shows whether the Valhalla engine is ready, building tiles, or unavailable
- Import PBF — upload an OpenStreetMap PBF extract
- Build progress — real-time status during tile building
- Delete data — remove imported routing data and tiles
The Valhalla container uses an entrypoint script with MD5-based skip logic — if the same PBF file is re-imported, tile building is skipped automatically. The container restarts after a PBF import to load the new tiles.