Scenario for unnecessary slight left onto Stralauer Str

This commit is contained in:
Daniel J. Hofmann 2016-08-08 11:07:27 +02:00 committed by Moritz Kobitzsch
parent 766e2713ab
commit da73bae9c6
6 changed files with 189 additions and 55 deletions

View File

@ -302,12 +302,12 @@ Feature: Collapse
Scenario: Entering a segregated road
Given the node map
| | a | f | | |
| | | | | g |
| | b | e | | |
| | | | | |
| | | | | |
| c | d | | | |
| | a | f | | | | g |
| | | | | | | |
| | b | e | | | | |
| | | | | | | |
| | | | | | | |
| c | d | | | | | |
And the ways
| nodes | highway | name | oneway |
@ -615,12 +615,12 @@ Feature: Collapse
Scenario: Forking before a turn (forky)
Given the node map
| | | | g | | |
| | | | | | |
| | | | c | | |
| a | b | | | | |
| | | | | d | |
| | | | | f | e |
| | | | | | g | | |
| | | | | | | | |
| | | | | | c | | |
| a | | | b | | | | |
| | | | | | | d | |
| | | | | | | f | e |
And the ways
| nodes | name | oneway | highway |

View File

@ -125,10 +125,10 @@ Feature: New-Name Instructions
| | | | | c |
And the ways
| nodes | highway |
| ab | residential |
| bc | residential |
| bd | service |
| nodes | highway | oneway |
| ab | residential | yes |
| bc | residential | yes |
| bd | service | yes |
When I route I should get
| waypoints | route | turns |

View File

@ -83,9 +83,9 @@ Feature: Ramp Guidance
Scenario: Ramp Off Though Street
Given the node map
| | | c |
| a | b | |
| | d | |
| | | | | c |
| a | | | b | |
| | | | d | |
And the ways
| nodes | highway |

View File

