Skip to content

fix: account for road width in map matching#7643

Open
Komzpa wants to merge 1 commit into
Project-OSRM:masterfrom
Komzpa:komzpa/matching-road-surface-lanes
Open

fix: account for road width in map matching#7643
Komzpa wants to merge 1 commit into
Project-OSRM:masterfrom
Komzpa:komzpa/matching-road-surface-lanes

Conversation

@Komzpa

@Komzpa Komzpa commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Fixes #4480.

Summary

  • Store profile-derived road width in edge annotations and expose it through the engine data facade.
  • Parse wiki-documented width tags in Lua profiles: width, est_width, width:carriageway, directional width tags, and width:lanes* variants.
  • Fall back to lanes when no explicit width is tagged, capped by the maximum road-surface width.
  • Treat map-matching candidates inside the tagged/derived road surface as zero outside-road distance.
  • Expand map-matching candidate searches by the observed maximum road half-width, instead of a fixed global expansion.
  • Preserve lane-derived width through graph compression when adjacent compressed edges have different lane counts.
  • Bump the data fingerprint because edge annotation storage changes.

Testing

  • git diff --check
  • jq empty taginfo.json
  • PR_TITLE="fix: account for road width in map matching" node scripts/check_pr_title.js
  • Lua parser smoke for supported width tags, imperial values, and unsupported tag rejection
  • node_modules/.bin/cucumber-js --dry-run features/testbot/matching.feature
  • cmake --build build-local --target util-tests engine-tests extractor-tests -j 30
  • ./build-local/unit_tests/util-tests --run_test=static_rtree --log_level=test_suite
  • ./build-local/unit_tests/engine-tests --log_level=test_suite
  • ./build-local/unit_tests/extractor-tests --run_test=graph_compressor --log_level=test_suite
  • codex review --base origin/master --title "fix: account for road width in map matching"

@Komzpa Komzpa force-pushed the komzpa/matching-road-surface-lanes branch 2 times, most recently from ede0921 to 3854d35 Compare July 3, 2026 09:27
@Komzpa Komzpa changed the title Fix map matching lane-width tolerance fix: account for lane width in map matching Jul 3, 2026
@Komzpa Komzpa force-pushed the komzpa/matching-road-surface-lanes branch 3 times, most recently from 5423fac to 9b795db Compare July 3, 2026 09:43
@Komzpa Komzpa changed the title fix: account for lane width in map matching fix: account for road width in map matching Jul 3, 2026
@DennisOSRM DennisOSRM requested a review from Copilot July 3, 2026 09:54
@Komzpa Komzpa force-pushed the komzpa/matching-road-surface-lanes branch from 9b795db to 537f42f Compare July 3, 2026 09:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates OSRM’s extraction → data facade → map matching pipeline to account for tagged/derived road surface width, improving matching robustness when GPS points are near the road edge rather than near the centerline (Issue #4480).

Changes:

  • Persist profile-derived road width (and lane-count fallback) into edge annotations and expose them via the engine DataFacade.
  • Adjust map matching emission probabilities to treat points within the road surface as having zero “outside-road” distance.
  • Expand candidate lookup bounds in geospatial queries (capped) and add a testbot regression scenario covering wide-road cases.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
unit_tests/mocks/mock_datafacade.hpp Updates the mock facade to satisfy the extended BaseDataFacade interface.
unit_tests/extractor/intersection_analysis_tests.cpp Updates annotation aggregate initialization for new fields.
unit_tests/engine/offline_facade.cpp Updates the offline facade test implementation with the new DataFacade methods.
src/extractor/scripting_environment_lua.cpp Exposes road_width to Lua profiles via ExtractionWay.
src/extractor/extractor_callbacks.cpp Encodes and stores lane count + road width into per-edge annotations during extraction.
src/engine/routing_algorithms/map_matching.cpp Uses “distance outside road surface” for emission probability calculations.
profiles/testbot.lua Adds lane/width handling to the testbot profile (via Guidance + lanes tag).
profiles/lib/measure.lua Adds missing lib/set dependency used by the module.
profiles/lib/guidance.lua Implements get_road_width parsing for multiple width tagging schemes.
include/extractor/node_data_container.hpp Adds accessors to read lanes/width from stored annotations.
include/extractor/node_based_edge.hpp Extends NodeBasedEdgeAnnotation to store lanes + width and includes them in comparisons.
include/extractor/intersection/constants.hpp Introduces a cap for road-surface width approximation.
include/extractor/extraction_way.hpp Adds road_width to the extraction result structure and resets it in clear().
include/engine/geospatial_query.hpp Broadens candidate search by capped half-width and applies per-segment half-width in filtering.
include/engine/datafacade/datafacade_base.hpp Adds GetNumberOfLanes / GetRoadWidth to the facade interface.
include/engine/datafacade/contiguous_internalmem_datafacade.hpp Implements the new facade methods via edge-based node data.
features/testbot/matching.feature Adds a regression scenario ensuring wide roads are matched correctly over parallel distractors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread include/engine/datafacade/datafacade_base.hpp Outdated
@Komzpa Komzpa force-pushed the komzpa/matching-road-surface-lanes branch 2 times, most recently from defeb76 to b2fd876 Compare July 3, 2026 11:34
@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.22642% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.22%. Comparing base (f984023) to head (a46d09e).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
include/engine/geospatial_query.hpp 77.77% 4 Missing ⚠️
src/engine/routing_algorithms/map_matching.cpp 88.00% 3 Missing ⚠️
src/extractor/graph_compressor.cpp 97.29% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #7643      +/-   ##
==========================================
+ Coverage   94.20%   94.22%   +0.01%     
==========================================
  Files         483      483              
  Lines       37670    37843     +173     
==========================================
+ Hits        35487    35656     +169     
- Misses       2183     2187       +4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Komzpa Komzpa force-pushed the komzpa/matching-road-surface-lanes branch from b2fd876 to a46d09e Compare July 3, 2026 16:55

@DennisOSRM DennisOSRM left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for the contribution. I left a couple of comments/questions on the PR. Could you provide some experimental results showing this leads to improved matching results?

Comment thread profiles/lib/guidance.lua
return nil
end

local function first_width(way, keys)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this maybe be called find_first_width to indicate that it greedily searches for the first width tag it can find?

Comment thread profiles/lib/guidance.lua
end
end

local function sum_width_lanes(value)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be called sum_lane_width?

Comment thread profiles/lib/guidance.lua

if found then
return total
end

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this return a nil value explicitly in case the sum is zero?

Comment thread profiles/lib/guidance.lua
end

local total = 0
local found = false

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this variable actually necessary? Would it be enough to check if sum is zero or not?

Comment thread profiles/lib/measure.lua
@@ -1,4 +1,5 @@
local Sequence = require('lib/sequence')
local Set = require('lib/set')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an unrelated change?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Take road width into account on map matching

3 participants