Map Matching Simulator: Snapping GPS Traces to Road Networks

simulator intermediate ~10 min
Loading simulation...
Match rate ≈ 94% — correct road identification

With σ_gps=10 m, road density of 15 km/km², and balanced heading constraint, the HMM map matcher correctly identifies the road segment for about 94% of GPS points.

Formula

P(zₜ|rᵢ) ∝ exp(-d²/(2σ²))  (emission probability)
P(rⱼ|rᵢ) ∝ exp(-|d_route - d_great_circle|/β)  (transition)
r* = argmax Π P(zₜ|rₜ) · P(rₜ|rₜ₋₁)  (Viterbi)

From Noisy Points to Clean Routes

Open any navigation app and your position sits neatly on the road. But the raw GPS data rarely falls exactly on a road — it scatters in a cloud with 3-50 meter uncertainty, sometimes placing you on the wrong side of a highway, on a parallel street, or in a building. Map matching is the algorithmic bridge between raw GPS measurements and clean road-level positioning, and it runs invisibly on billions of devices worldwide.

The Candidate Search

For each GPS point, the matcher identifies candidate road segments within a search radius. In sparse rural areas there may be only one candidate; in dense urban grids, dozens. The simulation visualizes this search process, highlighting candidate segments and showing why simple nearest-road matching fails when multiple roads are within the GPS error circle. The search radius must balance completeness (including the correct road) against computational cost.

Hidden Markov Model Matching

The state-of-the-art approach models map matching as a Hidden Markov Model. The hidden states are road positions; GPS observations are noisy emissions. The emission probability decreases with distance from GPS point to road. The transition probability between consecutive road positions depends on the difference between shortest-path distance and great-circle distance — penalizing routes that require implausible detours. The Viterbi algorithm finds the globally optimal path through this probability lattice.

Challenges at Scale

Real-world map matching must handle GPS outages (tunnels, urban canyons), U-turns, one-way streets, altitude ambiguity (overpasses vs. underpasses), and map errors. Low-sampling-rate data (one point per minute from fleet GPS) leaves large gaps that span multiple intersections, requiring path inference not just point snapping. The simulation lets you increase noise and road density to observe how these challenges degrade matching accuracy and how algorithmic parameters can compensate.

FAQ

What is map matching?

Map matching is the process of aligning raw GPS traces to the road network on a digital map. Because GPS positions have errors (3-50 m), raw points often fall off-road or on the wrong road. Map matching algorithms determine which road segment each GPS point actually belongs to, using distance, heading, and network topology.

How does the Hidden Markov Model approach work?

The HMM map matcher treats the true road position as a hidden state and GPS readings as noisy observations. Emission probabilities depend on distance from GPS point to candidate road segments. Transition probabilities favor routes along connected roads (penalizing impossible jumps). The Viterbi algorithm finds the most likely sequence of road segments — the global optimum path.

Why not just snap to the nearest road?

Simple nearest-road snapping fails when GPS noise causes points to be closer to a parallel or adjacent road than the correct one. In urban areas, this happens frequently. HMM-based matchers outperform nearest-road by 10-20% by considering the entire trajectory's consistency along the road network, not just individual point distances.

What applications use map matching?

Map matching is essential for turn-by-turn navigation (keeping the position icon on the road), fleet management (determining which roads vehicles actually traveled), traffic estimation (computing speeds from probe vehicle GPS), tolling (confirming use of tolled roads), and ride-hailing (computing correct trip routes and fares).

Sources

Embed

<iframe src="https://homo-deus.com/lab/navigation/map-matching/embed" width="100%" height="400" frameborder="0"></iframe>
View source on GitHub