Map Matching Accuracy Validation and Benchmarking

Most map-matching work is evaluated by looking at it. Somebody plots a matched trace over a basemap, it follows the roads, and the matcher is declared to work. That method finds catastrophic failures and misses everything else — the reversed one-way segment, the parallel service road, the junction where the path takes the wrong exit and rejoins two hundred metres later.

Those are the failures that matter, because they are the ones that reach a distance report or a driver’s scorecard while looking entirely plausible. Catching them needs ground truth, metrics that see different kinds of wrongness, and a gate that runs on every change. This page covers all three, and connects to the algorithm choices described in choosing a map matching algorithm.


Prerequisites

  • A matcher you can run repeatedly and deterministically. If the same input can produce two different outputs, measure that first — a non-deterministic matcher cannot be benchmarked.
  • Ground truth, discussed at length below. This is the part that takes work.
  • A projected CRS for every distance computation, per coordinate reference system mapping.
  • A pinned graph version, so a change in accuracy can be attributed to the matcher rather than to the map — see pinning map versions.
  • shapely 2.0+ and numpy for the geometric metrics.

What Ground Truth Means Here

Ground truth for map matching is a sequence of edge identifiers, not a line on a map. That distinction matters: two matchers can produce visually identical lines while disagreeing about which carriageway of a dual carriageway the vehicle was on, and only an edge sequence records the difference.

There are three practical sources, in descending order of cost and quality.

Instrumented drives. A vehicle with a survey-grade receiver, driven on a planned route, with the route recorded independently. Expensive per trace and unimpeachable. A few dozen of these anchor everything else.

High-rate recordings downsampled. Take 1 Hz traces, match them with generous parameters and a careful review, treat that as truth, then downsample to the fleet’s real rate and evaluate against it. This is the workhorse: it costs almost nothing per trace and it directly measures the effect of the sampling rate, which is usually the dominant factor.

Manually labelled production traces. Somebody walks a trace through a map and records the edge sequence. Slow and error-prone at scale, but it is the only source for the awkward cases — the multi-storey car park, the private yard, the ferry — and those are exactly what a benchmark drawn from easy traces will miss.

Three sources of ground truth, and what each is for Instrumented drives are expensive per trace and completely trustworthy. Downsampled high-rate recordings are nearly free and trustworthy enough for the common cases. Manually labelled production traces are slow but are the only source that covers awkward situations such as private yards and ferries. Use all three; they cover different gaps cost / trace trustworthy covers hard cases instrumented drive very high complete only if driven downsampled 1 Hz near zero good no manual labelling high good, if reviewed yes A benchmark built only from the middle row measures the easy majority and reports an accuracy nobody experiences. A benchmark built only from the bottom row is all edge cases and moves violently on any change. Aim for roughly 70 % downsampled, 20 % manually labelled hard cases, 10 % instrumented anchors.

Metrics That See Different Failures

No single metric covers map matching, because there are three independent ways to be wrong: in position, in topology, and in time.

Metric What it measures Blind to
Hausdorff distance Worst-case geometric deviation Direction, topology, missing links
Correct-edge rate Share of distance on the right edge How far wrong the wrong ones were
Edge F1 Precision and recall over the edge set Ordering and direction
Temporal alignment error Timing along the matched path Purely geometric errors
Route-length error Total distance, matched against truth Compensating errors in both directions

The pairing that covers the most ground for the least effort is correct-edge rate plus temporal alignment error. The first catches wrong roads; the second catches right roads traversed in the wrong order or the wrong direction, which the first cannot see at all.

Route-length error deserves a warning. It is the metric a business asks for, and it is the easiest to be accidentally right on: a match that takes a wrong turn and a compensating wrong turn back can have almost exactly the correct total distance while being wrong the whole way. Report it, but never gate on it alone.

Three ways to be wrong, three metrics The same ground-truth path matched three ways. One output follows a parallel service road, which correct-edge rate catches and route-length error does not. One reverses a segment, which only temporal alignment catches. One takes a detour and returns, which has almost the correct total length. One truth, three wrong answers ground truth parallel service road — correct-edge rate 0.71, length error 0.4 % reversed segment — correct-edge rate 1.00, temporal error 46 s The second row is the dangerous one: every geometric metric says it is perfect, and the vehicle drove the other way. Direction errors reach one-way-violation reports and driver scorecards, where they are read as behaviour.

Stratifying the Result

A single fleet-wide accuracy figure is close to useless, because it is dominated by whichever combination of network and sampling rate happens to be most common. Stratify by two axes at minimum:

  • Network density — rural, suburban, urban grid, dense centre. This is where the algorithm choice shows up.
  • Sampling interval — 1 Hz, 10 s, 30 s, 60 s and above. This is usually the larger effect, and it is a hardware and cost question rather than a software one.

A stratified table answers questions a single number cannot: whether to spend on better trackers or on a better matcher, which depots need attention, and whether a proposed change helps everywhere or trades one stratum against another. That last case is common enough to be worth watching for — a parameter change that improves dense-urban accuracy by three points while losing two on rural traces is a different decision depending on where the fleet drives.


Gating Changes

Once the benchmark exists, wire it into continuous integration. The gate has three properties worth insisting on.

It fails on a regression beyond a tolerance, not on any change. Matching accuracy moves slightly with any change to candidate search or tie-breaking, and a zero-tolerance gate gets disabled.

It reports per stratum, not just in aggregate. A change that loses four points on 60-second traces while gaining one overall should be visible as what it is.