@ -930,3 +930,40 @@ Feature: Simple Turns
When I route I should get
| waypoints | turns | route |
| a,h | depart,off ramp right,turn sharp left,arrive | Blue Star Memorial Hwy,bcde,Centreville Road,Centreville Road |
# https://www.openstreetmap.org/#map=20/52.51609/13.41080
Scenario: Unnecessary Slight Left onto Stralauer Strasse
Given the node map
| | e | | | | | |
| | | | | | | |
| a | | b | | c | | d |
And the ways
| nodes | name | highway | oneway |
| ab | Molkenmarkt | secondary | yes |
| bc | Stralauer Str | secondary | yes |
| cd | Stralauer Str | secondary | yes |
| ec | Molkenmarkt | secondary | yes |
When I route I should get
| waypoints | turns | route |
| a,d | depart,arrive | Molkenmarkt,Stralauer Str |
| e,d | depart,arrive | Molkenmarkt,Stralauer Str |
Scenario: Unnecessary Slight Left onto Stralauer Strasse
Given the node map
| | e | | | | | |
| | | | | | | |
| a | | b | | c | | d |
And the ways
| nodes | name | highway | oneway |
| ab | Molkenmarkt | secondary | yes |
| bc | Molkenmarkt | secondary | yes |
| cd | Stralauer Str | secondary | yes |
| ec | Molkenmarkt | secondary | yes |
When I route I should get
| waypoints | turns | route |
| a,d | depart,arrive | Molkenmarkt,Stralauer Str |
| e,d | depart,arrive | Molkenmarkt,Stralauer Str |

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/intersection_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection_handler.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "util/coordinate_calculation.hpp"
@ -341,15 +341,28 @@ bool IntersectionHandler::isThroughStreet(const std::size_t index,
{
if (node_based_graph.GetEdgeData(intersection[index].turn.eid).name_id == EMPTY_NAMEID)
return false;
for (const auto &road : intersection)
const auto &data_at_index = node_based_graph.GetEdgeData(intersection[index].turn.eid);
// a through street cannot start at our own position -> index 1
for (std::size_t road_index = 1; road_index < intersection.size(); ++road_index)
{
// a through street cannot start at our own position
if (road.turn.angle < std::numeric_limits<double>::epsilon())
if (road_index == index)
continue;
if (angularDeviation(road.turn.angle, intersection[index].turn.angle) >
(STRAIGHT_ANGLE - NARROW_TURN_ANGLE) &&
node_based_graph.GetEdgeData(road.turn.eid).name_id ==
node_based_graph.GetEdgeData(intersection[index].turn.eid).name_id)
const auto &road = intersection[road_index];
const auto &road_data = node_based_graph.GetEdgeData(road.turn.eid);
// roads have a near straight angle (180 degree)
const bool is_nearly_straight =
angularDeviation(road.turn.angle, intersection[index].turn.angle) >
(STRAIGHT_ANGLE - FUZZY_ANGLE_DIFFERENCE);
const bool have_same_name = data_at_index.name_id == road_data.name_id;
const bool have_same_category =
data_at_index.road_classification == road_data.road_classification;
if (is_nearly_straight && have_same_name && have_same_category)
return true;
}
return false;
@ -375,19 +388,29 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const EdgeData &in_data = node_based_graph.GetEdgeData(via_edge);
const auto in_classification = in_data.road_classification;
const auto obvious_by_road_class = [](const RoadClassification in_classification,
const RoadClassification obvious_candidate,
const RoadClassification compare_candidate) {
const bool has_high_priority =
2 * obvious_candidate.GetPriority() < compare_candidate.GetPriority();
const bool continues_on_same_class = in_classification == obvious_candidate;
return (has_high_priority && continues_on_same_class) ||
(!obvious_candidate.IsLowPriorityRoadClass() &&
compare_candidate.IsLowPriorityRoadClass());
};
for (std::size_t i = 1; i < intersection.size(); ++i)
{
const double deviation = angularDeviation(intersection[i].turn.angle, STRAIGHT_ANGLE);
if (intersection[i].entry_allowed && deviation < best_deviation)
{
best_deviation = deviation;
best = i;
}
if (!intersection[i].entry_allowed)
continue;
const auto out_data = node_based_graph.GetEdgeData(intersection[i].turn.eid);
auto continue_class =
const auto continue_class =
node_based_graph.GetEdgeData(intersection[best_continue].turn.eid).road_classification;
if (intersection[i].entry_allowed && out_data.name_id == in_data.name_id &&
if (out_data.name_id == in_data.name_id &&
(best_continue == 0 ||
(continue_class.GetPriority() > out_data.road_classification.GetPriority() &&
in_classification != continue_class) ||
@ -399,19 +422,50 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
best_continue_deviation = deviation;
best_continue = i;
}
const auto current_best_class =
node_based_graph.GetEdgeData(intersection[best_continue].turn.eid).road_classification;
// don't prefer low priority classes
if (out_data.road_classification.IsLowPriorityRoadClass() &&
!current_best_class.IsLowPriorityRoadClass())
continue;
const bool is_better_choice_by_priority = obvious_by_road_class(
in_data.road_classification, out_data.road_classification, current_best_class);
const bool other_is_better_choice_by_priority = obvious_by_road_class(
in_data.road_classification, current_best_class, out_data.road_classification);
if ((!other_is_better_choice_by_priority && deviation < best_deviation) ||
is_better_choice_by_priority)
{
best_deviation = deviation;
best = i;
}
}
std::cout << "Chose Best: " << best << std::endl;
if (best == 0)
return 0;
if (best_deviation >= 2 * NARROW_TURN_ANGLE)
return 0;
const std::size_t num_continue_names = [&]() {
std::size_t count = 0;
for (const auto &road : intersection)
if (in_data.name_id == node_based_graph.GetEdgeData(road.turn.eid).name_id)
++count;
return count;
}();
// has no obvious continued road
if (best_continue == 0 || best_continue_deviation >= 2 * NARROW_TURN_ANGLE ||
num_continue_names > 2 ||
(node_based_graph.GetEdgeData(intersection[best_continue].turn.eid).road_classification ==
node_based_graph.GetEdgeData(intersection[best].turn.eid).road_classification &&
std::abs(best_continue_deviation) > 1 && best_deviation / best_continue_deviation < 0.75))
{
std::cout << "Checking best" << std::endl;
// Find left/right deviation
const double left_deviation = angularDeviation(
intersection[(best + 1) % intersection.size()].turn.angle, STRAIGHT_ANGLE);
@ -422,26 +476,56 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
return best;
const auto &best_data = node_based_graph.GetEdgeData(intersection[best].turn.eid);
const auto left_index = (best + 1) % intersection.size();
const auto right_index = best - 1;
const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].turn.eid);
const auto &right_data = node_based_graph.GetEdgeData(intersection[right_index].turn.eid);
const bool obvious_to_left =
left_index == 0 || obvious_by_road_class(in_data.road_classification,
best_data.road_classification,
left_data.road_classification);
const bool obvious_to_right =
right_index == 0 || obvious_by_road_class(in_data.road_classification,
best_data.road_classification,
right_data.road_classification);
// other narrow turns?
if (angularDeviation(intersection[best - 1].turn.angle, STRAIGHT_ANGLE) <=
FUZZY_ANGLE_DIFFERENCE)
if (angularDeviation(intersection[right_index].turn.angle, STRAIGHT_ANGLE) <=
FUZZY_ANGLE_DIFFERENCE &&
!obvious_to_right)
{
std::cout << "Index to the right prevents it." << std::endl;
return 0;
if (angularDeviation(intersection[(best + 1) % intersection.size()].turn.angle,
STRAIGHT_ANGLE) <= FUZZY_ANGLE_DIFFERENCE)
}
if (angularDeviation(intersection[left_index].turn.angle, STRAIGHT_ANGLE) <=
FUZZY_ANGLE_DIFFERENCE &&
!obvious_to_left)
{
std::cout << "Index to the left prevents it." << std::endl;
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));
// Well distinct turn that is nearly straight
if ((left_deviation / best_deviation >= DISTINCTION_RATIO ||
(left_deviation > best_deviation &&
!intersection[(best + 1) % intersection.size()].entry_allowed)) &&
(right_deviation / best_deviation >= DISTINCTION_RATIO ||
(right_deviation > best_deviation && !intersection[best - 1].entry_allowed)))
{
if ((distinct_to_left || obvious_to_left) && (distinct_to_right || obvious_to_right))
return best;
}
std::cout << "Failed: " << distinct_to_left << " " << distinct_to_right << " "
<< obvious_to_left << " " << obvious_to_right << std::endl;
}
else
{
std::cout << "Checking best continue" << std::endl;
const double deviation =
angularDeviation(intersection[best_continue].turn.angle, STRAIGHT_ANGLE);
const auto &continue_data =
@ -456,8 +540,10 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
continue;
if (angularDeviation(intersection[i].turn.angle, STRAIGHT_ANGLE) / deviation < 1.1 &&
continue_data.road_classification ==
node_based_graph.GetEdgeData(intersection[i].turn.eid).road_classification)
!obvious_by_road_class(
in_data.road_classification,
continue_data.road_classification,
node_based_graph.GetEdgeData(intersection[i].turn.eid).road_classification))
return 0;
}
return best_continue; // no obvious turn

