Trigger lane anticipation based on distance, see discussion in #4260
This commit is contained in:
parent
c0c9ec1c7b
commit
5ece65cade
@ -3,7 +3,7 @@ Feature: Turn Lane Guidance
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "car"
|
Given the profile "car"
|
||||||
Given a grid size of 20 meters
|
Given a grid size of 100 meters
|
||||||
|
|
||||||
@anticipate
|
@anticipate
|
||||||
Scenario: Anticipate Lane Change for subsequent multi-lane intersections
|
Scenario: Anticipate Lane Change for subsequent multi-lane intersections
|
||||||
@ -371,9 +371,9 @@ Feature: Turn Lane Guidance
|
|||||||
Scenario: Anticipate Lanes for through with turn before / after
|
Scenario: Anticipate Lanes for through with turn before / after
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
c g l
|
c g l
|
||||||
b – d – e – h - i
|
b d e h i
|
||||||
a f j
|
a f j
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
@ -623,40 +623,11 @@ Feature: Turn Lane Guidance
|
|||||||
"""
|
"""
|
||||||
/a\
|
/a\
|
||||||
x – b d – y
|
x – b d – y
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
| |
|
||||||
| |
|
| |
|
||||||
| |
|
| |
|
||||||
| |
|
| |
|
||||||
| |
|
\ /
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
c
|
c
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -789,13 +760,6 @@ Feature: Turn Lane Guidance
|
|||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a – b – x
|
a – b – x
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
|
||||||
|
|
|
|
||||||
|
|
|
|
||||||
@ -823,11 +787,9 @@ Feature: Turn Lane Guidance
|
|||||||
Scenario: Don't Overdo It
|
Scenario: Don't Overdo It
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
q r s t u v
|
q r s t u v
|
||||||
| | | | | |
|
a - - b - - c - - d - - e - - f - g - h - i
|
||||||
a - - - - - - - - - - b - - - - - - - - - - c - - - - - - - - - - d - - - - - - - - - - e - - - - - - - - - - f - - - - - - - - - - g - h - i
|
p o n m l k j
|
||||||
| | | | | | |
|
|
||||||
p o n m l k j
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
|
@ -20,7 +20,7 @@ namespace guidance
|
|||||||
// as separate maneuvers.
|
// as separate maneuvers.
|
||||||
OSRM_ATTR_WARN_UNUSED
|
OSRM_ATTR_WARN_UNUSED
|
||||||
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
||||||
const double min_duration_needed_for_lane_change = 10);
|
const double min_distance_needed_for_lane_change = 200);
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -21,10 +21,10 @@ namespace guidance
|
|||||||
{
|
{
|
||||||
|
|
||||||
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
||||||
const double min_duration_needed_for_lane_change)
|
const double min_distance_needed_for_lane_change)
|
||||||
{
|
{
|
||||||
// Lane anticipation works on contiguous ranges of quick steps that have lane information
|
// Lane anticipation works on contiguous ranges of short steps that have lane information
|
||||||
const auto is_quick_has_lanes = [&](const RouteStep &step) {
|
const auto is_short_has_lanes = [&](const RouteStep &step) {
|
||||||
const auto has_lanes = step.intersections.front().lanes.lanes_in_turn > 0;
|
const auto has_lanes = step.intersections.front().lanes.lanes_in_turn > 0;
|
||||||
|
|
||||||
if (!has_lanes)
|
if (!has_lanes)
|
||||||
@ -41,10 +41,10 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
// We do not have a source-target lane mapping, assume worst case for lanes to cross.
|
// 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 to_cross = std::max(step.NumLanesToTheRight(), step.NumLanesToTheLeft());
|
||||||
const auto scale = 1 + to_cross;
|
const auto scale = 1 + to_cross;
|
||||||
const auto threshold = scale * min_duration_needed_for_lane_change;
|
const auto threshold = scale * min_distance_needed_for_lane_change;
|
||||||
|
|
||||||
const auto is_quick = step.duration < threshold;
|
const auto is_short = step.distance < threshold;
|
||||||
return is_quick;
|
return is_short;
|
||||||
};
|
};
|
||||||
|
|
||||||
using StepIter = decltype(steps)::iterator;
|
using StepIter = decltype(steps)::iterator;
|
||||||
@ -57,7 +57,7 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
quick_lanes_ranges.push_back(std::move(range));
|
quick_lanes_ranges.push_back(std::move(range));
|
||||||
};
|
};
|
||||||
|
|
||||||
util::group_by(begin(steps), end(steps), is_quick_has_lanes, range_back_inserter);
|
util::group_by(begin(steps), end(steps), is_short_has_lanes, range_back_inserter);
|
||||||
|
|
||||||
// The lanes for a keep straight depend on the next left/right turn. Tag them in advance.
|
// The lanes for a keep straight depend on the next left/right turn. Tag them in advance.
|
||||||
std::unordered_set<const RouteStep *> is_straight_left;
|
std::unordered_set<const RouteStep *> is_straight_left;
|
||||||
@ -75,10 +75,11 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
// state for the lamda
|
// state for the lamda
|
||||||
// the number of lanes we have to change depends on the number of lanes that are allowed for
|
// the number of lanes we have to change depends on the number of lanes that are allowed for
|
||||||
// a turn (in general) and the set of lanes which would allow for us to do the turn without
|
// a turn (in general) and the set of lanes which would allow for us to do the turn without
|
||||||
// a problem. In a sequence of turns, we have to look at how much time we need to switch the
|
// a problem. In a sequence of turns, we have to look at how much distance we need to switch
|
||||||
|
// the
|
||||||
// sequence. Given the turns in between, we would expect a bit longer than on a straight
|
// sequence. Given the turns in between, we would expect a bit longer than on a straight
|
||||||
// segment for a lane switch, but the total time shouldn't be unlimited.
|
// segment for a lane switch, but the total distance shouldn't be unlimited.
|
||||||
double time_to_constrained = 0.0;
|
double distance_to_constrained = 0.0;
|
||||||
|
|
||||||
util::for_each_pair(rev_first, rev_last, [&](RouteStep ¤t, RouteStep &previous) {
|
util::for_each_pair(rev_first, rev_last, [&](RouteStep ¤t, RouteStep &previous) {
|
||||||
const auto current_inst = current.maneuver.instruction;
|
const auto current_inst = current.maneuver.instruction;
|
||||||
@ -97,13 +98,13 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
// only prevent use lanes due to making all turns. don't make turns during curvy
|
// only prevent use lanes due to making all turns. don't make turns during curvy
|
||||||
// segments
|
// segments
|
||||||
if (previous_inst.type == TurnType::Suppressed)
|
if (previous_inst.type == TurnType::Suppressed)
|
||||||
time_to_constrained += previous.duration;
|
distance_to_constrained += previous.distance;
|
||||||
else
|
else
|
||||||
time_to_constrained = 0;
|
distance_to_constrained = 0.;
|
||||||
|
|
||||||
const auto lane_delta = previous_lanes.lanes_in_turn - current_lanes.lanes_in_turn;
|
const auto lane_delta = previous_lanes.lanes_in_turn - current_lanes.lanes_in_turn;
|
||||||
const auto can_make_all_turns =
|
const auto can_make_all_turns =
|
||||||
time_to_constrained > lane_delta * min_duration_needed_for_lane_change;
|
distance_to_constrained > lane_delta * min_distance_needed_for_lane_change;
|
||||||
|
|
||||||
if (!lanes_to_constrain || !lanes_fan_in || can_make_all_turns)
|
if (!lanes_to_constrain || !lanes_fan_in || can_make_all_turns)
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user