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.
-
pathstring - Directory the engine and its arguments resolve against. "./" is Spiral's own run directory, which holds the engine and the road data (see below).
-
runstring[] - 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.
-
trafficPredictionbooldefaultfalse - Send the time of day with each request. Off, requests carry no time ("@":-1) and a drive costs the same whenever it is made.
-
maximumRouteDistancedistance - The longest drive the engine is asked for.
-
speedFactorrealdefault1.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.
How Spiral uses the engine
Section titled “How Spiral uses the engine”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.
OSRM on a Helix node
Section titled “OSRM on a Helix node”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:
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.
Where the data is kept
Section titled “Where the data is kept”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:
install -d -m 2775 -g <group of the Helix accounts> /srv/helix-osrmexport HELIX_OSRM_DIR=/srv/helix-osrm # in each account's environmentWithout 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:
| Country | Source (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.