emit turn-straight for obvious turns where the main road continues
This commit is contained in:
parent
1e8a92ccb4
commit
a9f674497a
@ -1,5 +1,5 @@
|
|||||||
# 5.2
|
# 5.2.0
|
||||||
Changes from 5.1
|
Changes from 5.1.0
|
||||||
|
|
||||||
- API:
|
- API:
|
||||||
- new parameter `annotate` for `route` and `match` requests. Returns additional data about each
|
- new parameter `annotate` for `route` and `match` requests. Returns additional data about each
|
||||||
@ -11,6 +11,9 @@
|
|||||||
- Infrastructure:
|
- Infrastructure:
|
||||||
- Open sockets with SO_REUSEPORT to allow multiple servers connecting to the same port
|
- 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
|
# 5.1.0
|
||||||
Changes with regard to 5.0.0
|
Changes with regard to 5.0.0
|
||||||
|
|
||||||
|
@ -344,4 +344,4 @@ Feature: Collapse
|
|||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | first,first,first,first | depart,continue left,continue right,arrive |
|
| a,d | first,first,first,first | depart,continue left,continue right,arrive |
|
||||||
| a,e | first,second,second | depart,turn left,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 |
|
||||||
|
@ -18,7 +18,7 @@ Feature: Continue Instructions
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | abc,abc,abc | depart,continue left,arrive |
|
| a,c | abc,abc,abc | depart,continue left,arrive |
|
||||||
| a,d | abc,bd,bd | depart,new name straight,arrive |
|
| a,d | abc,bd,bd | depart,turn straight,arrive |
|
||||||
|
|
||||||
Scenario: Road turning right
|
Scenario: Road turning right
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -33,7 +33,7 @@ Feature: Continue Instructions
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | abc,abc,abc | depart,continue right,arrive |
|
| a,c | abc,abc,abc | depart,continue right,arrive |
|
||||||
| a,d | abc,bd,bd | depart,new name straight,arrive |
|
| a,d | abc,bd,bd | depart,turn straight,arrive |
|
||||||
|
|
||||||
Scenario: Road turning slight left
|
Scenario: Road turning slight left
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -323,8 +323,14 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
|||||||
return angularDeviation(bearing_in, bearing_out) > 170;
|
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
|
// 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());
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
if (one_back_step.mode == steps[two_back_index].mode)
|
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
|
// 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)
|
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
|
// additionall collapse a name-change as well
|
||||||
const bool continues_with_name_change =
|
const bool continues_with_name_change =
|
||||||
(step_index + 1 < steps.size()) &&
|
(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 =
|
const bool u_turn_with_name_change =
|
||||||
collapsable(current_step) && continues_with_name_change &&
|
collapsable(current_step) && continues_with_name_change &&
|
||||||
steps[step_index + 1].name == steps[two_back_index].name;
|
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]);
|
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
|
// first and last instructions are waypoints that cannot be collapsed
|
||||||
for (std::size_t step_index = 2; step_index < steps.size(); ++step_index)
|
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
|
// Due to empty segments, we can get name-changes from A->A
|
||||||
// These have to be handled in post-processing
|
// 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)
|
current_step.name == steps[one_back_index].name)
|
||||||
{
|
{
|
||||||
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
|
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.
|
// 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.
|
// A name oszillation changes from name A shortly to name B and back to A.
|
||||||
// In these cases, the name change will be suppressed.
|
// In these cases, the name change will be suppressed.
|
||||||
else if (TurnType::NewName == current_step.maneuver.instruction.type &&
|
else if (isCollapsableInstruction(current_step.maneuver.instruction) &&
|
||||||
TurnType::NewName == one_back_step.maneuver.instruction.type)
|
isCollapsableInstruction(one_back_step.maneuver.instruction))
|
||||||
{
|
{
|
||||||
// valid due to step_index starting at 2
|
// valid due to step_index starting at 2
|
||||||
const auto &coming_from_name = steps[two_back_index].name;
|
const auto &coming_from_name = steps[two_back_index].name;
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "extractor/guidance/toolkit.hpp"
|
#include "extractor/guidance/toolkit.hpp"
|
||||||
#include "extractor/guidance/turn_handler.hpp"
|
#include "extractor/guidance/turn_handler.hpp"
|
||||||
|
|
||||||
#include "util/simple_logger.hpp"
|
|
||||||
#include "util/guidance/toolkit.hpp"
|
#include "util/guidance/toolkit.hpp"
|
||||||
|
|
||||||
#include <limits>
|
#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
|
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);
|
BOOST_ASSERT(intersection[0].turn.angle < 0.001);
|
||||||
const auto isObviousOfTwo = [this](const ConnectedRoad road, const ConnectedRoad other) {
|
const auto isObviousOfTwo = [this](const ConnectedRoad road, const ConnectedRoad other) {
|
||||||
const auto first_class =
|
const auto first_class =
|
||||||
@ -134,14 +136,16 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
|
|||||||
{
|
{
|
||||||
assignFork(via_edge, intersection[2], intersection[1]);
|
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 =
|
intersection[1].turn.instruction =
|
||||||
getInstructionForObvious(intersection.size(), via_edge, false, intersection[1]);
|
getInstructionForObvious(intersection.size(), via_edge, false, intersection[1]);
|
||||||
intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]),
|
intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]),
|
||||||
DirectionModifier::SlightLeft};
|
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 =
|
intersection[2].turn.instruction =
|
||||||
getInstructionForObvious(intersection.size(), via_edge, false, intersection[2]);
|
getInstructionForObvious(intersection.size(), via_edge, false, intersection[2]);
|
||||||
@ -193,7 +197,8 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
|
|||||||
}
|
}
|
||||||
else
|
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(
|
intersection[1].turn.instruction = getInstructionForObvious(
|
||||||
3, via_edge, isThroughStreet(1, intersection), intersection[1]);
|
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)};
|
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(
|
intersection[2].turn.instruction = getInstructionForObvious(
|
||||||
3, via_edge, isThroughStreet(2, intersection), intersection[2]);
|
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
|
// check whether the obvious choice is actually a through street
|
||||||
if (obvious_index != 0)
|
if (obvious_index != 0)
|
||||||
{
|
{
|
||||||
intersection[obvious_index].turn.instruction = getInstructionForObvious(
|
intersection[obvious_index].turn.instruction = getInstructionForObvious(
|
||||||
intersection.size(), via_edge, isThroughStreet(obvious_index, intersection),
|
intersection.size(), via_edge, isThroughStreet(obvious_index, intersection),
|
||||||
intersection[obvious_index]);
|
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
|
// assign left/right turns
|
||||||
intersection = assignLeftTurns(via_edge, std::move(intersection), obvious_index + 1);
|
intersection = assignLeftTurns(via_edge, std::move(intersection), obvious_index + 1);
|
||||||
@ -302,7 +340,7 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assignTrivialTurns(via_edge,intersection,1,intersection.size());
|
assignTrivialTurns(via_edge, intersection, 1, intersection.size());
|
||||||
}
|
}
|
||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
@ -394,8 +432,7 @@ Intersection TurnHandler::assignLeftTurns(const EdgeID via_edge,
|
|||||||
const std::size_t starting_at) const
|
const std::size_t starting_at) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(starting_at <= intersection.size());
|
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());
|
BOOST_ASSERT(!intersection.empty());
|
||||||
|
|
||||||
for (auto &road : intersection)
|
for (auto &road : intersection)
|
||||||
@ -410,7 +447,6 @@ Intersection TurnHandler::assignLeftTurns(const EdgeID via_edge,
|
|||||||
intersection = assignRightTurns(via_edge, std::move(intersection), count);
|
intersection = assignRightTurns(via_edge, std::move(intersection), count);
|
||||||
switch_left_and_right(intersection);
|
switch_left_and_right(intersection);
|
||||||
|
|
||||||
|
|
||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,18 +573,6 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge,
|
|||||||
}
|
}
|
||||||
else
|
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);
|
assignTrivialTurns(via_edge, intersection, 1, up_to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user