From a1f1da4c160227dc4169975ed4eb9200caee6ca0 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Fri, 4 Mar 2016 12:17:06 +0100 Subject: [PATCH] improved fork handling --- include/extractor/guidance/turn_analysis.hpp | 11 ++ src/extractor/guidance/turn_analysis.cpp | 169 ++++++++++++++++--- 2 files changed, 160 insertions(+), 20 deletions(-) diff --git a/include/extractor/guidance/turn_analysis.hpp b/include/extractor/guidance/turn_analysis.hpp index 29be643fe..768316f3e 100644 --- a/include/extractor/guidance/turn_analysis.hpp +++ b/include/extractor/guidance/turn_analysis.hpp @@ -221,6 +221,17 @@ AnalyzeTurn(const NodeID node_u, const double angle, const std::shared_ptr node_based_graph); +// Assignment of specific turn types +void assignFork(const EdgeID via_edge, + TurnCandidate &left, + TurnCandidate &right, + const std::shared_ptr node_based_graph); +void assignFork(const EdgeID via_edge, + TurnCandidate &left, + TurnCandidate ¢er, + TurnCandidate &right, + const std::shared_ptr node_based_graph); + } // namespace detail } // namespace guidance } // namespace extractor diff --git a/src/extractor/guidance/turn_analysis.cpp b/src/extractor/guidance/turn_analysis.cpp index b64ae7451..52a7bdbde 100644 --- a/src/extractor/guidance/turn_analysis.cpp +++ b/src/extractor/guidance/turn_analysis.cpp @@ -4,6 +4,7 @@ #include "util/coordinate.hpp" #include +#include namespace osrm { @@ -29,6 +30,11 @@ const unsigned constexpr INVALID_NAME_ID = 0; using EdgeData = util::NodeBasedDynamicGraph::EdgeData; +bool requiresAnnouncedment(const EdgeData &from, const EdgeData &to) +{ + return !from.IsCompatibleTo(to); +} + struct Localizer { const std::vector *node_info_list = nullptr; @@ -282,7 +288,6 @@ inline std::vector fallbackTurnAssignmentMotorway( std::vector turn_candidates, const std::shared_ptr node_based_graph) { - util::SimpleLogger().Write(logWARNING) << "Fallback turn assignment"; for (auto &candidate : turn_candidates) { const auto &out_data = node_based_graph->GetEdgeData(candidate.eid); @@ -390,8 +395,7 @@ handleFromMotorway(const NodeID from, // splitting ramp at the end of a highway if (turn_candidates[1].valid && turn_candidates[2].valid) { - turn_candidates[1].instruction = {TurnType::Fork, DirectionModifier::SlightRight}; - turn_candidates[2].instruction = {TurnType::Fork, DirectionModifier::SlightLeft}; + assignFork(via_edge, turn_candidates[2], turn_candidates[1], node_based_graph); } else { @@ -404,11 +408,13 @@ handleFromMotorway(const NodeID from, getTurnDirection(turn_candidates[2].angle)}; } } - else + else if (countValid(turn_candidates)) // check whether turns exist at all { // FALLBACK, this should hopefully never be reached + auto coord = localizer(node_based_graph->GetTarget(via_edge)); util::SimpleLogger().Write(logWARNING) - << "Fallback reached from motorway, no continue angle, " << turn_candidates.size() + << "Fallback reached from motorway at " << toFloating(coord.lat) << " " + << toFloating(coord.lon) << ", no continue angle, " << turn_candidates.size() << " candidates, " << countValid(turn_candidates) << " valid ones."; fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); } @@ -486,21 +492,71 @@ handleFromMotorway(const NodeID from, turn_candidates[1].instruction = getInstructionForObvious(from, via_edge, turn_candidates[1], node_based_graph); util::SimpleLogger().Write(logWARNING) - << "Disable U-Turn on a freeway at " + << "Disabled U-Turn on a freeway at " << localizer(node_based_graph->GetTarget(via_edge)); turn_candidates[0].valid = false; // UTURN on the freeway } - else if (exiting_motorways != 2 || turn_candidates.size() != 3) + else if (exiting_motorways == 2) { - util::SimpleLogger().Write(logWARNING) << "Found motorway junction with more than " - "2 exiting motorways or additional ramps!" - << std::endl; - fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); + // standard fork + std::size_t first_valid = std::numeric_limits::max(), + second_valid = std::numeric_limits::max(); + for (std::size_t i = 0; i < turn_candidates.size(); ++i) + { + if (turn_candidates[i].valid && + isMotorwayClass(turn_candidates[i].eid, node_based_graph)) + { + if (first_valid < turn_candidates.size()) + { + second_valid = i; + break; + } + else + { + first_valid = i; + } + } + } + assignFork(via_edge, turn_candidates[second_valid], turn_candidates[first_valid], + node_based_graph); + } + else if (exiting_motorways == 3) + { + // triple fork + std::size_t first_valid = std::numeric_limits::max(), + second_valid = std::numeric_limits::max(), + third_valid = std::numeric_limits::max(); + for (std::size_t i = 0; i < turn_candidates.size(); ++i) + { + if (turn_candidates[i].valid && + isMotorwayClass(turn_candidates[i].eid, node_based_graph)) + { + if (second_valid < turn_candidates.size()) + { + third_valid = i; + break; + } + else if (first_valid < turn_candidates.size()) + { + second_valid = i; + } + else + { + first_valid = i; + } + } + } + assignFork(via_edge, turn_candidates[third_valid], turn_candidates[second_valid], + turn_candidates[first_valid], node_based_graph); } else { - turn_candidates[1].instruction = {TurnType::Fork, DirectionModifier::SlightRight}; - turn_candidates[2].instruction = {TurnType::Fork, DirectionModifier::SlightLeft}; + auto coord = localizer(node_based_graph->GetTarget(via_edge)); + util::SimpleLogger().Write(logWARNING) + << "Found motorway junction with more than " + "2 exiting motorways or additional ramps at " << toFloating(coord.lat) << " " + << toFloating(coord.lon); + fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); } } // done for more than one highway exit } @@ -596,8 +652,8 @@ handleMotorwayRamp(const NodeID from, if (isMotorwayClass(turn_candidates[1].eid, node_based_graph) && isMotorwayClass(turn_candidates[2].eid, node_based_graph)) { - turn_candidates[1].instruction = {TurnType::Merge, DirectionModifier::SlightRight}; - turn_candidates[2].instruction = {TurnType::Merge, DirectionModifier::SlightLeft}; + assignFork(via_edge, turn_candidates[2], turn_candidates[1], + node_based_graph); } else { @@ -743,11 +799,13 @@ bool isMotorwayJunction(const NodeID from, angularDeviation(candidate.angle, 180) > 35) || (candidate.valid && angularDeviation(candidate.angle, 0) < 35)) return false; - else if (candidate.valid && - (out_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY || - out_data.road_classification.road_class == FunctionalRoadClass::TRUNK)) - has_motorway = true; - else if (candidate.valid && !isRampClass(out_data.road_classification.road_class)) + else if (out_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY || + out_data.road_classification.road_class == FunctionalRoadClass::TRUNK) + { + if (candidate.valid) + has_motorway = true; + } + else if (!isRampClass(out_data.road_classification.road_class)) has_normal_roads = true; } @@ -1906,6 +1964,77 @@ handleConflicts(const NodeID from, return turn_candidates; } +void assignFork(const EdgeID via_edge, + TurnCandidate &left, + TurnCandidate &right, + const std::shared_ptr node_based_graph) +{ + const auto &in_data = node_based_graph->GetEdgeData(via_edge); + { // left fork + const auto &out_data = node_based_graph->GetEdgeData(left.eid); + if (angularDeviation(left.angle, 180) < FUZZY_ANGLE_DIFFERENCE) + { + if (requiresAnnouncedment(in_data, out_data)) + { + left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft}; + } + else + { + left.instruction = {TurnType::Suppressed, DirectionModifier::Straight}; + } + } + else + { + left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft}; + } + } + { // right fork + const auto &out_data = node_based_graph->GetEdgeData(right.eid); + if (angularDeviation(right.angle, 180) < FUZZY_ANGLE_DIFFERENCE) + { + if (requiresAnnouncedment(in_data, out_data)) + { + right.instruction = {TurnType::Fork, DirectionModifier::SlightRight}; + } + else + { + right.instruction = {TurnType::Suppressed, DirectionModifier::Straight}; + } + } + else + { + right.instruction = {TurnType::Fork, DirectionModifier::SlightRight}; + } + } +} + +void assignFork(const EdgeID via_edge, + TurnCandidate &left, + TurnCandidate ¢er, + TurnCandidate &right, + const std::shared_ptr node_based_graph) +{ + left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft}; + if (angularDeviation(center.angle, 180) < FUZZY_ANGLE_DIFFERENCE) + { + const auto &in_data = node_based_graph->GetEdgeData(via_edge); + const auto &out_data = node_based_graph->GetEdgeData(center.eid); + if (requiresAnnouncedment(in_data, out_data)) + { + center.instruction = {TurnType::Fork, DirectionModifier::Straight}; + } + else + { + center.instruction = {TurnType::Suppressed, DirectionModifier::Straight}; + } + } + else + { + center.instruction = {TurnType::Fork, DirectionModifier::Straight}; + } + right.instruction = {TurnType::Fork, DirectionModifier::SlightRight}; +} + } // anemspace detail } // namespace guidance } // namespace extractor