Skip to content

Commit

Permalink
Consider number of lanes to cross, resolves Project-OSRM#3025.
Browse files Browse the repository at this point in the history
Lane Anticipation currently triggers on quick steps with lanes. This
changeset makes the "quick" part more dynamic by taking lanes left and
right of the turn into account. The reasoning for this is as follows.

The user can drive on the leftmost or rightmost lane and has to cross
all lanes left or right of the turn, respecitvely.

We scale our threshold appropriately, which now means the threshold
describes the duration the user needs for crossing _a single lane_.

Note: this is a heuristic and assumes the worst case. Which in my
opinion is fine to do since triggering Lane Anticipation in complex
scenarios is desirable.
  • Loading branch information
daniel-j-h authored and TheMarex committed Jan 11, 2017
1 parent 434a3a6 commit 6ea9f9f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
35 changes: 35 additions & 0 deletions features/guidance/anticipate-lanes.feature
Original file line number Diff line number Diff line change
Expand Up @@ -783,3 +783,38 @@ Feature: Turn Lane Guidance
| waypoints | route | turns | lanes |
| a,f | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,turn right,arrive | ,left:false left:true none:false none:false,left:false left:true none:false none:false,left:false left:true none:false none:false,left:false left:false right:true, |
| a,g | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,turn left,arrive | ,left:true left:true none:false none:false,left:true left:true none:false none:false,left:true left:true none:false none:false,left:true left:true right:false, |

@anticipate
Scenario: Complex lane scenarios scale threshold for triggering Lane Anticipation
Given the node map
"""
a – b – x
|
|
|
|
|
|
|
|
|
|
c
|
e – d – y
"""
# With a grid size of 20m the duration is ~20s but our default threshold for Lane Anticipation is 15s.
# The additional lanes left and right of the turn scale the threshold up so that Lane Anticipation still triggers.

And the ways
| nodes | turn:lanes:forward | name |
| ab | through\|through\|right\|right | MySt |
| bx | | XSt |
| bc | | MySt |
| cd | left\|right | MySt |
| de | | MySt |
| dy | | YSt |

When I route I should get
| waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,turn right,arrive | ,straight:false straight:false right:false right:true,left:false right:true, |
22 changes: 20 additions & 2 deletions src/engine/guidance/lane_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/post_processing.hpp"

#include <algorithm>
#include <iterator>
#include <unordered_set>
#include <utility>
Expand All @@ -27,9 +28,26 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
{
// Lane anticipation works on contiguous ranges of quick steps that have lane information
const auto is_quick_has_lanes = [&](const RouteStep &step) {
const auto is_quick = step.duration < min_duration_needed_for_lane_change;
const auto has_lanes = step.intersections.front().lanes.lanes_in_turn > 0;
return has_lanes && is_quick;

if (!has_lanes)
return false;

// The more unused lanes to the left and right of the turn there are, the higher
// the chance the user is driving on one of those and has to cross lanes.
// Scale threshold for these cases to be adaptive to the situation's complexity.
//
// Note: what we could do instead: do Lane Anticipation on all step pairs and then scale
// the threshold based on the lanes we're constraining the user to. Would need a re-write
// since at the moment we first group-by and only then do Lane Anticipation selectively.
//
// We do not have a source-target lane mapping, assume worst case for lanes to cross.
const auto to_cross = std::max(step.NumLanesToTheRight(), step.NumLanesToTheLeft());
const auto scale = 1 + to_cross;
const auto threshold = scale * min_duration_needed_for_lane_change;

const auto is_quick = step.duration < threshold;
return is_quick;
};

using StepIter = decltype(steps)::iterator;
Expand Down

0 comments on commit 6ea9f9f

Please sign in to comment.