detect turning onto oneways at the end of the road as non obvious

This commit is contained in:
Moritz Kobitzsch 2017-08-15 11:50:14 +02:00
parent af8ddac2af
commit f347efb006
4 changed files with 62 additions and 15 deletions

View File

@ -1,4 +1,7 @@
# UNRELEASED # 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 # 5.11.0
- Changes from 5.10: - Changes from 5.10:

View File

@ -40,8 +40,8 @@ Feature: End Of Road Instructions
| ef | primary | turn | yes | | ef | primary | turn | yes |
When I route I should get When I route I should get
| waypoints | route | turns | | waypoints | route | turns |
| a,d | road, | depart,arrive | | a,d | road,, | depart,end of road right,arrive |
@3605 @3605
Scenario: End of Road with oneway through street Scenario: End of Road with oneway through street

View File

@ -108,12 +108,12 @@ Feature: Bearing parameter
| ha | yes | ring | | ha | yes | ring |
When I route I should get When I route I should get
| from | to | bearings | route | bearing | | from | to | bearings | route | bearing |
| 0 | q | 0 90 | ia,ring,ring | 0->0,0->90,90->0 | | 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 | 0->45,45->180,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 | 0->90,90->180,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 | 0->135,135->270,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 | 0->180,180->270,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 | 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 | 270 90 | og,ring,ring | 0->270,270->0,90->0 |
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 | | 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |

View File

@ -327,6 +327,42 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
return false; 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, 0.5)) <= 2);
};
if (best_over_best_continue) if (best_over_best_continue)
{ {
// Find left/right deviation // Find left/right deviation
@ -366,8 +402,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
angularDeviation(intersection[right_index].angle, STRAIGHT_ANGLE); angularDeviation(intersection[right_index].angle, STRAIGHT_ANGLE);
// return best_option candidate if it is nearly straight and distinct from the nearest other // return best_option candidate if it is nearly straight and distinct from the nearest other
// out // out way
// way
if (best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION && if (best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE) std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
return best_option; return best_option;
@ -385,8 +420,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
right_data.road_classification); right_data.road_classification);
// if the best_option turn isn't narrow, but there is a nearly straight turn, we don't // if the best_option turn isn't narrow, but there is a nearly straight turn, we don't
// consider the // consider the turn obvious
// turn obvious
const auto check_narrow = [&intersection, best_option_deviation](const std::size_t index) { const auto check_narrow = [&intersection, best_option_deviation](const std::size_t index) {
return angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) <= return angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) <=
FUZZY_ANGLE_DIFFERENCE && FUZZY_ANGLE_DIFFERENCE &&
@ -400,6 +434,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
if (check_narrow(left_index) && !obvious_to_left) if (check_narrow(left_index) && !obvious_to_left)
return 0; 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 // checks if a given way in the intersection is distinct enough from the best_option
// candidate // candidate
const auto isDistinct = [&](const std::size_t index, const double deviation) { const auto isDistinct = [&](const std::size_t index, const double deviation) {
@ -437,6 +476,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
if (std::abs(best_continue_deviation) < 1) if (std::abs(best_continue_deviation) < 1)
return best_continue; 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 // check if any other similar best continues exist
std::size_t i, last = intersection.size(); std::size_t i, last = intersection.size();
for (i = 1; i < last; ++i) for (i = 1; i < last; ++i)