View File

@ -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"
@ -124,6 +124,11 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
const auto &first_data = node_based_graph.GetEdgeData(intersection[1].turn.eid);
const auto &second_data = node_based_graph.GetEdgeData(intersection[2].turn.eid);
const auto obvious_index = findObviousTurn(via_edge, intersection);
std::cout << "[intersection]\n";
for (auto road : intersection)
std::cout << "\t" << toString(road) << std::endl;
std::cout << "Obvious: " << obvious_index << std::endl;
BOOST_ASSERT(intersection[0].turn.angle < 0.001);
/* Two nearly straight turns -> FORK
OOOOOOO
@ -143,9 +148,7 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
I
I
*/
else if (isEndOfRoad(intersection[0], intersection[1], intersection[2]) &&
!isObviousOfTwo(via_edge, intersection[1], intersection[2]) &&
!isObviousOfTwo(via_edge, intersection[2], intersection[1]))
else if (isEndOfRoad(intersection[0], intersection[1], intersection[2]) && obvious_index == 0)
{
if (intersection[1].entry_allowed)
{
@ -165,9 +168,12 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
}
else
{
if (isObviousOfTwo(via_edge, intersection[1], intersection[2]) &&
std::cout << "Name IDs: " << (int)in_data.name_id << " " << (int)first_data.name_id << " "
<< (int)second_data.name_id << std::endl;
if (obvious_index == 1 &&
(in_data.name_id != second_data.name_id || first_data.name_id == second_data.name_id))
{
std::cout << "Assigning Obvious first" << std::endl;
intersection[1].turn.instruction = getInstructionForObvious(
3, via_edge, isThroughStreet(1, intersection), intersection[1]);
}
@ -177,9 +183,10 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
getTurnDirection(intersection[1].turn.angle)};
}
if (isObviousOfTwo(via_edge, intersection[2], intersection[1]) &&
if (obvious_index == 2 &&
(in_data.name_id != first_data.name_id || first_data.name_id == second_data.name_id))
{
std::cout << "Assigning Obvious Second" << std::endl;
intersection[2].turn.instruction = getInstructionForObvious(
3, via_edge, isThroughStreet(2, intersection), intersection[2]);
}
@ -195,6 +202,10 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection intersection) const
{
const std::size_t obvious_index = findObviousTurn(via_edge, intersection);
std::cout << "[intersection]\n";
for (auto road : intersection)
std::cout << "\t" << toString(road) << std::endl;
std::cout << "Obvious: " << obvious_index << std::endl;
const auto fork_range = findFork(via_edge, intersection);
std::size_t straightmost_turn = 0;
double straightmost_deviation = 180;