Skip to content

travelCalculatorObject

Configures the travel calculator Spiral uses to refine journey times and distances across the topography — an external routing engine such as OSRM. Without one, Spiral uses its own estimate: the straight line, scaled by the topography’s fractalDimension and referenceTravel and the urban zones it crosses.

{
"path": <string>,
"run": <string[]>,
"speedFactor": <real>,
}
path string
Directory the engine and its arguments resolve against. "./" is Spiral's own run directory, which holds the engine and the road data (see below).
run string[]
The engine and its arguments. For spiralTravelOSRM.l64 the first argument is the data file without its .osrm extension; -l names the engine's log, -t the number of worker threads, -d the log level.
trafficPrediction bool default false
Send the time of day with each request. Off, requests carry no time ("@":-1) and a drive costs the same whenever it is made.
maximumRouteDistance distance
The longest drive the engine is asked for.
speedFactor real default 1.0
A drive the engine answers becomes its duration ÷ speedFactor, so a factor below 1 lengthens every refined drive. This is not the resource type's speedFactor, which scales Spiral's own estimate.

Spiral plans on its own estimate and asks the engine for the drives it is weighing: the open stops, and a resource’s drive to a stop another resource already holds. Each answer is kept in the travel cache, and a stop that has not started takes the refined value (tvl ≈ duration ÷ speedFactor). A stop already deployed, heading, committed or arrived keeps the drive it was started on; the refined answer serves the next comparison, which is how the engine corrects future plans without disturbing the plan in progress. Requests are answered asynchronously (-t), so a plan made just after a position update is on Spiral’s own estimate until the engine replies.

Choosing speedFactor. In a comparison of 1,000 drives of 5–120 km across the UK, Spiral’s own estimate matched OSRM’s raw duration within 1% for drives over 50 km and exceeded it under 25 km (by 1.4–1.6×, the straight line at a zone speed against a town’s roads). The factor therefore sets the whole relationship between the two: at 0.95 the median refined drive is within 2% of Spiral’s own and 45% of refined drives are inside it; at 1.10, 80% are inside. A factor well below 1 makes every refined drive longer than the estimate it replaces, which favours moving work from the resource heading to a stop onto one whose drive is still estimated.

A Helix node passes the travel calculator to Spiral through the SPIRAL_TRAVEL_CALCULATOR environment variable, and your domain file includes it. Put this line in <Client>.domain.json:

{"include":{"environment":"SPIRAL_TRAVEL_CALCULATOR"}},

Helix doesn’t include the variable itself. Your domain does it, so Spiral gets the same instructions whether Helix drives it or your own system feeds it directly. Once the domain includes it, the variable must be set; use '{}' to run without a travel calculator.

The OSRM interface, spiralTravelOSRM.l64, is part of the Helix core. The preprocessed road network it reads is published separately: one image per country, at registry.gitlab.com/honeywick-consulting/helix/osrm:<country>-latest.

Spiral always runs in a working directory that holds spiralTravelOSRM.l64 and an osrm/<country> folder for each country on the machine. Use paths relative to it, and the same value works in a container, on a server without containers, and in the test harness:

Terminal window
export SPIRAL_TRAVEL_CALCULATOR='{"set":{"travelCalculator":{"path":"./",
"run":["spiralTravelOSRM.l64","osrm/united-kingdom/united-kingdom",
"-lspiralTravelCalculatorOSRM.err.json","-t4","-d1"],
"trafficPrediction":false,"maximumRouteDistance":"500km","speedFactor":0.95}}}'

The first argument after the binary is the data file, without its .osrm extension. The travel engine’s own log (-l…) is kept with the node’s logs.

helixctl pull (and helixctl install) fetches the latest data for every country named this way. Each start then makes it available read-only. If the data is not on the machine, the node refuses to start and asks you to run helixctl pull. helixctl check lists each country with the version in use. helixctl osrm fetches the data on its own, without pulling a core.

Each machine keeps one copy of each country’s data in a shared OSRM area, used by every Helix account and every container on that machine. helixctl downloads the image, unpacks it into the area, and then deletes the image, so the data is not stored twice. A pull asks the registry whether anything changed before downloading, so an unchanged country costs nothing.

The area keeps two versions per country: the one in use, and the one before it. A container started before an update keeps using the version it started with until it restarts. Set HELIX_OSRM_KEEP to keep more or fewer.

On a server with several Helix accounts, create the area once, as root, owned by a group those accounts share, and point every account at it:

Terminal window
install -d -m 2775 -g <group of the Helix accounts> /srv/helix-osrm
export HELIX_OSRM_DIR=/srv/helix-osrm # in each account's environment

Without HELIX_OSRM_DIR, each account keeps its own area in ~/HelixRuntime/osrm, which suits a single-user machine. This works with any podman 4+ or docker version Helix supports.

Countries currently published:

CountrySource (Geofabrik)
united-kingdom (England, Scotland, Wales, Northern Ireland)europe/united-kingdom

The data is rebuilt from the latest Geofabrik extract when a new Helix core is released.