Skip to content

Commit

Permalink
detect turning onto oneways at the end of the road as non obvious
Browse files Browse the repository at this point in the history
  • Loading branch information
Moritz Kobitzsch committed Aug 16, 2017
1 parent cde8f86 commit 889b89a
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
- Fix a pre-processing bug where incorrect directions could be issued when two turns would have similar instructions and we tried to give them distinct values (https://github.com/Project-OSRM/osrm-backend/pull/4375)
- The entry bearing for correct the cardinality of a direction value (https://github.com/Project-OSRM/osrm-backend/pull/4353
- Change timezones in West Africa to the WAT zone so they're recognized on the Windows platform
- Guidance
- now announcing turning onto oneways at the end of a road (e.g. onto dual carriageways)

# 5.10.0
- Changes from 5.9:
Expand Down
4 changes: 2 additions & 2 deletions features/guidance/end-of-road.feature
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ Feature: End Of Road Instructions
| ef | primary | turn | yes |

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

@3605
Scenario: End of Road with oneway through street
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
// 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;

// 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);

// 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,1)) <= 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

0 comments on commit 889b89a

Please sign in to comment.