emit turn-straight for obvious turns where the main road continues

This commit is contained in:
Moritz Kobitzsch 2016-05-11 16:15:34 +02:00 committed by Patrick Niklaus
parent 1e8a92ccb4
commit a9f674497a
No known key found for this signature in database
GPG Key ID: E426891B5F978B1B
5 changed files with 74 additions and 36 deletions

View File

@ -1,5 +1,5 @@
# 5.2
Changes from 5.1
# 5.2.0
Changes from 5.1.0
- API:
- new parameter `annotate` for `route` and `match` requests. Returns additional data about each
@ -11,6 +11,9 @@
- Infrastructure:
- Open sockets with SO_REUSEPORT to allow multiple servers connecting to the same port
- Guidance:
- improved detection of turning streets, not reporting new-name in wrong situations
# 5.1.0
Changes with regard to 5.0.0

View File

@ -344,4 +344,4 @@ Feature: Collapse
| waypoints | route | turns |
| a,d | first,first,first,first | depart,continue left,continue right,arrive |
| a,e | first,second,second | depart,turn left,arrive |
| a,f | first,third,third | depart,new name straight,arrive |
| a,f | first,third,third | depart,turn straight,arrive |

View File

@ -16,9 +16,9 @@ Feature: Continue Instructions
| bd | primary |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,continue left,arrive |
| a,d | abc,bd,bd | depart,new name straight,arrive |
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,continue left,arrive |
| a,d | abc,bd,bd | depart,turn straight,arrive |
Scenario: Road turning right
Given the node map
@ -31,9 +31,9 @@ Feature: Continue Instructions
| bd | primary |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,continue right,arrive |
| a,d | abc,bd,bd | depart,new name straight,arrive |
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,continue right,arrive |
| a,d | abc,bd,bd | depart,turn straight,arrive |
Scenario: Road turning slight left
Given the node map

View File

