diff --git a/CHANGELOG.md b/CHANGELOG.md index 314a8c159..42d1617f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Guidance - Improved detection of obvious turns - Improved turn lane detection + - Improved lane anticipation for roundabouts - Bugfixes - Fix bug that didn't chose minimal weights on overlapping edges diff --git a/features/guidance/anticipate-lanes.feature b/features/guidance/anticipate-lanes.feature index e6b6bff5f..7461ec3d7 100644 --- a/features/guidance/anticipate-lanes.feature +++ b/features/guidance/anticipate-lanes.feature @@ -365,6 +365,62 @@ Feature: Turn Lane Guidance | x,c | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,slight right:true slight right:true, | | x,a | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,slight right:true slight right:true, | + @anticipate + Scenario: Departing or arriving inside a roundabout does not yet anticipate lanes (BIG version) + Given the node map + | | | a | | | + | x | b | | d | y | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | c | | | + + And the ways + | nodes | turn:lanes:forward | highway | junction | name | + | xb | slight_right\|slight_right | primary | | xb | + | dy | | primary | | dy | + | ab | | primary | roundabout | roundabout | + | bc | | primary | roundabout | roundabout | + | cd | left\|slight_right | primary | roundabout | roundabout | + | da | | primary | roundabout | roundabout | + + When I route I should get + | waypoints | route | turns | lanes | + | x,y | xb,dy,dy | depart,roundabout-exit-1,arrive | ,slight right:false slight right:true, | + | x,c | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,slight right:true slight right:true, | + | x,a | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,slight right:true slight right:true, | + @anticipate Scenario: Anticipate Lanes for turns before and / or after roundabout Given the node map diff --git a/include/engine/guidance/lane_processing.hpp b/include/engine/guidance/lane_processing.hpp index c3d7f16dd..8e6f6e1ef 100644 --- a/include/engine/guidance/lane_processing.hpp +++ b/include/engine/guidance/lane_processing.hpp @@ -15,7 +15,10 @@ namespace guidance // Constrains lanes for multi-hop situations where lane changes depend on earlier ones. // Instead of forcing users to change lanes rapidly in a short amount of time, // we anticipate lane changes emitting only matching lanes early on. -std::vector anticipateLaneChange(std::vector steps); +// the second parameter describes the duration that we feel two segments need to be apart to count +// as separate maneuvers. +std::vector anticipateLaneChange(std::vector steps, + const double min_duration_needed_for_lane_change = 15); } // namespace guidance } // namespace engine diff --git a/src/engine/guidance/lane_processing.cpp b/src/engine/guidance/lane_processing.cpp index d7a2b0f0b..17be2c48b 100644 --- a/src/engine/guidance/lane_processing.cpp +++ b/src/engine/guidance/lane_processing.cpp @@ -1,3 +1,4 @@ +#include "util/debug.hpp" #include "util/for_each_pair.hpp" #include "util/group_by.hpp" #include "util/guidance/toolkit.hpp" @@ -20,18 +21,17 @@ namespace engine namespace guidance { -std::vector anticipateLaneChange(std::vector steps) +std::vector anticipateLaneChange(std::vector steps, + const double min_duration_needed_for_lane_change) { - const constexpr auto MIN_DURATION_NEEDED_FOR_LANE_CHANGE = 15.; - // Postprocessing does not strictly guarantee for only turns const auto is_turn = [](const RouteStep &step) { return step.maneuver.instruction.type != TurnType::NewName && step.maneuver.instruction.type != TurnType::Notification; }; - const auto is_quick = [MIN_DURATION_NEEDED_FOR_LANE_CHANGE](const RouteStep &step) { - return step.duration < MIN_DURATION_NEEDED_FOR_LANE_CHANGE; + const auto is_quick = [min_duration_needed_for_lane_change](const RouteStep &step) { + return step.duration < min_duration_needed_for_lane_change; }; const auto is_quick_turn = [&](const RouteStep &step) { diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index 6f4b0cab5..f4d15c1f4 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -524,7 +524,10 @@ std::vector anticipateLaneChangeForRoundabouts(std::vector enter.maneuver.instruction.direction_modifier = mirrorDirectionModifier(enter_direction); - auto enterAndLeave = anticipateLaneChange({enter, leave}); + // a roundabout is a continuous maneuver. We don't switch lanes within a roundabout, as long + // as it can be avoided. + auto enterAndLeave = + anticipateLaneChange({enter, leave}, std::numeric_limits::max()); // Undo flipping direction on a right turn in a right-sided counter-clockwise roundabout. // FIXME: assumes right-side driving (counter-clockwise roundabout flow)