fix detection of forks in present of oneways
This commit is contained in:
parent
dbd108df8c
commit
66f2cc5184
@ -22,6 +22,37 @@ Feature: Fork Instructions
|
||||
| a,c | ab,bc,bc | depart,fork slight left,arrive |
|
||||
| a,d | ab,bd,bd | depart,fork slight right,arrive |
|
||||
|
||||
Scenario: Don't Fork On Single Road
|
||||
Given the node map
|
||||
| | | | | c |
|
||||
| a | | b | | |
|
||||
| | | | | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | oneway |
|
||||
| ab | primary | no |
|
||||
| cb | primary | yes |
|
||||
| bd | primary | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bd,bd | depart,new name slight right,arrive |
|
||||
|
||||
Scenario: Don't Fork On Single Road
|
||||
Given the node map
|
||||
| | | | | | | c |
|
||||
| a | | b | | d | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | oneway | name |
|
||||
| ab | primary | no | road |
|
||||
| cb | primary | yes | road |
|
||||
| bd | primary | yes | turn |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | road,turn,turn | depart,new name straight,arrive |
|
||||
|
||||
Scenario: Do not fork on link type
|
||||
Given the node map
|
||||
| | | | | c |
|
||||
|
@ -133,6 +133,22 @@ Feature: Simple Turns
|
||||
| d,c | db,cb,cb | depart,turn right,arrive |
|
||||
| d,a | db,ab,ab | depart,new name straight,arrive |
|
||||
|
||||
Scenario: Three Way Intersection - Meeting Oneways
|
||||
Given the node map
|
||||
| | c | |
|
||||
| a | b | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | oneway |
|
||||
| ab | primary | yes |
|
||||
| bc | primary | yes |
|
||||
| db | primary | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | ab,bc,bc | depart,turn left,arrive |
|
||||
| d,c | db,bc,bc | depart,turn right,arrive |
|
||||
|
||||
Scenario: Three Way Intersection on Through Street
|
||||
Given the node map
|
||||
| | d | |
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/intersection_handler.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
@ -534,26 +534,48 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
best_data.road_classification,
|
||||
right_data.road_classification);
|
||||
|
||||
// if the best turn isn't narrow, but there is a nearly straight turn, we don't consider the
|
||||
// turn obvious
|
||||
const auto check_narrow = [&intersection, best_deviation](const std::size_t index) {
|
||||
return angularDeviation(intersection[index].turn.angle, STRAIGHT_ANGLE) <=
|
||||
FUZZY_ANGLE_DIFFERENCE &&
|
||||
(best_deviation > NARROW_TURN_ANGLE || intersection[index].entry_allowed);
|
||||
};
|
||||
|
||||
// other narrow turns?
|
||||
if (angularDeviation(intersection[right_index].turn.angle, STRAIGHT_ANGLE) <=
|
||||
FUZZY_ANGLE_DIFFERENCE &&
|
||||
!obvious_to_right)
|
||||
if (check_narrow(right_index) && !obvious_to_right)
|
||||
return 0;
|
||||
|
||||
if (angularDeviation(intersection[left_index].turn.angle, STRAIGHT_ANGLE) <=
|
||||
FUZZY_ANGLE_DIFFERENCE &&
|
||||
!obvious_to_left)
|
||||
if (check_narrow(left_index) && !obvious_to_left)
|
||||
return 0;
|
||||
|
||||
const bool distinct_to_left =
|
||||
left_deviation / best_deviation >= DISTINCTION_RATIO ||
|
||||
(left_deviation > best_deviation &&
|
||||
(!intersection[left_index].entry_allowed && in_data.distance > 30));
|
||||
const bool distinct_to_right =
|
||||
right_deviation / best_deviation >= DISTINCTION_RATIO ||
|
||||
(right_deviation > best_deviation &&
|
||||
(!intersection[right_index].entry_allowed && in_data.distance > 30));
|
||||
// check if a turn is distinct enough
|
||||
const auto isDistinct = [&](const std::size_t index, const double deviation) {
|
||||
/*
|
||||
If the neighbor is not possible to enter, we allow for a lower
|
||||
distinction rate. If the road category is smaller, its also adjusted. Only
|
||||
roads of the same priority require the full distinction ratio.
|
||||
*/
|
||||
const auto adjusted_distinction_ratio = [&]() {
|
||||
// not allowed competitors are easily distinct
|
||||
if (!intersection[index].entry_allowed)
|
||||
return 0.7 * DISTINCTION_RATIO;
|
||||
// a bit less obvious are road classes
|
||||
else if (in_data.road_classification == best_data.road_classification &&
|
||||
best_data.road_classification.GetPriority() <
|
||||
node_based_graph.GetEdgeData(intersection[index].turn.eid)
|
||||
.road_classification.GetPriority())
|
||||
return 0.8 * DISTINCTION_RATIO;
|
||||
// if road classes are the same, we use the full ratio
|
||||
else
|
||||
return DISTINCTION_RATIO;
|
||||
}();
|
||||
return index == 0 || deviation / best_deviation >= adjusted_distinction_ratio ||
|
||||
(deviation <= NARROW_TURN_ANGLE && !intersection[index].entry_allowed);
|
||||
};
|
||||
|
||||
const bool distinct_to_left = isDistinct(left_index, left_deviation);
|
||||
const bool distinct_to_right = isDistinct(right_index, right_deviation);
|
||||
// Well distinct turn that is nearly straight
|
||||
if ((distinct_to_left || obvious_to_left) && (distinct_to_right || obvious_to_right))
|
||||
return best;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "extractor/guidance/turn_handler.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/intersection_scenario_three_way.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
#include "extractor/guidance/turn_handler.hpp"
|
||||
|
||||
#include "util/guidance/toolkit.hpp"
|
||||
|
||||
@ -207,18 +207,6 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
|
||||
}
|
||||
}
|
||||
|
||||
// check whether there is a turn of the same name
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
|
||||
const bool has_same_name_turn = [&]() {
|
||||
for (std::size_t i = 1; i < intersection.size(); ++i)
|
||||
{
|
||||
if (node_based_graph.GetEdgeData(intersection[i].turn.eid).name_id == in_data.name_id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
|
||||
// check whether the obvious choice is actually a through street
|
||||
if (obvious_index != 0)
|
||||
{
|
||||
@ -227,26 +215,6 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
|
||||
via_edge,
|
||||
isThroughStreet(obvious_index, intersection),
|
||||
intersection[obvious_index]);
|
||||
if (has_same_name_turn &&
|
||||
node_based_graph.GetEdgeData(intersection[obvious_index].turn.eid).name_id !=
|
||||
in_data.name_id &&
|
||||
intersection[obvious_index].turn.instruction.type == TurnType::NewName)
|
||||
{
|
||||
// this is a special case that is necessary to correctly handle obvious turns on
|
||||
// continuing streets. Right now osrm does not know about right of way. If a street
|
||||
// turns to the left just like:
|
||||
//
|
||||
// a
|
||||
// a
|
||||
// aaaaaaa b b
|
||||
//
|
||||
// And another road exits here, we don't want to call it a new name, even though the
|
||||
// turn is obvious and does not require steering. To correctly handle these situations
|
||||
// in turn collapsing, we use the turn + straight combination here
|
||||
intersection[obvious_index].turn.instruction.type = TurnType::Turn;
|
||||
intersection[obvious_index].turn.instruction.direction_modifier =
|
||||
DirectionModifier::Straight;
|
||||
}
|
||||
|
||||
// assign left/right turns
|
||||
intersection = assignLeftTurns(via_edge, std::move(intersection), obvious_index + 1);
|
||||
@ -553,9 +521,26 @@ std::pair<std::size_t, std::size_t> TurnHandler::findFork(const EdgeID via_edge,
|
||||
return true;
|
||||
}();
|
||||
|
||||
// check if all entries in the fork range allow entry
|
||||
const bool only_valid_entries = [&]() {
|
||||
BOOST_ASSERT(right <= left && left < intersection.size());
|
||||
|
||||
// one past the end of the fork range
|
||||
const auto end_itr = intersection.begin() + left + 1;
|
||||
|
||||
const auto has_entry_forbidden = [](const ConnectedRoad &road) {
|
||||
return !road.entry_allowed;
|
||||
};
|
||||
|
||||
const auto first_disallowed_entry =
|
||||
std::find_if(intersection.begin() + right, end_itr, has_entry_forbidden);
|
||||
// if no entry was found that forbids entry, the intersection entries are all valid.
|
||||
return first_disallowed_entry == end_itr;
|
||||
}();
|
||||
|
||||
// TODO check whether 2*NARROW_TURN is too large
|
||||
if (valid_indices && separated_at_left_side && separated_at_right_side &&
|
||||
not_more_than_three && !has_obvious && has_compatible_classes)
|
||||
not_more_than_three && !has_obvious && has_compatible_classes && only_valid_entries)
|
||||
return std::make_pair(right, left);
|
||||
}
|
||||
return std::make_pair(std::size_t{0}, std::size_t{0});
|
||||
|
Loading…
Reference in New Issue
Block a user