What a walk actually costs: hills, and calories
Status: built and live, 2026-08-19. Figures below are measured on this system.
A journey planner will happily offer you two routes that take the same number of minutes, draw them as the same blue line, and never mention that one of them walks you up a hundred and seventy metres of Sheffield. This is the part of a walk a duration cannot express, so the planner now says it outright.
Two numbers now appear on every itinerary: how much climbing the walking legs involve, and roughly what they cost in energy.
Where the ground heights come from
OS Terrain 50 — Ordnance Survey's open terrain model, 50 metre postings, Open Government Licence. Bare earth, which is the reason it was chosen over the finer Copernicus 30 m model: Copernicus is a surface model, so in a city its "gradient" is substantially the height of buildings and trees, which nobody walks over.
The national download is 2,800 zipped ASCII tiles on the British National
Grid. build_elevation.py reduces the planner's own rectangle to a single
array of int16 decimetres on a plain latitude/longitude grid: 2,067 x 2,001
cells, 8.3 MB, every cell carrying a height. Heights are stored in decimetres
rather than metres because the whole point is gradient, and rounding to the
nearest metre puts a 2% error into the slope of every 50 m cell.
Spot checks against published heights: Holme Moss summit reads 524.5 m against a published 524 m, Emley Moor 257.7 m, Doncaster station 12.0 m, Sheffield city centre 80.2 m.
The 27-metre trap
Converting latitude and longitude to the National Grid with the Helmert approximation — the seven-parameter shift most code reaches for, including PROJ's own fallback — is a flat 27 metres out across Yorkshire. That is half a cell of the model it is sampling, enough to read a slope off the wrong side of a street, and it is invisible in the output: every height is still a plausible height.
The build therefore insists on OSTN15, Ordnance Survey's official transformation, and refuses to run without the grid shift file rather than producing a plausible, uniformly wrong model. The projection happens once, at build time; the file the site reads is plain latitude and longitude, so nothing in the serving path does any geodesy at all.
How the energy is worked out
Not a MET table. The familiar "walking is 3.5 METs" figure has no term for gradient, which is the entire question here. The model is Minetti's measured cost of walking against slope, in joules per kilogram per metre travelled:
Cw(i) = 280.5 i^5 - 58.7 i^4 - 76.8 i^3 + 51.9 i^2 + 19.6 i + 2.5
It has the two properties anyone who walks a hilly city will recognise, and that a linear model gets wrong: going down costs less than the flat but never nothing, and the cheapest gradient is a gentle downhill of about -10% rather than level ground.
| gradient | cost (J/kg/m) |
|---|---|
| -30% | 2.21 |
| -20% | 1.09 |
| -10% | 1.13 |
| 0% | 2.50 |
| +10% | 4.90 |
| +20% | 7.88 |
| +30% | 11.18 |
Each 25 m of a walk is charged at its own gradient rather than at the leg's average, so a route that goes up and back down is not scored as if it were flat. Resting metabolism is added over the leg's duration, so the figure is comparable with what a fitness tracker would show. Body mass is assumed to be 70 kg, and the wording says so wherever the number appears.
A worked pair, planned this morning between Sheffield station and Crookes:
| climb | energy | |
|---|---|---|
| Station to Crookes, 3.7 km | +169 m, -3 m | 282 kcal |
| Crookes to station, 3.7 km | +3 m, -169 m | 177 kcal |
The same walk, the same distance, 105 kcal apart. That difference is the argument for doing this at all.
What the planner shows
Each itinerary card carries the climb and the calories next to the walk time, because the comparison between options is made there rather than inside a leg. A gradient of 12% or steeper — about a Sheffield side street — is marked, but never by colour alone; the arrow and the metres say the same thing.
Flat walks say nothing. A route with no climb worth mentioning gets silence rather than "0 m", which would be a fact nobody asked for.
The words it uses
The label is ranked on total climb, because that is what costs the effort, with steepness able to promote a walk one tier. Direction comes from the balance of ascent and descent.
| Climb | Going up | Going down |
|---|---|---|
| under 8 m either way | flat | flat |
| under 25 m | gentle climb | gentle descent |
| 25–70 m | steady climb | steady descent |
| over 70 m | steep climb | long descent |
A walk that gains and loses comparable amounts is rolling, or hilly once the two together pass 70 m. A section at 12% or steeper promotes a walk one tier, but only one with at least 15 m of climb in it — otherwise a single steep kerb ramp would describe a stroll as a climb.
An earlier version ranked on the steepest single segment instead of the total. That read a 10 m walk with one sharp ramp as uphill while a 20 m climb up a shallow road came out slightly uphill — the smaller walk described as the bigger one. Direction is now sent by the API rather than inferred from the words, so nothing downstream has to guess that "gentle descent" points downwards.
What this does not do
- It does not change the timings. The router still walks everyone at a constant speed, so a hill changes the effort we report and not the minutes we predict. Uphill journeys are therefore still optimistic on time.
- It does not know about steps, bridges or lifts. These are bare-earth ground heights. A footbridge over a valley reads as the valley.
- It is an estimate of an average adult's energy, not a measurement of yours. Age, fitness, load and pace all move it, and none of them are known here.
- Accessibility is not addressed by this. Knowing a route climbs 12% is useful to someone deciding whether they can manage it, but a proper step-free or gradient-limited routing option is a different piece of work.
Contains OS data (c) Crown copyright and database right 2026.