Skip to content

Commit

Permalink
Ensure u-turn exists in intersection view (Project-OSRM#6376)
Browse files Browse the repository at this point in the history
Due to some rather complex logic that tries to calculate intersection
angles by looking further up the road, it's possible to return
an intersection view that is missing a u-turn - something which
is assumed to exist in later guidance calculations.

We apply a fix here by ensuring the u-turn is always included in
the returned view.
  • Loading branch information
mjjbell authored and mattwigway committed Jul 20, 2023
1 parent 01fbea6 commit c8e7067
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
- ADDED: Support snapping to multiple ways at an input location. [#5953](https://github.com/Project-OSRM/osrm-backend/pull/5953)
- FIXED: Fix snapping target locations to ways used in turn restrictions. [#6339](https://github.com/Project-OSRM/osrm-backend/pull/6339)
- ADDED: Support OSM traffic signal directions. [#6153](https://github.com/Project-OSRM/osrm-backend/pull/6153)
- FIXED: Ensure u-turn exists in intersection view. [#6376](https://github.com/Project-OSRM/osrm-backend/pull/6376)
- Profile:
- CHANGED: Bicycle surface speeds [#6212](https://github.com/Project-OSRM/osrm-backend/pull/6212)

Expand Down
31 changes: 31 additions & 0 deletions features/foot/intersection.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@routing @foot
Feature: Foot - Intersections

Background:
Given the profile "foot"
Given a grid size of 2 meters

# https://github.com/Project-OSRM/osrm-backend/issues/6218
Scenario: Foot - Handles non-planar intersections
Given the node map

"""
f
|
a
|
b---c---d
|
e
"""

And the ways
| nodes | highway | foot | layer |
| ac | footway | yes | 0 |
| bc | footway | yes | 0 |
| cd | footway | yes | 0 |
| cef | footway | yes | 1 |

When I route I should get
| from | to | route |
| a | d | ac,cd,cd |
26 changes: 22 additions & 4 deletions src/extractor/intersection/intersection_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,12 +617,13 @@ IntersectionView convertToIntersectionView(const util::NodeBasedDynamicGraph &gr
std::vector<IntersectionViewDataWithAngle> pre_intersection_view;
IntersectionViewData uturn{{SPECIAL_EDGEID, 0., 0., 0.}, false, 0.};
std::size_t allowed_uturns_number = 0;

const auto is_uturn = [](const auto angle) {
return std::fabs(angle) < std::numeric_limits<double>::epsilon();
};

for (const auto &outgoing_edge : outgoing_edges)
{
const auto is_uturn = [](const auto angle) {
return std::fabs(angle) < std::numeric_limits<double>::epsilon();
};

const auto edge_it = findEdge(edge_geometries, outgoing_edge.edge);
const auto is_merged = merged_edges.count(outgoing_edge.edge) != 0;
const auto is_turn_allowed = intersection::isTurnAllowed(graph,
Expand Down Expand Up @@ -678,6 +679,7 @@ IntersectionView convertToIntersectionView(const util::NodeBasedDynamicGraph &gr
BOOST_ASSERT(uturn.eid != SPECIAL_EDGEID);
if (uturn.entry_allowed || allowed_uturns_number == 0)
{ // Add the true U-turn if it is allowed or no other U-turns found
BOOST_ASSERT(uturn.angle == 0.);
pre_intersection_view.insert(pre_intersection_view.begin(), {uturn, 0});
}

Expand Down Expand Up @@ -706,6 +708,22 @@ IntersectionView convertToIntersectionView(const util::NodeBasedDynamicGraph &gr
}
}

auto no_uturn = std::none_of(pre_intersection_view.begin(),
pre_intersection_view.end(),
[&is_uturn](const IntersectionViewDataWithAngle &road) {
return is_uturn(road.first.angle);
});
// After all of this, if we now don't have a u-turn, let's add one to the intersection.
// This is a hack to fix the triggered assertion ( see:
// https://github.com/Project-OSRM/osrm-backend/issues/6218 ). Ideally we would fix this more
// robustly, but this will require overhauling all of the intersection logic.
if (no_uturn)
{
BOOST_ASSERT(!uturn.entry_allowed && allowed_uturns_number > 0);
BOOST_ASSERT(uturn.angle == 0.);
pre_intersection_view.insert(pre_intersection_view.begin(), {uturn, 0});
}

// Copy intersection view data
IntersectionView intersection_view;
intersection_view.reserve(pre_intersection_view.size());
Expand Down

0 comments on commit c8e7067

Please sign in to comment.