Skip to content

fix: closed segments no longer incorrectly remove turn permissions at non-adjacent intersections - #7745

Open
hamishcampbell wants to merge 3 commits into
Project-OSRM:masterfrom
uintel:fix/7332-closed-segment-target
Open

hamishcampbell wants to merge 3 commits into
Project-OSRM:masterfrom
uintel:fix/7332-closed-segment-target

Conversation

@hamishcampbell

@hamishcampbell hamishcampbell commented Oct 12, 2026 •

Copy link
Copy Markdown

Issue

Fixes #7332.

When --segment-speed-file closes a segment (speed 0), OSRM treats the whole edge-based node holding that segment as unusable. A start or end point on an open part of the same way, past the closure, either can't route at all or has to make a detour. For example, a house on segment A in the issue can't route north even though segment A itself is open.

This PR makes routing look at where the phantom sits relative to the closure, rather than only at whether the node has a closure somewhere on it. There are three commits, each one a separate case found & validated through manual testing:

  1. fix(mld): start past a closure. The MLD customizer used to drop every turn leaving a node with a zero-speed segment. It now keeps those turns but marks them INVALID_EDGE_WEIGHT, so cell customization and through traffic still can't use them. In the MLD route, table and matching searches, a seed on such a node may leave it when no closed segment lies after the phantom (the seed weight shows this exactly). A source is now valid when its own segment is open. CH still drops these turns, so CH behaviour doesn't change for sources.

  2. fix(engine): reach a target past a closure along its own edge. A target on a node with a closed segment before it used to be invalid outright, so a route from a source on the same node had to leave the node and U-turn back in from the other side. Now a phantom is a valid target, like a source, when its own segment is open. The searches refuse to reach it from the start of its node across the closure: a target seed can't be left past a closure before it, and the forward and reverse searches can only meet at such a seed when the source side entered the node past the closure. This covers CH and MLD route, table and alternative searches.

  3. fix(engine): turn around at a waypoint heading towards a closure. With continue_straight a route that reached a waypoint heading towards a closure on the same node had nowhere to go, so the next leg failed. This is now treated like a dead end i.e the route may continue from the waypoint in the other direction, which continue_straight=false already allows.

Testing

  • New cucumber scenarios in features/testbot/zero-speed-updates.feature:
    • Closing a segment should not trap a start past the closure on the same way (CH and MLD)
    • Turning around at a waypoint heading towards a closed segment
  • features/testbot/snap_intersection.feature the b → e and d → a cases in "previous section of segment blocked" used to expect NoRoute. They now route under MLD (new @no_ch scenario). The a → e / e → a cases still give NoRoute.
  • Manually checked against the NZ reproduction from the issue (Christchurch query, MLD, segment speed file) and it fixes the linked issue.

AI Disclosure

Claude was primarily used to find the fix this issue, alongside manual testing of routes and code review.

Tasklist

Requirements / Relations

N/A see the source issue #7332

A zero-speed segment from --segment-speed-file made the customizer drop
every turn leaving its edge-based node, so a source anywhere on that node
had no way off it, even past the closure (Project-OSRM#7332).

Keep those turns, marked with INVALID_EDGE_WEIGHT so cell customization
and through traffic still can't use them. In the MLD route, table and
matching searches a seed on such a node may leave it when no closed
segment lies after the phantom, which the seed weight tells exactly.
A source is now valid when its own segment is open.

CH still drops the turns, so its behaviour is unchanged.
A target on an edge-based node with a closed (zero-speed) segment before
it was invalid outright, so a route to it from a source on the same node
past the closure had to leave the node and U-turn back into it from the
other side.

A phantom is now a valid target, like a source, when its own segment is
open. Reaching it from the start of its node would cross the closure, so
the searches refuse that instead: a target seed may not be left past a
closure before it, and the two sides of a search may only meet at such a
seed when the source side entered its node past that closure, which the
seed weights tell. This covers the CH and MLD route, table and
alternative searches.
With continue_straight, a route that reached a waypoint heading towards
a closed (zero-speed) segment on the same edge-based node could not go
on, as the node can't be left past the closure, and there is no turn to
make before it. Any waypoint after it on the way back failed to route.

Treat that like a dead end: when the direction a route reached a
waypoint in has a closure ahead, it may carry on from the waypoint in
the other direction too, as continue_straight=false always allows.
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.

Closing a segment incorrectly removes turn permissions at non-adjacent intersections

1 participant