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

make end of road non obvious #4411

Merged
merged 2 commits into from
Aug 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# UNRELEASED
- Changes from 5.11:
- Guidance
- now announcing turning onto oneways at the end of a road (e.g. onto dual carriageways)

# 5.11.0
- Changes from 5.10:
Expand Down
19 changes: 19 additions & 0 deletions features/guidance/end-of-road.feature
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@ Feature: End Of Road Instructions
| a,c | aeb,cbd,cbd | depart,end of road left,arrive |
| a,d | aeb,cbd,cbd | depart,end of road right,arrive |

# http://map.project-osrm.org/?z=18&center=38.906632%2C-77.008265&loc=38.906463%2C-77.007621&loc=38.906822%2C-77.008860&hl=en&alt=0
Scenario: End of Road, unnamed oneway
Given the node map
"""
c
a e b
f d
"""

And the ways
| nodes | highway | name | oneway |
| aeb | primary | road | yes |
| cbd | primary | | yes |
| ef | primary | turn | yes |

When I route I should get
| waypoints | route | turns |
| a,d | road,, | depart,end of road right,arrive |

@3605
Scenario: End of Road with oneway through street
Given the node map
Expand Down
18 changes: 9 additions & 9 deletions features/testbot/bearing_param.feature
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,12 @@ Feature: Bearing parameter
| ha | yes | ring |

When I route I should get
| from | to | bearings | route | bearing |
| 0 | q | 0 90 | ia,ring,ring | 0->0,0->90,90->0 |
| 0 | a | 45 90 | jb,ring,ring | 0->45,45->180,90->0 |
| 0 | q | 90 90 | kc,ring,ring | 0->90,90->180,90->0 |
| 0 | a | 135 90 | ld,ring,ring | 0->135,135->270,90->0 |
| 0 | a | 180 90 | me,ring,ring | 0->180,180->270,90->0 |
| 0 | a | 225 90 | nf,ring,ring | 0->225,225->0,90->0 |
| 0 | a | 270 90 | og,ring,ring | 0->270,270->0,90->0 |
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
| from | to | bearings | route | bearing |
| 0 | q | 0 90 | ia,ring,ring,ring,ring | 0->0,0->90,180->270,270->0,90->0 |
| 0 | a | 45 90 | jb,ring,ring,ring,ring | 0->45,45->180,180->270,270->0,90->0 |
| 0 | q | 90 90 | kc,ring,ring,ring | 0->90,90->180,270->0,90->0 |
| 0 | a | 135 90 | ld,ring,ring,ring | 0->135,135->270,270->0,90->0 |
| 0 | a | 180 90 | me,ring,ring,ring | 0->180,180->270,270->0,90->0 |
| 0 | a | 225 90 | nf,ring,ring | 0->225,225->0,90->0 |
| 0 | a | 270 90 | og,ring,ring | 0->270,270->0,90->0 |
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
52 changes: 48 additions & 4 deletions include/extractor/guidance/intersection_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,42 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
return false;
}();

// check whether we turn onto a oneway through street. These typically happen at the end of
Copy link
Member

Choose a reason for hiding this comment

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

This is getting a bit out of hand with all the inline lambdas etc.

Do you think we could refactor the intersection handler a bit to make it easier to follow the logic here?

Copy link
Author

Choose a reason for hiding this comment

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

we could, but that is not the scope of this PR

// roads and might not seem obvious, since it isn't always as visible that you cannot turn
// left/right. To be on the safe side, we announce these as non-obvious
const auto turns_onto_through_street = [&](const auto &road) {
// find edge opposite to the one we are checking (in-road)
const auto in_through_candidate =
intersection.FindClosestBearing(util::bearing::reverse(road.bearing));

const auto &in_data = node_based_graph.GetEdgeData(in_through_candidate->eid);
const auto &out_data = node_based_graph.GetEdgeData(road.eid);

// by asking for the same class, we ensure that we do not overrule obvious by road-class
// decisions
const auto same_class = in_data.road_classification == out_data.road_classification;
Copy link
Member

Choose a reason for hiding this comment

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

The implication here is a change in road class is always obvious already? Is this always the case? Where is it determined?

Copy link
Author

Choose a reason for hiding this comment

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

not necessarily, but we check for a through street. A street that changes class in between is probably not just a normal road but a different scenario


// only if the entry is allowed for one of the two, but not the other, we need to check.
// Otherwise other handlers do it better
const bool is_oneway = !in_through_candidate->entry_allowed && road.entry_allowed;

const bool not_roundabout =
!(in_data.roundabout || in_data.circular || out_data.roundabout || out_data.circular);
Copy link
Member

Choose a reason for hiding this comment

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

Care to remind me about the difference between checking for the roundabout instruction and the roundabout data here?

Copy link
Author

Choose a reason for hiding this comment

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

roundabout instructions can only be checked after they have been assigned. We are in the process of assigning turn-types, so they cannot be checked.


// for the purpose of this check, we do not care about low-priority roads (parking lots,
// mostly). Since we postulate both classes to be the same, checking one of the two is
// enough
const bool not_low_priority = !in_data.road_classification.IsLowPriorityRoadClass();

const auto in_deviation = angularDeviation(in_through_candidate->angle, STRAIGHT_ANGLE);
const auto out_deviaiton = angularDeviation(road.angle, STRAIGHT_ANGLE);
// in case the deviation isn't considerably lower for the road we are turning onto,
// consider it non-obvious. The threshold here requires a slight (60) vs sharp (120)
// degree variation, at lest (120/60 == 2)
return is_oneway && same_class && not_roundabout && not_low_priority &&
(in_deviation / (std::max(out_deviaiton, 0.5)) <= 2);
};

if (best_over_best_continue)
{
// Find left/right deviation
Expand Down Expand Up @@ -366,8 +402,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
angularDeviation(intersection[right_index].angle, STRAIGHT_ANGLE);

// return best_option candidate if it is nearly straight and distinct from the nearest other
// out
// way
// out way
if (best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
return best_option;
Expand All @@ -385,8 +420,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
right_data.road_classification);

// if the best_option turn isn't narrow, but there is a nearly straight turn, we don't
// consider the
// turn obvious
// consider the turn obvious
const auto check_narrow = [&intersection, best_option_deviation](const std::size_t index) {
return angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) <=
FUZZY_ANGLE_DIFFERENCE &&
Expand All @@ -400,6 +434,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
if (check_narrow(left_index) && !obvious_to_left)
return 0;

// we are turning onto a through street (possibly at the end of the road). Ensure that we
// announce a turn, if it isn't a slight merge
if (turns_onto_through_street(intersection[best_option]))
return 0;

// checks if a given way in the intersection is distinct enough from the best_option
// candidate
const auto isDistinct = [&](const std::size_t index, const double deviation) {
Expand Down Expand Up @@ -437,6 +476,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
if (std::abs(best_continue_deviation) < 1)
return best_continue;

// we are turning onto a through street (possibly at the end of the road). Ensure that we
// announce a turn, if it isn't a slight merge
if (turns_onto_through_street(intersection[best_continue]))
return 0;

// check if any other similar best continues exist
std::size_t i, last = intersection.size();
for (i = 1; i < last; ++i)
Expand Down