diff --git a/CHANGELOG.md b/CHANGELOG.md index ed4fe01af..f9f656ef0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ -# 5.2 - Changes from 5.1 +# 5.2.0 + Changes from 5.1.0 - API: - new parameter `annotate` for `route` and `match` requests. Returns additional data about each @@ -11,6 +11,9 @@ - Infrastructure: - Open sockets with SO_REUSEPORT to allow multiple servers connecting to the same port + - Guidance: + - improved detection of turning streets, not reporting new-name in wrong situations + # 5.1.0 Changes with regard to 5.0.0 diff --git a/features/guidance/collapse.feature b/features/guidance/collapse.feature index 9cde9eb3f..ac4a826c9 100644 --- a/features/guidance/collapse.feature +++ b/features/guidance/collapse.feature @@ -344,4 +344,4 @@ Feature: Collapse | waypoints | route | turns | | a,d | first,first,first,first | depart,continue left,continue right,arrive | | a,e | first,second,second | depart,turn left,arrive | - | a,f | first,third,third | depart,new name straight,arrive | + | a,f | first,third,third | depart,turn straight,arrive | diff --git a/features/guidance/continue.feature b/features/guidance/continue.feature index b3abe4843..cc12434d7 100644 --- a/features/guidance/continue.feature +++ b/features/guidance/continue.feature @@ -16,9 +16,9 @@ Feature: Continue Instructions | bd | primary | When I route I should get - | waypoints | route | turns | - | a,c | abc,abc,abc | depart,continue left,arrive | - | a,d | abc,bd,bd | depart,new name straight,arrive | + | waypoints | route | turns | + | a,c | abc,abc,abc | depart,continue left,arrive | + | a,d | abc,bd,bd | depart,turn straight,arrive | Scenario: Road turning right Given the node map @@ -31,9 +31,9 @@ Feature: Continue Instructions | bd | primary | When I route I should get - | waypoints | route | turns | - | a,c | abc,abc,abc | depart,continue right,arrive | - | a,d | abc,bd,bd | depart,new name straight,arrive | + | waypoints | route | turns | + | a,c | abc,abc,abc | depart,continue right,arrive | + | a,d | abc,bd,bd | depart,turn straight,arrive | Scenario: Road turning slight left Given the node map diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index 7d8da6e7f..18726d97a 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -323,8 +323,14 @@ void collapseTurnAt(std::vector &steps, return angularDeviation(bearing_in, bearing_out) > 170; }; + const auto isCollapsableInstruction = [](const TurnInstruction instruction) { + return instruction.type == TurnType::NewName || + (instruction.type == TurnType::Turn && + instruction.direction_modifier == DirectionModifier::Straight); + }; + // Very Short New Name - if (TurnType::NewName == one_back_step.maneuver.instruction.type) + if (isCollapsableInstruction(one_back_step.maneuver.instruction)) { BOOST_ASSERT(two_back_index < steps.size()); if (one_back_step.mode == steps[two_back_index].mode) @@ -339,7 +345,7 @@ void collapseTurnAt(std::vector &steps, } } // very short segment after turn - else if (TurnType::NewName == current_step.maneuver.instruction.type) + else if (isCollapsableInstruction(current_step.maneuver.instruction)) { if (one_back_step.mode == current_step.mode) { @@ -365,7 +371,7 @@ void collapseTurnAt(std::vector &steps, // additionall collapse a name-change as well const bool continues_with_name_change = (step_index + 1 < steps.size()) && - (TurnType::NewName == steps[step_index + 1].maneuver.instruction.type); + isCollapsableInstruction(steps[step_index + 1].maneuver.instruction); const bool u_turn_with_name_change = collapsable(current_step) && continues_with_name_change && steps[step_index + 1].name == steps[two_back_index].name; @@ -533,6 +539,11 @@ std::vector collapseTurns(std::vector steps) invalidateStep(steps[1]); } } + const auto isCollapsableInstruction = [](const TurnInstruction instruction) { + return instruction.type == TurnType::NewName || + (instruction.type == TurnType::Turn && + instruction.direction_modifier == DirectionModifier::Straight); + }; // first and last instructions are waypoints that cannot be collapsed for (std::size_t step_index = 2; step_index < steps.size(); ++step_index) @@ -551,7 +562,7 @@ std::vector collapseTurns(std::vector steps) // Due to empty segments, we can get name-changes from A->A // These have to be handled in post-processing - if (TurnType::NewName == current_step.maneuver.instruction.type && + if (isCollapsableInstruction(current_step.maneuver.instruction) && current_step.name == steps[one_back_index].name) { steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]); @@ -560,8 +571,8 @@ std::vector collapseTurns(std::vector steps) // If we look at two consecutive name changes, we can check for a name oszillation. // A name oszillation changes from name A shortly to name B and back to A. // In these cases, the name change will be suppressed. - else if (TurnType::NewName == current_step.maneuver.instruction.type && - TurnType::NewName == one_back_step.maneuver.instruction.type) + else if (isCollapsableInstruction(current_step.maneuver.instruction) && + isCollapsableInstruction(one_back_step.maneuver.instruction)) { // valid due to step_index starting at 2 const auto &coming_from_name = steps[two_back_index].name; diff --git a/src/extractor/guidance/turn_handler.cpp b/src/extractor/guidance/turn_handler.cpp index b6d898777..3211fc3a8 100644 --- a/src/extractor/guidance/turn_handler.cpp +++ b/src/extractor/guidance/turn_handler.cpp @@ -3,7 +3,6 @@ #include "extractor/guidance/toolkit.hpp" #include "extractor/guidance/turn_handler.hpp" -#include "util/simple_logger.hpp" #include "util/guidance/toolkit.hpp" #include @@ -78,6 +77,9 @@ Intersection TurnHandler::handleTwoWayTurn(const EdgeID via_edge, Intersection i Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection intersection) const { + 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); BOOST_ASSERT(intersection[0].turn.angle < 0.001); const auto isObviousOfTwo = [this](const ConnectedRoad road, const ConnectedRoad other) { const auto first_class = @@ -134,14 +136,16 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection { assignFork(via_edge, intersection[2], intersection[1]); } - else if (isObviousOfTwo(intersection[1], intersection[2])) + else if (isObviousOfTwo(intersection[1], intersection[2]) && + second_data.name_id != in_data.name_id) { intersection[1].turn.instruction = getInstructionForObvious(intersection.size(), via_edge, false, intersection[1]); intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]), DirectionModifier::SlightLeft}; } - else if (isObviousOfTwo(intersection[2], intersection[1])) + else if (isObviousOfTwo(intersection[2], intersection[1]) && + first_data.name_id != in_data.name_id) { intersection[2].turn.instruction = getInstructionForObvious(intersection.size(), via_edge, false, intersection[2]); @@ -193,7 +197,8 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection } else { - if (isObviousOfTwo(intersection[1], intersection[2])) + if (isObviousOfTwo(intersection[1], intersection[2]) && + in_data.name_id != second_data.name_id) { intersection[1].turn.instruction = getInstructionForObvious( 3, via_edge, isThroughStreet(1, intersection), intersection[1]); @@ -204,7 +209,8 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection getTurnDirection(intersection[1].turn.angle)}; } - if (isObviousOfTwo(intersection[2], intersection[1])) + if (isObviousOfTwo(intersection[2], intersection[1]) && + in_data.name_id != first_data.name_id) { intersection[2].turn.instruction = getInstructionForObvious( 3, via_edge, isThroughStreet(2, intersection), intersection[2]); @@ -234,12 +240,44 @@ 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) { intersection[obvious_index].turn.instruction = getInstructionForObvious( intersection.size(), 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); @@ -302,7 +340,7 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection } else { - assignTrivialTurns(via_edge,intersection,1,intersection.size()); + assignTrivialTurns(via_edge, intersection, 1, intersection.size()); } return intersection; } @@ -394,8 +432,7 @@ Intersection TurnHandler::assignLeftTurns(const EdgeID via_edge, const std::size_t starting_at) const { BOOST_ASSERT(starting_at <= intersection.size()); - const auto switch_left_and_right = []( Intersection &intersection ) - { + const auto switch_left_and_right = [](Intersection &intersection) { BOOST_ASSERT(!intersection.empty()); for (auto &road : intersection) @@ -410,7 +447,6 @@ Intersection TurnHandler::assignLeftTurns(const EdgeID via_edge, intersection = assignRightTurns(via_edge, std::move(intersection), count); switch_left_and_right(intersection); - return intersection; } @@ -537,18 +573,6 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge, } else { - util::SimpleLogger().Write(logWARNING) - << "Reached fallback for right turns, size 3 " - << " Valids: " << (intersection[1].entry_allowed + intersection[2].entry_allowed + - intersection[3].entry_allowed); - for (const auto road : intersection) - { - const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid); - util::SimpleLogger().Write(logWARNING) - << "\troad: " << toString(road) << " Name: " << out_data.name_id - << " Road Class: " << (int)out_data.road_classification.road_class; - } - assignTrivialTurns(via_edge, intersection, 1, up_to); } }