From 9123c93a906eeda294341ecb418a9b855febd88f Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Tue, 6 Sep 2016 15:47:03 +0200 Subject: [PATCH] fix interaction between sliproads/segregated intersections --- features/guidance/advanced-lanes.feature | 60 ++----------------- features/guidance/turn-lanes.feature | 10 ++-- .../routing_algorithms/routing_base.hpp | 18 +++--- .../extractor/guidance/motorway_handler.hpp | 2 +- .../extractor/guidance/roundabout_handler.hpp | 2 +- include/extractor/guidance/toolkit.hpp | 2 +- include/extractor/guidance/turn_handler.hpp | 2 +- include/util/node_based_graph.hpp | 5 +- .../guidance/intersection_handler.cpp | 24 ++++++-- src/extractor/guidance/motorway_handler.cpp | 2 +- src/extractor/guidance/roundabout_handler.cpp | 2 +- src/extractor/guidance/sliproad_handler.cpp | 6 +- src/extractor/guidance/turn_analysis.cpp | 2 +- src/extractor/guidance/turn_handler.cpp | 2 +- src/extractor/guidance/turn_lane_handler.cpp | 42 +++++++------ src/extractor/guidance/turn_lane_matcher.cpp | 3 + 16 files changed, 73 insertions(+), 111 deletions(-) diff --git a/features/guidance/advanced-lanes.feature b/features/guidance/advanced-lanes.feature index 50a9a49d2..dc6e413fb 100644 --- a/features/guidance/advanced-lanes.feature +++ b/features/guidance/advanced-lanes.feature @@ -132,55 +132,7 @@ Feature: Turn Lane Guidance | a,i | ,ksd,ksd | depart,turn right,arrive | ,left:false none:true right:true, | @todo @bug @2650 @sliproads - #market and haight in SF - #http://www.openstreetmap.org/#map=19/37.77308/-122.42238 - Scenario: Through Street Crossing Mid-Turn - Given the node map - | | | | | | | | g | j | | - | | | | | | | | | | | - | | | | | | | | | | | - | | | | | | | | | | | - | | | | | | k | | | | | - | | | | | | | | | | | - | | | | | | | | | | f | - | | | | | | | | | e | | - | | | | | | | | d | | | - | | | | | | | | | | | - | a | | | b | | | | | | | - | | | | | | | | c | | | - | | | | | | | | | | | - | | | | | | | | | | | - | | | | | | | | | | | - | | | | | | | | | | | - | | | | | | | | | | | - | | | l | | | | | h | i | | - - And the ways - | nodes | name | highway | oneway | turn:lanes:forward | - | ab | ghough | secondary | yes | | - | bc | ghough | secondary | yes | through\|through | - | bd | ghough | secondary | yes | none\|through | - | def | ghough | secondary | yes | | - | gd | market | primary | yes | | - | dc | market | primary | yes | | - | ch | market | primary | yes | | - | iej | market | primary | yes | | - | gkb | haight | residential | yes | | - | bl | haight | residential | yes | left\|none | - - And the relations - | type | way:from | way:to | node:via | restriction | - | relation | bd | dc | d | no_right_turn | - - When I route I should get - | waypoints | route | turns | lanes | - | a,l | ghough,haight,haight | depart,turn right,arrive | ,none:false straight:false straight:false straight:true, | - | a,h | ghough,market,market | depart,turn slight right,arrive | ,none:false straight:false straight:true straight:true, | - | a,j | ghough,market,market | depart,turn left,arrive | ,none:true straight:false straight:false straight:false, | - | a,f | ghough,ghough,ghough | depart,continue slight left,arrive | ,none:true straight:true straight:false straight:false, | - - @todo @bug @2650 @sliproads - #market and haight in SF + #market and haight in SF, restricted turn #http://www.openstreetmap.org/#map=19/37.77308/-122.42238 Scenario: Market/Haight without Through Street Given the node map @@ -209,8 +161,8 @@ Feature: Turn Lane Guidance | bd | ghough | secondary | yes | none\|through | | def | ghough | secondary | yes | | | gd | market | primary | yes | | - | dc | market | primary | yes | | - | ch | market | primary | yes | | + | dc | market | primary | yes | | + | ch | market | primary | yes | | | iej | market | primary | yes | | | bl | haight | residential | yes | left\|none | @@ -226,7 +178,7 @@ Feature: Turn Lane Guidance | a,f | ghough,ghough,ghough | depart,continue slight left,arrive | ,none:true straight:true straight:false straight:false, | @todo @2650 @bug @sliproads - #market and haight in SF + #market and haight in SF, unrestricted #http://www.openstreetmap.org/#map=19/37.77308/-122.42238 Scenario: Market/Haight without Through Street Given the node map @@ -255,8 +207,8 @@ Feature: Turn Lane Guidance | bd | ghough | secondary | yes | none\|through | | def | ghough | secondary | yes | | | gd | market | primary | yes | | - | dc | market | primary | yes | | - | ch | market | primary | yes | | + | dc | market | primary | yes | | + | ch | market | primary | yes | | | iej | market | primary | yes | | | bl | haight | residential | yes | left\|none | diff --git a/features/guidance/turn-lanes.feature b/features/guidance/turn-lanes.feature index 34c7cbf8d..e1d493b49 100644 --- a/features/guidance/turn-lanes.feature +++ b/features/guidance/turn-lanes.feature @@ -499,11 +499,11 @@ Feature: Turn Lane Guidance @reverse @previous-lanes Scenario: U-Turn Road at Intersection Given the node map - | | | | | | h | | - | | | | | f | e | j | - | a | b | | | | | | - | | | | | c | d | i | - | | | | | | g | | + | | | | | | | h | | + | | | | | f | | e | j | + | a | b | | | | | | | + | | | | | c | | d | i | + | | | | | | | g | | And the ways | nodes | name | turn:lanes:forward | oneway | highway | diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index 1d198c5f7..6951209d1 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -702,15 +702,15 @@ template class BasicRoutingInterface } } - const auto insertInCoreHeap = - [](const CoreEntryPoint &p, SearchEngineData::QueryHeap &core_heap) { - NodeID id; - EdgeWeight weight; - NodeID parent; - // TODO this should use std::apply when we get c++17 support - std::tie(id, weight, parent) = p; - core_heap.Insert(id, weight, parent); - }; + const auto insertInCoreHeap = [](const CoreEntryPoint &p, + SearchEngineData::QueryHeap &core_heap) { + NodeID id; + EdgeWeight weight; + NodeID parent; + // TODO this should use std::apply when we get c++17 support + std::tie(id, weight, parent) = p; + core_heap.Insert(id, weight, parent); + }; forward_core_heap.Clear(); for (const auto &p : forward_entry_points) diff --git a/include/extractor/guidance/motorway_handler.hpp b/include/extractor/guidance/motorway_handler.hpp index 2034f5306..789545bab 100644 --- a/include/extractor/guidance/motorway_handler.hpp +++ b/include/extractor/guidance/motorway_handler.hpp @@ -2,8 +2,8 @@ #define OSRM_EXTRACTOR_GUIDANCE_MOTORWAY_HANDLER_HPP_ #include "extractor/guidance/intersection.hpp" -#include "extractor/guidance/intersection_handler.hpp" #include "extractor/guidance/intersection_generator.hpp" +#include "extractor/guidance/intersection_handler.hpp" #include "extractor/query_node.hpp" #include "util/attributes.hpp" diff --git a/include/extractor/guidance/roundabout_handler.hpp b/include/extractor/guidance/roundabout_handler.hpp index c352a027f..9aee76975 100644 --- a/include/extractor/guidance/roundabout_handler.hpp +++ b/include/extractor/guidance/roundabout_handler.hpp @@ -3,8 +3,8 @@ #include "extractor/compressed_edge_container.hpp" #include "extractor/guidance/intersection.hpp" -#include "extractor/guidance/intersection_handler.hpp" #include "extractor/guidance/intersection_generator.hpp" +#include "extractor/guidance/intersection_handler.hpp" #include "extractor/guidance/roundabout_type.hpp" #include "extractor/profile_properties.hpp" #include "extractor/query_node.hpp" diff --git a/include/extractor/guidance/toolkit.hpp b/include/extractor/guidance/toolkit.hpp index 4d7dc2e09..0ac4f1b1c 100644 --- a/include/extractor/guidance/toolkit.hpp +++ b/include/extractor/guidance/toolkit.hpp @@ -211,7 +211,7 @@ inline bool requiresNameAnnounced(const std::string &from, const auto first_prefix_and_suffixes = getPrefixAndSuffix(first); const auto second_prefix_and_suffixes = getPrefixAndSuffix(second); // reverse strings, get suffices and reverse them to get prefixes - const auto checkTable = [&](const std::string& str) { + const auto checkTable = [&](const std::string &str) { return str.empty() || suffix_table.isSuffix(str); }; diff --git a/include/extractor/guidance/turn_handler.hpp b/include/extractor/guidance/turn_handler.hpp index 116778c84..69feae162 100644 --- a/include/extractor/guidance/turn_handler.hpp +++ b/include/extractor/guidance/turn_handler.hpp @@ -2,8 +2,8 @@ #define OSRM_EXTRACTOR_GUIDANCE_TURN_HANDLER_HPP_ #include "extractor/guidance/intersection.hpp" -#include "extractor/guidance/intersection_handler.hpp" #include "extractor/guidance/intersection_generator.hpp" +#include "extractor/guidance/intersection_handler.hpp" #include "extractor/query_node.hpp" #include "util/attributes.hpp" diff --git a/include/util/node_based_graph.hpp b/include/util/node_based_graph.hpp index 9fd6bf1c1..c5981c665 100644 --- a/include/util/node_based_graph.hpp +++ b/include/util/node_based_graph.hpp @@ -53,9 +53,8 @@ struct NodeBasedEdgeData bool IsCompatibleTo(const NodeBasedEdgeData &other) const { - return (reversed == other.reversed) && - (roundabout == other.roundabout) && (startpoint == other.startpoint) && - (access_restricted == other.access_restricted) && + return (reversed == other.reversed) && (roundabout == other.roundabout) && + (startpoint == other.startpoint) && (access_restricted == other.access_restricted) && (travel_mode == other.travel_mode) && (road_classification == other.road_classification); } diff --git a/src/extractor/guidance/intersection_handler.cpp b/src/extractor/guidance/intersection_handler.cpp index c35d849cd..1f521f634 100644 --- a/src/extractor/guidance/intersection_handler.cpp +++ b/src/extractor/guidance/intersection_handler.cpp @@ -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" @@ -457,8 +457,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge, if (best == 0) return 0; - const std::pair num_continue_names = [&]() { - std::size_t count = 0, count_valid = 0; + const std::pair num_continue_names = [&]() { + std::int64_t count = 0, count_valid = 0; if (in_data.name_id != EMPTY_NAMEID) { for (std::size_t i = 1; i < intersection.size(); ++i) @@ -486,11 +486,25 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge, return 0; } + const bool all_continues_are_narrow = [&]() { + if (in_data.name_id == EMPTY_NAMEID) + return false; + + return std::count_if( + intersection.begin() + 1, intersection.end(), [&](const ConnectedRoad &road) { + return (in_data.name_id == + node_based_graph.GetEdgeData(road.turn.eid).name_id) && + angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < NARROW_TURN_ANGLE; + }) == num_continue_names.first; + }(); + // has no obvious continued road const auto &best_data = node_based_graph.GetEdgeData(intersection[best].turn.eid); - if (best_continue == 0 || (num_continue_names.first >= 2 && intersection.size() >= 4) || + if (best_continue == 0 || (!all_continues_are_narrow && + (num_continue_names.first >= 2 && intersection.size() >= 4)) || (num_continue_names.second >= 2 && best_continue_deviation >= 2 * NARROW_TURN_ANGLE) || - (best_deviation < FUZZY_ANGLE_DIFFERENCE && !best_data.road_classification.IsRampClass())) + (best_deviation != best_continue_deviation && best_deviation < FUZZY_ANGLE_DIFFERENCE && + !best_data.road_classification.IsRampClass())) { // Find left/right deviation const double left_deviation = angularDeviation( diff --git a/src/extractor/guidance/motorway_handler.cpp b/src/extractor/guidance/motorway_handler.cpp index 01b0748fe..d9ed02c08 100644 --- a/src/extractor/guidance/motorway_handler.cpp +++ b/src/extractor/guidance/motorway_handler.cpp @@ -1,5 +1,5 @@ -#include "extractor/guidance/constants.hpp" #include "extractor/guidance/motorway_handler.hpp" +#include "extractor/guidance/constants.hpp" #include "extractor/guidance/road_classification.hpp" #include "extractor/guidance/toolkit.hpp" diff --git a/src/extractor/guidance/roundabout_handler.cpp b/src/extractor/guidance/roundabout_handler.cpp index c21dd4505..24ca74e5f 100644 --- a/src/extractor/guidance/roundabout_handler.cpp +++ b/src/extractor/guidance/roundabout_handler.cpp @@ -1,5 +1,5 @@ -#include "extractor/guidance/constants.hpp" #include "extractor/guidance/roundabout_handler.hpp" +#include "extractor/guidance/constants.hpp" #include "extractor/guidance/toolkit.hpp" #include "util/coordinate_calculation.hpp" diff --git a/src/extractor/guidance/sliproad_handler.cpp b/src/extractor/guidance/sliproad_handler.cpp index 0cb27805d..169cc3efa 100644 --- a/src/extractor/guidance/sliproad_handler.cpp +++ b/src/extractor/guidance/sliproad_handler.cpp @@ -1,6 +1,6 @@ +#include "extractor/guidance/sliproad_handler.hpp" #include "extractor/guidance/constants.hpp" #include "extractor/guidance/intersection_scenario_three_way.hpp" -#include "extractor/guidance/sliproad_handler.hpp" #include "extractor/guidance/toolkit.hpp" #include "util/guidance/toolkit.hpp" @@ -129,10 +129,6 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection) const auto source_edge_data = node_based_graph.GetEdgeData(source_edge_id); - const bool hasNext = obvious_turn_index != 0; - if (!hasNext) - return intersection; - // check whether the continue road is valid const auto check_valid = [this, source_edge_data](const ConnectedRoad &road) { const auto road_edge_data = node_based_graph.GetEdgeData(road.turn.eid); diff --git a/src/extractor/guidance/turn_analysis.cpp b/src/extractor/guidance/turn_analysis.cpp index d2d2c9020..99c081742 100644 --- a/src/extractor/guidance/turn_analysis.cpp +++ b/src/extractor/guidance/turn_analysis.cpp @@ -1,6 +1,6 @@ +#include "extractor/guidance/turn_analysis.hpp" #include "extractor/guidance/constants.hpp" #include "extractor/guidance/road_classification.hpp" -#include "extractor/guidance/turn_analysis.hpp" #include "util/coordinate.hpp" #include "util/coordinate_calculation.hpp" diff --git a/src/extractor/guidance/turn_handler.cpp b/src/extractor/guidance/turn_handler.cpp index 321c1a054..d867c8267 100644 --- a/src/extractor/guidance/turn_handler.cpp +++ b/src/extractor/guidance/turn_handler.cpp @@ -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" diff --git a/src/extractor/guidance/turn_lane_handler.cpp b/src/extractor/guidance/turn_lane_handler.cpp index 2b553386a..c0f12b2e3 100644 --- a/src/extractor/guidance/turn_lane_handler.cpp +++ b/src/extractor/guidance/turn_lane_handler.cpp @@ -42,6 +42,7 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g turn_lane_masks(turn_lane_masks), lane_description_map(lane_description_map), node_info_list(node_info_list), turn_analysis(turn_analysis), id_map(id_map) { + count_handled = count_called = 0; } TurnLaneHandler::~TurnLaneHandler() @@ -285,12 +286,10 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at, // At b-c, we get access to either a new set of lanes, or -- via the previous intersection // -- to // the second part of | left | through | right |. Lane anticipation can then deduce which - // lanes - // correspond to what and suppress unnecessary instructions. + // lanes correspond to what and suppress unnecessary instructions. // // For our initial case, we consider only the turns that are available at the current - // location, - // which are given by partitioning the lane data and selecting the first part. + // location, which are given by partitioning the lane data and selecting the first part. if (!lane_data.empty()) { if (lane_data.size() >= possible_entries) @@ -355,21 +354,22 @@ void TurnLaneHandler::extractLaneData(const EdgeID via_edge, LaneDataVector &lane_data) const { const auto &edge_data = node_based_graph.GetEdgeData(via_edge); - // TODO access correct data lane_description_id = edge_data.lane_description_id; - const auto lane_description = - lane_description_id != INVALID_LANE_DESCRIPTIONID - ? TurnLaneDescription(turn_lane_masks.begin() + turn_lane_offsets[lane_description_id], - turn_lane_masks.begin() + - turn_lane_offsets[lane_description_id + 1]) - : TurnLaneDescription(); + // create an empty lane data + if (INVALID_LANE_DESCRIPTIONID != lane_description_id) + { + const auto lane_description = TurnLaneDescription( + turn_lane_masks.begin() + turn_lane_offsets[lane_description_id], + turn_lane_masks.begin() + turn_lane_offsets[lane_description_id + 1]); - if (!lane_description.empty()) lane_data = laneDataFromDescription(lane_description); - - BOOST_ASSERT(lane_description.empty() || - lane_description.size() == (turn_lane_offsets[lane_description_id + 1] - - turn_lane_offsets[lane_description_id])); + BOOST_ASSERT(lane_description.size() == (turn_lane_offsets[lane_description_id + 1] - + turn_lane_offsets[lane_description_id])); + } + else + { + lane_data.clear(); + } } /* A simple intersection does not depend on the next intersection coming up. This is important @@ -401,8 +401,7 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data, } // in case an intersection offers far more lane data items than actual turns, some of them - // have - // to be for another intersection. A single additional item can be for an invalid bus lane. + // have to be for another intersection. A single additional item can be for an invalid bus lane. const auto num_turns = [&]() { auto count = getNumberOfTurns(intersection); if (count < lane_data.size() && !intersection[0].entry_allowed && @@ -476,6 +475,7 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data, return intersection.begin(); }(); + BOOST_ASSERT(best_match != intersection.end()); std::size_t match_index = std::distance(intersection.begin(), best_match); all_simple &= (matched_indices.count(match_index) == 0); matched_indices.insert(match_index); @@ -521,10 +521,8 @@ std::pair TurnLaneHandler::partitionLaneData( * look back between (1) and (2) to make sure we find the correct lane for the left-turn. * * Intersections like these have two parts. Turns that can be made at the first intersection - * and - * turns that have to be made at the second. The partitioning returns the lane data split - * into - * two parts, one for the first and one for the second intersection. + * and turns that have to be made at the second. The partitioning returns the lane data split + * into two parts, one for the first and one for the second intersection. */ // Try and maitch lanes to available turns. For Turns that are not directly matchable, check diff --git a/src/extractor/guidance/turn_lane_matcher.cpp b/src/extractor/guidance/turn_lane_matcher.cpp index c15b1beb4..7f2d46c38 100644 --- a/src/extractor/guidance/turn_lane_matcher.cpp +++ b/src/extractor/guidance/turn_lane_matcher.cpp @@ -105,6 +105,9 @@ bool isValidMatch(const TurnLaneType::Mask tag, const TurnInstruction instructio double getMatchingQuality(const TurnLaneType::Mask tag, const ConnectedRoad &road) { const constexpr double idealized_turn_angles[] = {0, 35, 90, 135, 180, 225, 270, 315}; + const auto modifier = getMatchingModifier(tag); + BOOST_ASSERT(static_cast(modifier) < + sizeof(idealized_turn_angles) / sizeof(*idealized_turn_angles)); const auto idealized_angle = idealized_turn_angles[getMatchingModifier(tag)]; return angularDeviation(idealized_angle, road.turn.angle); }