From 0e017a6ce53bf471b7e5671cddd745fa3a158914 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Mon, 18 Jul 2016 11:24:41 +0200 Subject: [PATCH] collapse use-lane instructions if possible --- CHANGELOG.md | 3 +- features/guidance/anticipate-lanes.feature | 6 +- features/guidance/turn-lanes.feature | 71 ++++++++++----------- include/engine/api/route_api.hpp | 1 + include/engine/guidance/post_processing.hpp | 9 +++ src/engine/guidance/post_processing.cpp | 41 ++++++++++++ 6 files changed, 91 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42d1617f3..827253ce8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # 5.3.0 Changes from 5.3.0-rc.3 + - Guidance + - Only announce `use lane` on required turns (not using all lanes to go straight) - Bugfixes - Fix BREAKING: bug that could result in failure to load 'osrm.icd' files. This breaks the dataformat @@ -8,7 +10,6 @@ - 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 9611aa61b..cb778956a 100644 --- a/features/guidance/anticipate-lanes.feature +++ b/features/guidance/anticipate-lanes.feature @@ -135,9 +135,9 @@ Feature: Turn Lane Guidance | cj | | 1 | motorway_link | yes | xbcj | When I route I should get - | waypoints | route | turns | lanes | - | a,i | ab,xbcj,ci,ci | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, | - | a,j | ab,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight right:false, | + | waypoints | route | turns | lanes | + | a,i | ab,xbcj,ci,ci | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, | + | a,j | ab,xbcj,xbcj | depart,merge slight left,arrive | ,, | @anticipate diff --git a/features/guidance/turn-lanes.feature b/features/guidance/turn-lanes.feature index c385ecdcb..7c0d82b03 100644 --- a/features/guidance/turn-lanes.feature +++ b/features/guidance/turn-lanes.feature @@ -87,7 +87,6 @@ Feature: Turn Lane Guidance #this next test requires decision on how to announce lanes for going straight if there is no turn - @TODO Scenario: Turn with Bus-Lane Given the node map | a | | b | | c | @@ -101,9 +100,9 @@ Feature: Turn Lane Guidance | bd | turn | | | When I route I should get - | waypoints | route | turns | lanes | - | a,d | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, | - | a,c | road,road,road | depart,use lane straight,arrive | ,straight:true right:false, | + | waypoints | route | turns | lanes | + | a,d | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, | + | a,c | road,road | depart,arrive | , | @PROFILE @LANES Scenario: Turn with Bus-Lane but without lanes @@ -194,13 +193,13 @@ Feature: Turn Lane Guidance | fl | cross | | yes | When I route I should get - | waypoints | route | turns | lanes | - | a,j | road,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true, | - | k,d | cross,road,road | depart,turn right,arrive | ,left:false straight;right:true, | - | e,l | road,cross,cross | depart,turn right,arrive | ,none:false straight:false straight;right:true, | - | i,h | cross,road,road | depart,turn right,arrive | ,, | - | i,j | cross,cross,cross | depart,use lane straight,arrive | ,left:false straight:true, | - | i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false, | + | waypoints | route | turns | lanes | + | a,j | road,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true, | + | k,d | cross,road,road | depart,turn right,arrive | ,left:false straight;right:true, | + | e,l | road,cross,cross | depart,turn right,arrive | ,none:false straight:false straight;right:true, | + | i,h | cross,road,road | depart,turn right,arrive | ,, | + | i,j | cross,cross | depart,arrive | , | + | i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false, | Scenario: Turn Lanes at Segregated Road Given the node map @@ -238,9 +237,9 @@ Feature: Turn Lane Guidance | ce | turn | | When I route I should get - | waypoints | route | turns | lanes | - | a,e | road,turn,turn | depart,turn right,arrive | ,none:false right:true, | - | a,d | road,road,road | depart,use lane straight,arrive | ,none:true right:false, | + | waypoints | route | turns | lanes | + | a,e | road,turn,turn | depart,turn right,arrive | ,none:false right:true, | + | a,d | road,road | depart,arrive | , | Scenario: Turn Lanes Given earlier than actual turn Given the node map @@ -258,11 +257,11 @@ Feature: Turn Lane Guidance | hk | second-turn | | | When I route I should get - | waypoints | route | turns | lanes | - | a,k | road,second-turn,second-turn | depart,turn right,arrive | ,none:false right:true, | - | a,i | road,road,road | depart,use lane straight,arrive | ,none:true right:false, | - | i,j | road,first-turn,first-turn | depart,turn left,arrive | ,left:true none:false, | - | i,a | road,road,road | depart,use lane straight,arrive | ,left:false none:true, | + | waypoints | route | turns | lanes | + | a,k | road,second-turn,second-turn | depart,turn right,arrive | ,none:false right:true, | + | a,i | road,road | depart,arrive | , | + | i,j | road,first-turn,first-turn | depart,turn left,arrive | ,left:true none:false, | + | i,a | road,road | depart,arrive | , | Scenario: Passing a one-way street Given the node map @@ -358,9 +357,9 @@ Feature: Turn Lane Guidance | ce | turn | | When I route I should get - | waypoints | route | turns | lanes | - | a,d | road,road,road | depart,use lane straight,arrive | ,straight:true right:false, | - | a,e | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, | + | waypoints | route | turns | lanes | + | a,d | road,road | depart,arrive | , | + | a,e | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, | @bug @todo Scenario: Theodor Heuss Platz @@ -422,9 +421,9 @@ Feature: Turn Lane Guidance | restriction | bc | fdcg | c | no_right_turn | When I route I should get - | waypoints | route | turns | lanes | - | a,g | road,cross,cross | depart,turn left,arrive | ,left:true left:true straight:false straight:false, | - | a,e | road,road,road | depart,use lane straight,arrive | ,left:false left:false straight:true straight:true, | + | waypoints | route | turns | lanes | + | a,g | road,cross,cross | depart,turn left,arrive | ,left:true left:true straight:false straight:false, | + | a,e | road,road | depart,arrive | , | Scenario: U-Turn Road at Intersection Given the node map @@ -445,11 +444,11 @@ Feature: Turn Lane Guidance | gdeh | cross | | no | primary | When I route I should get - | from | to | bearings | route | turns | lanes | - | a | g | 180,180 180,180 | road,cross,cross | depart,turn right,arrive | ,none:false straight:false right:true, | - | a | h | 180,180 180,180 | road,cross,cross | depart,turn left,arrive | ,none:true straight:false right:false, | - | a | i | 180,180 180,180 | road,road,road | depart,use lane straight,arrive | ,none:true straight:true right:false, | - | b | a | 90,2 270,2 | road,road,road | depart,continue uturn,arrive | ,none:true straight:false right:false, | + | from | to | bearings | route | turns | lanes | + | a | g | 180,180 180,180 | road,cross,cross | depart,turn right,arrive | ,none:false straight:false right:true, | + | a | h | 180,180 180,180 | road,cross,cross | depart,turn left,arrive | ,none:true straight:false right:false, | + | a | i | 180,180 180,180 | road,road | depart,arrive | , | + | b | a | 90,2 270,2 | road,road,road | depart,continue uturn,arrive | ,none:true straight:false right:false, | Scenario: Segregated Intersection Merges With Lanes Given the node map @@ -519,7 +518,7 @@ Feature: Turn Lane Guidance When I route I should get | waypoints | route | turns | lanes | - | a,d | road,road,road | depart,use lane straight,arrive | ,straight:true straight:true straight;slight right:true slight right:false, | + | a,d | road,road | depart,arrive | , | | a,e | road,cross,cross | depart,turn slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, | Scenario: Highway Ramp @@ -535,7 +534,7 @@ Feature: Turn Lane Guidance When I route I should get | waypoints | route | turns | lanes | - | a,d | hwy,hwy,hwy | depart,use lane straight,arrive | ,straight:true straight:true straight;slight right:true slight right:false, | + | a,d | hwy,hwy | depart,arrive | , | | a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, | @bug @todo @@ -575,7 +574,7 @@ Feature: Turn Lane Guidance When I route I should get | waypoints | route | turns | lanes | - | a,c | hwy,hwy,hwy | depart,use lane slight left,arrive | ,straight:true straight:true slight right:false, | + | a,c | hwy,hwy | depart,arrive | , | | a,d | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false slight right:true, | Scenario: Reverse Lane in Segregated Road @@ -681,9 +680,9 @@ Feature: Turn Lane Guidance | ab | on | motorway_link | | When I route I should get - | waypoints | route | turns | lanes | - | a,j | on,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight right:false, | - | a,i | on,xbcj,off,off | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, | + | waypoints | route | turns | lanes | + | a,j | on,xbcj,xbcj | depart,merge slight left,arrive | ,, | + | a,i | on,xbcj,off,off | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, | #http://www.openstreetmap.org/#map=17/52.47414/13.35712 @todo @ramp @2645 diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index f3965caa1..25e9f7a80 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -151,6 +151,7 @@ class RouteAPI : public BaseAPI phantoms.source_phantom, phantoms.target_phantom); leg.steps = guidance::anticipateLaneChange(std::move(leg.steps)); + leg.steps = guidance::collapseUseLane(std::move(leg.steps)); leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps); } diff --git a/include/engine/guidance/post_processing.hpp b/include/engine/guidance/post_processing.hpp index 16d383df6..ad0b3d63e 100644 --- a/include/engine/guidance/post_processing.hpp +++ b/include/engine/guidance/post_processing.hpp @@ -43,6 +43,15 @@ std::vector buildIntersections(std::vector steps); // remove steps invalidated by post-processing std::vector removeNoTurnInstructions(std::vector steps); +// remove use lane information that is not actually a turn. For post-processing, we need to +// associate lanes with every turn. Some of these use-lane instructions are not required after lane +// anticipation anymore. This function removes all use lane instructions that are not actually used +// anymore since all lanes going straight are used anyhow. +// FIXME this is currently only a heuristic. We need knowledge on which lanes actually might become +// turn lanes. If a straight lane becomes a turn lane, this might be something to consider. Right +// now we bet on lane-anticipation to catch this. +std::vector collapseUseLane(std::vector steps); + // postProcess will break the connection between the leg geometry // for which a segment is supposed to represent exactly the coordinates // between routing maneuvers and the route steps itself. diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index f4d15c1f4..296ef7be0 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -1149,6 +1149,47 @@ std::vector buildIntersections(std::vector steps) return removeNoTurnInstructions(std::move(steps)); } +std::vector collapseUseLane(std::vector steps) +{ + const auto containsTag = [](const extractor::guidance::TurnLaneType::Mask mask, + const extractor::guidance::TurnLaneType::Mask tag) { + return (mask & tag) != extractor::guidance::TurnLaneType::empty; + }; + + const auto canCollapeUseLane = + [containsTag](const util::guidance::LaneTupel lanes, + extractor::guidance::TurnLaneDescription lane_description) { + // the lane description is given left to right, lanes are counted from the right. + // Therefore we access the lane description yousing the reverse iterator + if (lanes.first_lane_from_the_right > 0 && + containsTag(*(lane_description.rbegin() + (lanes.first_lane_from_the_right - 1)), + (extractor::guidance::TurnLaneType::straight | + extractor::guidance::TurnLaneType::none))) + return false; + + const auto lane_to_the_right = lanes.first_lane_from_the_right + lanes.lanes_in_turn; + if (lane_to_the_right < lane_description.size() && + containsTag(*(lane_description.rbegin() + lane_to_the_right), + (extractor::guidance::TurnLaneType::straight | + extractor::guidance::TurnLaneType::none))) + return false; + + return true; + }; + + for (std::size_t step_index = 1; step_index < steps.size(); ++step_index) + { + const auto &step = steps[step_index]; + if (step.maneuver.instruction.type == TurnType::UseLane && + canCollapeUseLane(step.maneuver.lanes, step.maneuver.lane_description)) + { + elongate(steps[step_index - 1], steps[step_index]); + invalidateStep(steps[step_index]); + } + } + return removeNoTurnInstructions(std::move(steps)); +} + } // namespace guidance } // namespace engine } // namespace osrm