It runs against a pinned graph. Otherwise a map refresh will show up as a code regression, and the team will spend a day looking in the wrong place.

def gate(new: dict[str, float], baseline: dict[str, float], tol_pts: float = 0.5) -> None:
    regressions = {
        k: (new[k] - baseline[k]) * 100
        for k in baseline
        if (new[k] - baseline[k]) * 100 < -tol_pts
    }
    if regressions:
        raise SystemExit(f"accuracy regression beyond {tol_pts} pts: {regressions}")

Watching for Drift in Production

The benchmark protects against changes you make. It does not protect against changes made to you — a map refresh, a device firmware rollout that alters the sampling rate, a new operating area with different network characteristics.

For those, track the same metrics on live traffic. Full ground truth is unavailable there, but two proxies work well: the share of traces that fail to match at all, and the distribution of the matcher’s own confidence. Neither measures correctness, and both move sharply when something upstream changes — which is exactly what a drift alarm needs to do.


Frequently Asked Questions

Is the matcher’s confidence score a substitute for ground truth?

No, and the reason is worth being precise about. A confidence score measures how well the observations fit the path the matcher already selected. A trace snapped confidently onto a parallel service road produces a high score, because the fixes really are close to that road and the transitions really are cheap. Confidence measures internal consistency, not correctness, and the two diverge exactly where matching is hard. Use it to triage which traces deserve a human look, never as a label.

How do I evaluate a matcher when no ground truth exists for a region?

Use agreement between independent matchers as a weak proxy, and be explicit that it is one. Where two differently-configured engines agree, the match is probably right; where they disagree, something is hard. That gives a usable ranking of traces to investigate without giving an accuracy figure. It is enough to find problems and not enough to publish a number, and conflating the two is the most common misuse of the technique.

What accuracy should a fleet actually expect?

On 1 Hz urban traces against a current graph, ninety to ninety-five percent correct-edge rate is realistic. At 30-second reporting the same fleet typically sits in the high seventies to mid eighties in dense centres and the low nineties on trunk roads. Numbers above ninety-eight percent on urban data almost always mean the evaluation set is easier than production — check how the labels were made before treating it as a target.

Should accuracy be reported per vehicle or per trace?

Per trace for engineering, per vehicle for operations. Engineering needs the trace-level distribution to find failure modes; operations needs to know which vehicles produce unreliable data, which is a hardware and installation question. The two views frequently disagree, and that disagreement is informative: a handful of vehicles producing most of the bad traces is a very different problem from uniform mediocrity.

How does sampling rate compare with algorithm choice as a driver of accuracy?

Sampling rate usually wins, and by a wide margin. Moving a fleet from 60-second to 10-second reporting typically buys more accuracy than any algorithmic change available, because it removes ambiguity rather than resolving it more cleverly. That makes the benchmark a procurement input as much as an engineering one — the stratified table is the argument for or against better hardware.

What is the minimum viable version of this whole exercise?

Fifty labelled traces spread across your two hardest network types, correct-edge rate and temporal error, run manually before each release. That is an afternoon of work and it catches the regressions that reach customers. Everything else on this page is refinement on top of it, and a team that has the minimum version running is in a far better position than one still planning the full one.

Operational Troubleshooting

Benchmark accuracy is far above production experience. The suite is drawn from easy traces. Add the awkward cases: multi-storey car parks, private yards, ferry crossings, and anything a driver has complained about.

Accuracy moves every run without any change. The matcher is non-deterministic — usually an unordered candidate set or a tie broken by dictionary ordering. Fix that before trusting any number.

One stratum swings wildly between runs. It is too small. A stratum with thirty traces has a standard error of several points; either grow it or stop reporting it separately.

A change improves the benchmark and worsens production. The suite has drifted from the workload. Check when it was last extended, and whether the fleet’s sampling-rate mix has moved since.


Deployment Checklist


Benchmarking Engines Against Each Other

The same apparatus answers a second question: which engine to run. Published comparisons are of limited use here, because match accuracy depends far more on your network and your sampling rate than on the engine’s algorithm — all three mainstream engines implement the same hidden-Markov idea.

Run the comparison on your own stratified set, against the same graph data, and report the same metrics. Two practical notes make the result meaningful.

Normalise the output before comparing. Each engine returns its own edge identifiers, so both sides must be resolved to OSM way identifiers plus a direction flag first. Skipping this measures the identifier scheme rather than the match, and it is the single most common error in engine comparisons.

Give each engine a fair configuration. A default-configured Valhalla against a carefully tuned OSRM measures the tuning. Spend the same effort on each: set each engine’s emission and transition parameters from the same measured receiver error, and use the same candidate radius policy.

The result is usually less dramatic than expected. Correct-edge rate typically differs by two to four points across engines on the same data, while latency and operational cost differ by an order of magnitude — which is why choosing a routing engine argues the decision is usually made on constraints rather than on accuracy.

Where an engine does lose materially, the loss is almost always concentrated in one stratum, and the stratified report shows which. That is a more useful finding than a headline number: it may mean the engine is a good fit for the trunk-road majority and a poor one for the city-centre work, which suggests running two rather than choosing one.

Three engines, one stratified set Correct-edge rate for three routing engines across rural, suburban, urban-grid and dense-centre strata on the same traces and the same graph data. The engines are within two points everywhere except the dense centre, where one loses seven points. Same traces, same map data, comparable configuration 100 % 85 % 70 % rural suburban urban grid dense centre Three engines within two points on three strata, and a seven-point gap on the fourth — which is the finding. A single aggregate would have reported a one-point difference and hidden the only result worth acting on.