Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix street routing on roundabout #5732

Merged
merged 2 commits into from
Mar 20, 2024

Conversation

vpaturet
Copy link
Contributor

@vpaturet vpaturet commented Mar 7, 2024

Summary

As detailed in #5706, OTP fails to find a path between 2 points under certain routing network configurations.
Further analysis shows that A* cannot traverse a loop made of 2 edges:
A ------>B------>A

This is due to:

  • A* refusing to backtrack on an edge that goes back to its previous state (thus preventing infinite loops?)
    In other words: if the edge e has been traversed in state n, reverse(e) cannot be traversed in state n+1.
  • A technical implementation detail in the temporary edge class org.opentripplanner.street.model.edge.TemporaryPartialStreetEdge that defines the reverse of a temporary edge as the reverse of its parent.

In the corner case of the loop:
A ------>B------>A
if the trip origin is A and the destination is a temporary vertex T between B and A:
A ------>B---T--->A
The temporary edge B-T has B-A as its parent, thus reverse(B-T)=reverse(B-A)=A-B
As a result B-T cannot be traversed after A-B.

Proposed fix:
It is unclear why the reverse of a temporary edge should be the reverse of its parent.
Assuming this is only an optimization detail, this pull request removes the overloaded method TemporaryPartialStreetEdge.reverseOf() so that the default implementation applies.

Issue

Closes #5706

Unit tests

Added unit test

Documentation

No

@vpaturet vpaturet added the Bug label Mar 7, 2024
@vpaturet vpaturet self-assigned this Mar 7, 2024
@vpaturet vpaturet requested a review from a team as a code owner March 7, 2024 12:44
Copy link

codecov bot commented Mar 7, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 67.78%. Comparing base (6c956b8) to head (b2ee65f).
Report is 29 commits behind head on dev-2.x.

Additional details and impacted files
@@              Coverage Diff              @@
##             dev-2.x    #5732      +/-   ##
=============================================
+ Coverage      67.76%   67.78%   +0.01%     
- Complexity     16471    16478       +7     
=============================================
  Files           1901     1901              
  Lines          72114    72128      +14     
  Branches        7430     7429       -1     
=============================================
+ Hits           48869    48892      +23     
+ Misses         20734    20723      -11     
- Partials        2511     2513       +2     

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

@leonardehrenfried leonardehrenfried requested a review from abyrd March 7, 2024 15:17
@vpaturet vpaturet changed the title Fix direct routing on roundabout Fix street routing on roundabout Mar 11, 2024
@t2gran t2gran added this to the 2.5 (next release) milestone Mar 12, 2024
@leonardehrenfried
Copy link
Member

@abyrd I don't think we ever formally asked you if you are willing to review this. Are you?

@t2gran t2gran modified the milestones: 2.5, 2.6 (next release) Mar 13, 2024
Copy link
Member

@abyrd abyrd left a comment

Choose a reason for hiding this comment

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

It's not clear why the isReverseOf logic was overridden this way in the case of TemporaryPartialStreetEdge. As discussed on the call, the reason may be lost to time, and it looks like the proposed change should work as expected.

The reasons why isReverseOf is checked are better known:

  • Going back to the same vertex can never improve the state at that vertex. (All edge costs are constrained to be positive - if they weren't, this would clearly lead to infinite loops.) So if we naively traverse all edges encountered during a search, about half of the edge traversals are useless. Checking whether an edge leads back to the previously visited vertex should always be faster/cheaper than actually computing the cost of traversing it, and effectively skips the edge traversal computations for these useless traversals.
  • Besides never yielding a better state, traversing the reverse edge would involve a usually-illegal U turn. In cases where U turns are feasible and beneficial, the two directions of the street are often mapped as separate ways. Indeed they'd have to be to improve the cost of reaching an intermediate vertex by making a U turn.

@vpaturet vpaturet merged commit 384e1e6 into opentripplanner:dev-2.x Mar 20, 2024
5 checks passed
t2gran pushed a commit that referenced this pull request Mar 20, 2024
@t2gran t2gran deleted the fix_roundabout_direct_routing branch October 9, 2024 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Direct routing does not return any result when passing some intersections
4 participants