@ -323,8 +323,14 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
return angularDeviation(bearing_in, bearing_out) > 170;
};
const auto isCollapsableInstruction = [](const TurnInstruction instruction) {
return instruction.type == TurnType::NewName ||
(instruction.type == TurnType::Turn &&
instruction.direction_modifier == DirectionModifier::Straight);
};
// Very Short New Name
if (TurnType::NewName == one_back_step.maneuver.instruction.type)
if (isCollapsableInstruction(one_back_step.maneuver.instruction))
{
BOOST_ASSERT(two_back_index < steps.size());
if (one_back_step.mode == steps[two_back_index].mode)
@ -339,7 +345,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
}
}
// very short segment after turn
else if (TurnType::NewName == current_step.maneuver.instruction.type)
else if (isCollapsableInstruction(current_step.maneuver.instruction))
{
if (one_back_step.mode == current_step.mode)
{
@ -365,7 +371,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
// additionall collapse a name-change as well
const bool continues_with_name_change =
(step_index + 1 < steps.size()) &&
(TurnType::NewName == steps[step_index + 1].maneuver.instruction.type);
isCollapsableInstruction(steps[step_index + 1].maneuver.instruction);
const bool u_turn_with_name_change =
collapsable(current_step) && continues_with_name_change &&
steps[step_index + 1].name == steps[two_back_index].name;
@ -533,6 +539,11 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
invalidateStep(steps[1]);
}
}
const auto isCollapsableInstruction = [](const TurnInstruction instruction) {
return instruction.type == TurnType::NewName ||
(instruction.type == TurnType::Turn &&
instruction.direction_modifier == DirectionModifier::Straight);
};
// first and last instructions are waypoints that cannot be collapsed
for (std::size_t step_index = 2; step_index < steps.size(); ++step_index)
@ -551,7 +562,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
// Due to empty segments, we can get name-changes from A->A
// These have to be handled in post-processing
if (TurnType::NewName == current_step.maneuver.instruction.type &&
if (isCollapsableInstruction(current_step.maneuver.instruction) &&
current_step.name == steps[one_back_index].name)
{
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
@ -560,8 +571,8 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
// If we look at two consecutive name changes, we can check for a name oszillation.
// A name oszillation changes from name A shortly to name B and back to A.
// In these cases, the name change will be suppressed.
else if (TurnType::NewName == current_step.maneuver.instruction.type &&
TurnType::NewName == one_back_step.maneuver.instruction.type)
else if (isCollapsableInstruction(current_step.maneuver.instruction) &&
isCollapsableInstruction(one_back_step.maneuver.instruction))
{
// valid due to step_index starting at 2
const auto &coming_from_name = steps[two_back_index].name;

View File

@ -3,7 +3,6 @@
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_handler.hpp"
#include "util/simple_logger.hpp"
#include "util/guidance/toolkit.hpp"
#include <limits>
@ -78,6 +77,9 @@ Intersection TurnHandler::handleTwoWayTurn(const EdgeID via_edge, Intersection i
Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection intersection) const
{
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
const auto &first_data = node_based_graph.GetEdgeData(intersection[1].turn.eid);
const auto &second_data = node_based_graph.GetEdgeData(intersection[2].turn.eid);
BOOST_ASSERT(intersection[0].turn.angle < 0.001);
const auto isObviousOfTwo = [this](const ConnectedRoad road, const ConnectedRoad other) {
const auto first_class =
@ -134,14 +136,16 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
{
assignFork(via_edge, intersection[2], intersection[1]);
}
else if (isObviousOfTwo(intersection[1], intersection[2]))
else if (isObviousOfTwo(intersection[1], intersection[2]) &&
second_data.name_id != in_data.name_id)
{
intersection[1].turn.instruction =
getInstructionForObvious(intersection.size(), via_edge, false, intersection[1]);
intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]),
DirectionModifier::SlightLeft};
}
else if (isObviousOfTwo(intersection[2], intersection[1]))
else if (isObviousOfTwo(intersection[2], intersection[1]) &&
first_data.name_id != in_data.name_id)
{
intersection[2].turn.instruction =
getInstructionForObvious(intersection.size(), via_edge, false, intersection[2]);
@ -193,7 +197,8 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
}
else
{
if (isObviousOfTwo(intersection[1], intersection[2]))
if (isObviousOfTwo(intersection[1], intersection[2]) &&
in_data.name_id != second_data.name_id)
{
intersection[1].turn.instruction = getInstructionForObvious(
3, via_edge, isThroughStreet(1, intersection), intersection[1]);
@ -204,7 +209,8 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
getTurnDirection(intersection[1].turn.angle)};
}
if (isObviousOfTwo(intersection[2], intersection[1]))
if (isObviousOfTwo(intersection[2], intersection[1]) &&
in_data.name_id != first_data.name_id)
{
intersection[2].turn.instruction = getInstructionForObvious(
3, via_edge, isThroughStreet(2, intersection), intersection[2]);
@ -234,12 +240,44 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
}
}
// check whether there is a turn of the same name
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
const bool has_same_name_turn = [&]() {
for (std::size_t i = 1; i < intersection.size(); ++i)
{
if (node_based_graph.GetEdgeData(intersection[i].turn.eid).name_id == in_data.name_id)
return true;
}
return false;
}();
// check whether the obvious choice is actually a through street
if (obvious_index != 0)
{
intersection[obvious_index].turn.instruction = getInstructionForObvious(
intersection.size(), via_edge, isThroughStreet(obvious_index, intersection),
intersection[obvious_index]);
if (has_same_name_turn &&
node_based_graph.GetEdgeData(intersection[obvious_index].turn.eid).name_id !=
in_data.name_id &&
intersection[obvious_index].turn.instruction.type == TurnType::NewName)
{
// this is a special case that is necessary to correctly handle obvious turns on
// continuing streets. Right now osrm does not know about right of way. If a street
// turns to the left just like:
//
// a
// a
// aaaaaaa b b
//
// And another road exits here, we don't want to call it a new name, even though the
// turn is obvious and does not require steering. To correctly handle these situations
// in turn collapsing, we use the turn + straight combination here
intersection[obvious_index].turn.instruction.type = TurnType::Turn;
intersection[obvious_index].turn.instruction.direction_modifier =
DirectionModifier::Straight;
}
// assign left/right turns
intersection = assignLeftTurns(via_edge, std::move(intersection), obvious_index + 1);
@ -302,7 +340,7 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
}
else
{
assignTrivialTurns(via_edge,intersection,1,intersection.size());
assignTrivialTurns(via_edge, intersection, 1, intersection.size());
}
return intersection;
}
@ -394,8 +432,7 @@ Intersection TurnHandler::assignLeftTurns(const EdgeID via_edge,
const std::size_t starting_at) const
{
BOOST_ASSERT(starting_at <= intersection.size());
const auto switch_left_and_right = []( Intersection &intersection )
{
const auto switch_left_and_right = [](Intersection &intersection) {
BOOST_ASSERT(!intersection.empty());
for (auto &road : intersection)
@ -410,7 +447,6 @@ Intersection TurnHandler::assignLeftTurns(const EdgeID via_edge,
intersection = assignRightTurns(via_edge, std::move(intersection), count);
switch_left_and_right(intersection);
return intersection;
}
@ -537,18 +573,6 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge,
}
else
{
util::SimpleLogger().Write(logWARNING)
<< "Reached fallback for right turns, size 3 "
<< " Valids: " << (intersection[1].entry_allowed + intersection[2].entry_allowed +
intersection[3].entry_allowed);
for (const auto road : intersection)
{
const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid);
util::SimpleLogger().Write(logWARNING)
<< "\troad: " << toString(road) << " Name: " << out_data.name_id
<< " Road Class: " << (int)out_data.road_classification.road_class;
}
assignTrivialTurns(via_edge, intersection, 1, up_to);
}
}