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,c | ab,bc,bc | depart,fork slight left,arrive |
|
||||||
| a,d | ab,bd,bd | depart,fork slight right,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
|
Scenario: Do not fork on link type
|
||||||
Given the node map
|
Given the node map
|
||||||
| | | | | c |
|
| | | | | c |
|
||||||
|
@ -133,6 +133,22 @@ Feature: Simple Turns
|
|||||||
| d,c | db,cb,cb | depart,turn right,arrive |
|
| d,c | db,cb,cb | depart,turn right,arrive |
|
||||||
| d,a | db,ab,ab | depart,new name straight,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
|
Scenario: Three Way Intersection on Through Street
|
||||||
Given the node map
|
Given the node map
|
||||||
| | d | |
|
| | d | |
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "extractor/guidance/constants.hpp"
|
|
||||||
#include "extractor/guidance/intersection_handler.hpp"
|
#include "extractor/guidance/intersection_handler.hpp"
|
||||||
|
#include "extractor/guidance/constants.hpp"
|
||||||
#include "extractor/guidance/toolkit.hpp"
|
#include "extractor/guidance/toolkit.hpp"
|
||||||
|
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
@ -534,26 +534,48 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
|||||||
best_data.road_classification,
|
best_data.road_classification,
|
||||||
right_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?
|
// other narrow turns?
|
||||||
if (angularDeviation(intersection[right_index].turn.angle, STRAIGHT_ANGLE) <=
|
if (check_narrow(right_index) && !obvious_to_right)
|
||||||
FUZZY_ANGLE_DIFFERENCE &&
|
|
||||||
!obvious_to_right)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (angularDeviation(intersection[left_index].turn.angle, STRAIGHT_ANGLE) <=
|
if (check_narrow(left_index) && !obvious_to_left)
|
||||||
FUZZY_ANGLE_DIFFERENCE &&
|
|
||||||
!obvious_to_left)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const bool distinct_to_left =
|
// check if a turn is distinct enough
|
||||||
left_deviation / best_deviation >= DISTINCTION_RATIO ||
|
const auto isDistinct = [&](const std::size_t index, const double deviation) {
|
||||||
(left_deviation > best_deviation &&
|
/*
|
||||||
(!intersection[left_index].entry_allowed && in_data.distance > 30));
|
If the neighbor is not possible to enter, we allow for a lower
|
||||||
const bool distinct_to_right =
|
distinction rate. If the road category is smaller, its also adjusted. Only
|
||||||
right_deviation / best_deviation >= DISTINCTION_RATIO ||
|
roads of the same priority require the full distinction ratio.
|
||||||
(right_deviation > best_deviation &&
|
*/
|
||||||
(!intersection[right_index].entry_allowed && in_data.distance > 30));
|
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
|
// Well distinct turn that is nearly straight
|
||||||
if ((distinct_to_left || obvious_to_left) && (distinct_to_right || obvious_to_right))
|
if ((distinct_to_left || obvious_to_left) && (distinct_to_right || obvious_to_right))
|
||||||
return best;
|
return best;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "extractor/guidance/turn_handler.hpp"
|
|
||||||
#include "extractor/guidance/constants.hpp"
|
#include "extractor/guidance/constants.hpp"
|
||||||
#include "extractor/guidance/intersection_scenario_three_way.hpp"
|
#include "extractor/guidance/intersection_scenario_three_way.hpp"
|
||||||
#include "extractor/guidance/toolkit.hpp"
|
#include "extractor/guidance/toolkit.hpp"
|
||||||
|
#include "extractor/guidance/turn_handler.hpp"
|
||||||
|
|
||||||
#include "util/guidance/toolkit.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
|
// check whether the obvious choice is actually a through street
|
||||||
if (obvious_index != 0)
|
if (obvious_index != 0)
|
||||||
{
|
{
|
||||||
@ -227,26 +215,6 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
|
|||||||
via_edge,
|
via_edge,
|
||||||
isThroughStreet(obvious_index, intersection),
|
isThroughStreet(obvious_index, intersection),
|
||||||
intersection[obvious_index]);
|
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
|
// assign left/right turns
|
||||||
intersection = assignLeftTurns(via_edge, std::move(intersection), obvious_index + 1);
|
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;
|
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
|
// TODO check whether 2*NARROW_TURN is too large
|
||||||
if (valid_indices && separated_at_left_side && separated_at_right_side &&
|
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(right, left);
|
||||||
}
|
}
|
||||||
return std::make_pair(std::size_t{0}, std::size_t{0});
|
return std::make_pair(std::size_t{0}, std::size_t{0});
|
||||||
|
Loading…
Reference in New Issue
Block a user