reduce verbosity of use-lane in combination with lane-anticipation
This commit is contained in:
parent
a45b9e07fc
commit
03bb6dc161
@ -818,3 +818,37 @@ Feature: Turn Lane Guidance
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| 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, |
|
| a,e | MySt,MySt,MySt,MySt | depart,continue right,turn right,arrive | ,straight:false straight:false right:false right:true,left:false right:true, |
|
||||||
|
|
||||||
|
@anticipate
|
||||||
|
Scenario: Don't Overdo It
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
q r s t u v
|
||||||
|
| | | | | |
|
||||||
|
a - - - - - - - - - - b - - - - - - - - - - c - - - - - - - - - - d - - - - - - - - - - e - - - - - - - - - - f - - - - - - - - - - g - h - i
|
||||||
|
| | | | | | |
|
||||||
|
p o n m l k j
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name | turn:lanes:forward | oneway |
|
||||||
|
| ab | road | left\|\|\| | yes |
|
||||||
|
| bc | road | left\|\|\| | yes |
|
||||||
|
| cd | road | left\|\|\| | yes |
|
||||||
|
| de | road | left\|\|\| | yes |
|
||||||
|
| ef | road | left\|\|\| | yes |
|
||||||
|
| fg | road | left\|\|\| | yes |
|
||||||
|
| gh | road | \|\|right | yes |
|
||||||
|
| hi | road | | yes |
|
||||||
|
| qbp | 1st | | no |
|
||||||
|
| rco | 2nd | | no |
|
||||||
|
| sdn | 3rd | | no |
|
||||||
|
| tem | 4th | | no |
|
||||||
|
| ufl | 5th | | no |
|
||||||
|
| vgk | 6th | | no |
|
||||||
|
| hj | 7th | | no |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns | locations | lanes |
|
||||||
|
| a,i | road,road,road | depart,use lane straight,arrive | a,g,i | ,left:false none:true none:true none:false, |
|
||||||
|
| a,j | road,road,7th,7th | depart,use lane straight,turn right,arrive | a,f,h,j | ,left:false none:false none:false none:true,none:false none:false right:true, |
|
||||||
|
@ -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 = 15);
|
const double min_duration_needed_for_lane_change = 10);
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -28,6 +28,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps);
|
|||||||
|
|
||||||
// A check whether two instructions can be treated as one. This is only the case for very short
|
// A check whether two instructions can be treated as one. This is only the case for very short
|
||||||
// maneuvers that can, in some form, be seen as one. Lookahead of one step.
|
// maneuvers that can, in some form, be seen as one. Lookahead of one step.
|
||||||
|
// This is only a pre-check and does not necessarily allow collapsing turns!!!
|
||||||
bool collapsable(const RouteStep &step, const RouteStep &next);
|
bool collapsable(const RouteStep &step, const RouteStep &next);
|
||||||
|
|
||||||
// trim initial/final segment of very short length.
|
// trim initial/final segment of very short length.
|
||||||
|
@ -74,6 +74,15 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
|
|
||||||
// We're walking backwards over all adjacent turns:
|
// We're walking backwards over all adjacent turns:
|
||||||
// the current turn lanes constrain the lanes we have to take in the previous turn.
|
// the current turn lanes constrain the lanes we have to take in the previous turn.
|
||||||
|
|
||||||
|
// state for the lamda
|
||||||
|
// 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 problem. In a sequence of turns, we have to look at how much time we need to switch the
|
||||||
|
// 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.
|
||||||
|
double time_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;
|
||||||
const auto current_lanes = current.intersections.front().lanes;
|
const auto current_lanes = current.intersections.front().lanes;
|
||||||
@ -88,7 +97,18 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1;
|
const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1;
|
||||||
const bool lanes_fan_in = previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn;
|
const bool lanes_fan_in = previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn;
|
||||||
|
|
||||||
if (!lanes_to_constrain || !lanes_fan_in)
|
// only prevent use lanes due to making all turns. don't make turns during curvy
|
||||||
|
// segments
|
||||||
|
if (previous_inst.type == TurnType::UseLane)
|
||||||
|
time_to_constrained += previous.duration;
|
||||||
|
else
|
||||||
|
time_to_constrained = 0;
|
||||||
|
|
||||||
|
const auto lane_delta = previous_lanes.lanes_in_turn - current_lanes.lanes_in_turn;
|
||||||
|
const auto can_make_all_turns =
|
||||||
|
time_to_constrained > lane_delta * min_duration_needed_for_lane_change;
|
||||||
|
|
||||||
|
if (!lanes_to_constrain || !lanes_fan_in || can_make_all_turns)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// We do not have a mapping from lanes to lanes. All we have is the lanes in the turn
|
// We do not have a mapping from lanes to lanes. All we have is the lanes in the turn
|
||||||
@ -99,9 +119,6 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
const LaneID current_num_lanes_right_of_turn = current.NumLanesToTheRight();
|
const LaneID current_num_lanes_right_of_turn = current.NumLanesToTheRight();
|
||||||
const LaneID current_num_lanes_left_of_turn = current.NumLanesToTheLeft();
|
const LaneID current_num_lanes_left_of_turn = current.NumLanesToTheLeft();
|
||||||
|
|
||||||
const LaneID num_shared_lanes = std::min(current_lanes.lanes_in_turn, //
|
|
||||||
previous_lanes.lanes_in_turn); //
|
|
||||||
|
|
||||||
// 0/ Tag keep straight with the next turn's direction if available
|
// 0/ Tag keep straight with the next turn's direction if available
|
||||||
const auto previous_is_straight =
|
const auto previous_is_straight =
|
||||||
!isLeftTurn(previous_inst) && !isRightTurn(previous_inst);
|
!isLeftTurn(previous_inst) && !isRightTurn(previous_inst);
|
||||||
@ -121,14 +138,14 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
LaneID new_first_lane_from_the_right =
|
LaneID new_first_lane_from_the_right =
|
||||||
previous_lanes.first_lane_from_the_right // start from rightmost lane
|
previous_lanes.first_lane_from_the_right // start from rightmost lane
|
||||||
+ previous_lanes.lanes_in_turn // one past leftmost lane
|
+ previous_lanes.lanes_in_turn // one past leftmost lane
|
||||||
- num_shared_lanes; // back number of new lanes
|
- current_lanes.lanes_in_turn; // back number of new lanes
|
||||||
|
|
||||||
// The leftmost target lanes might not be involved in the turn. Figure out
|
// The leftmost target lanes might not be involved in the turn. Figure out
|
||||||
// how many lanes are to the left and not in the turn.
|
// how many lanes are to the left and not in the turn.
|
||||||
new_first_lane_from_the_right -=
|
new_first_lane_from_the_right -=
|
||||||
std::min(current_num_lanes_left_of_turn, num_shared_lanes);
|
std::min(current_num_lanes_left_of_turn, current_lanes.lanes_in_turn);
|
||||||
|
|
||||||
previous_lanes = {num_shared_lanes, new_first_lane_from_the_right};
|
previous_lanes = {current_lanes.lanes_in_turn, new_first_lane_from_the_right};
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto anticipate_for_right_turn = [&] {
|
const auto anticipate_for_right_turn = [&] {
|
||||||
@ -139,9 +156,9 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
// The rightmost target lanes might not be involved in the turn. Figure out
|
// The rightmost target lanes might not be involved in the turn. Figure out
|
||||||
// how many lanes are to the right and not in the turn.
|
// how many lanes are to the right and not in the turn.
|
||||||
new_first_lane_from_the_right +=
|
new_first_lane_from_the_right +=
|
||||||
std::min(current_num_lanes_right_of_turn, num_shared_lanes);
|
std::min(current_num_lanes_right_of_turn, current_lanes.lanes_in_turn);
|
||||||
|
|
||||||
previous_lanes = {num_shared_lanes, new_first_lane_from_the_right};
|
previous_lanes = {current_lanes.lanes_in_turn, new_first_lane_from_the_right};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2/ When to anticipate a left, right turn
|
// 2/ When to anticipate a left, right turn
|
||||||
@ -179,13 +196,11 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
|||||||
anticipate_for_right_turn();
|
anticipate_for_right_turn();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We might have constrained the previous step in a way that makes it compatible
|
if (previous_inst.type == TurnType::UseLane && current_inst.type == TurnType::UseLane &&
|
||||||
// with the current step. If we did so we collapse it here and mark the current
|
previous.mode == current.mode && previous_lanes == current_lanes)
|
||||||
// step as invalid, scheduled for later removal.
|
|
||||||
if (collapsable(previous, current))
|
|
||||||
{
|
{
|
||||||
previous.ElongateBy(current);
|
previous.ElongateBy(current);
|
||||||
current.maneuver.instruction = TurnInstruction::NO_TURN();
|
current.Invalidate();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user