start of four way turns

This commit is contained in:
Moritz Kobitzsch 2016-03-04 15:10:33 +01:00 committed by Patrick Niklaus
parent 119487f1aa
commit 01318a08b4
2 changed files with 142 additions and 51 deletions

View File

@ -111,10 +111,11 @@ bool isMotorwayJunction(const NodeID from,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph); const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
// Decide whether a turn is a turn or a ramp access // Decide whether a turn is a turn or a ramp access
TurnType turnOrRamp(const NodeID from, TurnType
const EdgeID via_edge, findBasicTurnType(const NodeID from,
const TurnCandidate &candidate, const EdgeID via_edge,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph); const TurnCandidate &candidate,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
// Get the Instruction for an obvious turn // Get the Instruction for an obvious turn
// Instruction will be a silent instruction // Instruction will be a silent instruction

View File

@ -5,6 +5,7 @@
#include <cstddef> #include <cstddef>
#include <limits> #include <limits>
#include <iomanip>
namespace osrm namespace osrm
{ {
@ -23,6 +24,7 @@ const double constexpr STRAIGHT_ANGLE = 180.;
const double constexpr MAXIMAL_ALLOWED_NO_TURN_DEVIATION = 2.; const double constexpr MAXIMAL_ALLOWED_NO_TURN_DEVIATION = 2.;
// angle that lies between two nearly indistinguishable roads // angle that lies between two nearly indistinguishable roads
const double constexpr NARROW_TURN_ANGLE = 35.; const double constexpr NARROW_TURN_ANGLE = 35.;
const double constexpr WELL_DISTINCT_ANGLE = 50;
// angle difference that can be classified as straight, if its the only narrow turn // angle difference that can be classified as straight, if its the only narrow turn
const double constexpr FUZZY_ANGLE_DIFFERENCE = 15.; const double constexpr FUZZY_ANGLE_DIFFERENCE = 15.;
const double constexpr DISTINCTION_RATIO = 2; const double constexpr DISTINCTION_RATIO = 2;
@ -105,37 +107,35 @@ getTurns(const NodeID from,
} }
if (detail::isBasicJunction(from, via_edge, turn_candidates, node_based_graph) && if (detail::isBasicJunction(from, via_edge, turn_candidates, node_based_graph) &&
turn_candidates.size() <= 3) // TODO change when larger junctions are handled turn_candidates.size() <= 4) // TODO change when larger junctions are handled
{ {
if (turn_candidates.size() == 1) if (turn_candidates.size() == 1)
{ {
return detail::handleOneWayTurn(from, via_edge, std::move(turn_candidates), turn_candidates = detail::handleOneWayTurn(from, via_edge, std::move(turn_candidates),
node_based_graph); node_based_graph);
} }
if (turn_candidates.size() == 2) if (turn_candidates.size() == 2)
{ {
return detail::handleTwoWayTurn(from, via_edge, std::move(turn_candidates), turn_candidates = detail::handleTwoWayTurn(from, via_edge, std::move(turn_candidates),
node_based_graph); node_based_graph);
} }
if (turn_candidates.size() == 3) if (turn_candidates.size() == 3)
{ {
return detail::handleConflicts( detail::handleThreeWayTurn(from, via_edge, std::move(turn_candidates),
from, via_edge, detail::handleThreeWayTurn( node_based_graph);
from, via_edge, std::move(turn_candidates), node_based_graph),
node_based_graph);
} }
if (turn_candidates.size() == 4) if (turn_candidates.size() == 4)
{ {
return detail::handleConflicts( detail::handleFourWayTurn(from, via_edge, std::move(turn_candidates), node_based_graph);
from, via_edge, detail::handleFourWayTurn( }
from, via_edge, std::move(turn_candidates), node_based_graph), else
node_based_graph); {
turn_candidates = detail::handleComplexTurn(from, via_edge, std::move(turn_candidates),
node_based_graph);
} }
// complex intersection, potentially requires conflict resolution // complex intersection, potentially requires conflict resolution
return detail::handleConflicts( return detail::handleConflicts(from, via_edge, std::move(turn_candidates),
from, via_edge, node_based_graph);
detail::handleComplexTurn(from, via_edge, std::move(turn_candidates), node_based_graph),
node_based_graph);
} }
#if PRINT_DEBUG_CANDIDATES #if PRINT_DEBUG_CANDIDATES
@ -413,9 +413,10 @@ handleFromMotorway(const NodeID from,
// FALLBACK, this should hopefully never be reached // FALLBACK, this should hopefully never be reached
auto coord = localizer(node_based_graph->GetTarget(via_edge)); auto coord = localizer(node_based_graph->GetTarget(via_edge));
util::SimpleLogger().Write(logWARNING) util::SimpleLogger().Write(logWARNING)
<< "Fallback reached from motorway at " << toFloating(coord.lat) << " " << "Fallback reached from motorway at " << std::setprecision(12)
<< toFloating(coord.lon) << ", no continue angle, " << turn_candidates.size() << toFloating(coord.lat) << " " << toFloating(coord.lon) << ", no continue angle, "
<< " candidates, " << countValid(turn_candidates) << " valid ones."; << turn_candidates.size() << " candidates, " << countValid(turn_candidates)
<< " valid ones.";
fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph);
} }
} }
@ -554,8 +555,8 @@ handleFromMotorway(const NodeID from,
auto coord = localizer(node_based_graph->GetTarget(via_edge)); auto coord = localizer(node_based_graph->GetTarget(via_edge));
util::SimpleLogger().Write(logWARNING) util::SimpleLogger().Write(logWARNING)
<< "Found motorway junction with more than " << "Found motorway junction with more than "
"2 exiting motorways or additional ramps at " << toFloating(coord.lat) << " " "2 exiting motorways or additional ramps at " << std::setprecision(12)
<< toFloating(coord.lon); << toFloating(coord.lat) << " " << toFloating(coord.lon);
fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph);
} }
} // done for more than one highway exit } // done for more than one highway exit
@ -652,8 +653,7 @@ handleMotorwayRamp(const NodeID from,
if (isMotorwayClass(turn_candidates[1].eid, node_based_graph) && if (isMotorwayClass(turn_candidates[1].eid, node_based_graph) &&
isMotorwayClass(turn_candidates[2].eid, node_based_graph)) isMotorwayClass(turn_candidates[2].eid, node_based_graph))
{ {
assignFork(via_edge, turn_candidates[2], turn_candidates[1], assignFork(via_edge, turn_candidates[2], turn_candidates[1], node_based_graph);
node_based_graph);
} }
else else
{ {
@ -818,18 +818,28 @@ bool isMotorwayJunction(const NodeID from,
in_data.road_classification.road_class == FunctionalRoadClass::TRUNK; in_data.road_classification.road_class == FunctionalRoadClass::TRUNK;
} }
TurnType turnOrRamp(const NodeID from, TurnType
const EdgeID via_edge, findBasicTurnType(const NodeID from,
const TurnCandidate &candidate, const EdgeID via_edge,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph) const TurnCandidate &candidate,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph)
{ {
bool on_ramp = const auto &in_data = node_based_graph->GetEdgeData(via_edge);
isRampClass(node_based_graph->GetEdgeData(via_edge).road_classification.road_class); const auto &out_data = node_based_graph->GetEdgeData(candidate.eid);
bool onto_ramp = bool on_ramp = isRampClass(in_data.road_classification.road_class);
isRampClass(node_based_graph->GetEdgeData(candidate.eid).road_classification.road_class);
return (!on_ramp && onto_ramp) ? TurnType::Ramp : TurnType::Turn; bool onto_ramp = isRampClass(out_data.road_classification.road_class);
if (!onto_ramp && onto_ramp)
return TurnType::Ramp;
if (in_data.name_id == out_data.name_id && in_data.name_id != INVALID_NAME_ID)
{
return TurnType::Continue;
}
return TurnType::Turn;
} }
TurnInstruction TurnInstruction
@ -862,7 +872,7 @@ getInstructionForObvious(const NodeID from,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph) const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph)
{ {
if (turnOrRamp(from, via_edge, candidate, node_based_graph) == TurnType::Turn) if (findBasicTurnType(from, via_edge, candidate, node_based_graph) == TurnType::Turn)
{ {
return noTurnOrNewName(from, via_edge, candidate, node_based_graph); return noTurnOrNewName(from, via_edge, candidate, node_based_graph);
} }
@ -943,7 +953,8 @@ handleThreeWayTurn(const NodeID from,
{ {
if (turn_candidates[1].valid && turn_candidates[2].valid) if (turn_candidates[1].valid && turn_candidates[2].valid)
{ {
if (TurnType::Turn == turnOrRamp(from, via_edge, turn_candidates[1], node_based_graph)) if (TurnType::Turn ==
findBasicTurnType(from, via_edge, turn_candidates[1], node_based_graph))
{ {
if (angularDeviation(turn_candidates[1].angle, STRAIGHT_ANGLE) < if (angularDeviation(turn_candidates[1].angle, STRAIGHT_ANGLE) <
MAXIMAL_ALLOWED_NO_TURN_DEVIATION) MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
@ -961,7 +972,8 @@ handleThreeWayTurn(const NodeID from,
else else
turn_candidates[1].instruction = {TurnType::Ramp, DirectionModifier::SlightRight}; turn_candidates[1].instruction = {TurnType::Ramp, DirectionModifier::SlightRight};
if (TurnType::Turn == turnOrRamp(from, via_edge, turn_candidates[2], node_based_graph)) if (TurnType::Turn ==
findBasicTurnType(from, via_edge, turn_candidates[2], node_based_graph))
{ {
if (angularDeviation(turn_candidates[2].angle, STRAIGHT_ANGLE) < if (angularDeviation(turn_candidates[2].angle, STRAIGHT_ANGLE) <
MAXIMAL_ALLOWED_NO_TURN_DEVIATION) MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
@ -1003,14 +1015,16 @@ handleThreeWayTurn(const NodeID from,
{ {
if (turn_candidates[1].valid) if (turn_candidates[1].valid)
{ {
if (TurnType::Turn == turnOrRamp(from, via_edge, turn_candidates[1], node_based_graph)) if (TurnType::Ramp !=
findBasicTurnType(from, via_edge, turn_candidates[1], node_based_graph))
turn_candidates[1].instruction = {TurnType::EndOfRoad, DirectionModifier::Right}; turn_candidates[1].instruction = {TurnType::EndOfRoad, DirectionModifier::Right};
else else
turn_candidates[1].instruction = {TurnType::Ramp, DirectionModifier::Right}; turn_candidates[1].instruction = {TurnType::Ramp, DirectionModifier::Right};
} }
if (turn_candidates[2].valid) if (turn_candidates[2].valid)
{ {
if (TurnType::Turn == turnOrRamp(from, via_edge, turn_candidates[2], node_based_graph)) if (TurnType::Ramp !=
findBasicTurnType(from, via_edge, turn_candidates[2], node_based_graph))
turn_candidates[2].instruction = {TurnType::EndOfRoad, DirectionModifier::Left}; turn_candidates[2].instruction = {TurnType::EndOfRoad, DirectionModifier::Left};
else else
turn_candidates[2].instruction = {TurnType::Ramp, DirectionModifier::Left}; turn_candidates[2].instruction = {TurnType::Ramp, DirectionModifier::Left};
@ -1028,7 +1042,8 @@ handleThreeWayTurn(const NodeID from,
{ {
if (turn_candidates[1].valid) if (turn_candidates[1].valid)
{ {
if (turnOrRamp(from, via_edge, turn_candidates[1], node_based_graph) == TurnType::Turn) if (TurnType::Ramp !=
findBasicTurnType(from, via_edge, turn_candidates[1], node_based_graph))
turn_candidates[1].instruction = turn_candidates[1].instruction =
getInstructionForObvious(from, via_edge, turn_candidates[1], node_based_graph); getInstructionForObvious(from, via_edge, turn_candidates[1], node_based_graph);
else else
@ -1037,7 +1052,7 @@ handleThreeWayTurn(const NodeID from,
if (turn_candidates[2].valid) if (turn_candidates[2].valid)
{ {
turn_candidates[2].instruction = { turn_candidates[2].instruction = {
turnOrRamp(from, via_edge, turn_candidates[2], node_based_graph), findBasicTurnType(from, via_edge, turn_candidates[2], node_based_graph),
DirectionModifier::Left}; DirectionModifier::Left};
} }
} }
@ -1057,7 +1072,7 @@ handleThreeWayTurn(const NodeID from,
getInstructionForObvious(from, via_edge, turn_candidates[2], node_based_graph); getInstructionForObvious(from, via_edge, turn_candidates[2], node_based_graph);
if (turn_candidates[1].valid) if (turn_candidates[1].valid)
turn_candidates[1].instruction = { turn_candidates[1].instruction = {
turnOrRamp(from, via_edge, turn_candidates[1], node_based_graph), findBasicTurnType(from, via_edge, turn_candidates[1], node_based_graph),
DirectionModifier::Right}; DirectionModifier::Right};
} }
// merge onto a through street // merge onto a through street
@ -1166,7 +1181,82 @@ handleFourWayTurn(const NodeID from,
std::vector<TurnCandidate> turn_candidates, std::vector<TurnCandidate> turn_candidates,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph) const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph)
{ {
static int fallback_count = 0;
// basic turn, or slightly rotated basic turn, has straight ANGLE
if (angularDeviation(turn_candidates[2].angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE &&
angularDeviation(turn_candidates[0].angle, turn_candidates[1].angle) > NARROW_TURN_ANGLE &&
angularDeviation(turn_candidates[1].angle, turn_candidates[2].angle) > NARROW_TURN_ANGLE &&
angularDeviation(turn_candidates[2].angle, turn_candidates[3].angle) > NARROW_TURN_ANGLE &&
angularDeviation(turn_candidates[3].angle, turn_candidates[0].angle) > NARROW_TURN_ANGLE)
{
{ // Right
const auto type =
findBasicTurnType(from, via_edge, turn_candidates[1], node_based_graph);
turn_candidates[1].instruction = {type, DirectionModifier::Right};
}
{ // Straight
turn_candidates[2].instruction =
getInstructionForObvious(from, via_edge, turn_candidates[2], node_based_graph);
}
{ // Left
const auto type =
findBasicTurnType(from, via_edge, turn_candidates[3], node_based_graph);
turn_candidates[3].instruction = {type, DirectionModifier::Left};
}
}
// well differentiated turns
else if (angularDeviation(turn_candidates[1].angle, turn_candidates[2].angle) >
WELL_DISTINCT_ANGLE &&
angularDeviation(turn_candidates[2].angle, turn_candidates[3].angle) >
WELL_DISTINCT_ANGLE)
{
for (std::size_t i = 1; i < turn_candidates.size(); ++i)
{
const auto type =
findBasicTurnType(from, via_edge, turn_candidates[i], node_based_graph);
turn_candidates[i].instruction = {type, getTurnDirection(turn_candidates[i].angle)};
}
}
// * *
// * *
// * *
// * *
// * *
// * *
// Two roads at the right side of a street
else if ( false && angularDeviation(turn_candidates[3].angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE)
{
//currently unhandled
}
// * *
// * *
// * *
// * *
// * *
// * *
// Two roads at the left side of a street
else if ( false && angularDeviation(turn_candidates[1].angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE)
{
//currently unhandled
}
else
{
if (fallback_count++ < 10)
{
const auto coord = localizer(node_based_graph->GetTarget(via_edge));
util::SimpleLogger().Write(logWARNING)
<< "Resolved to keep fallback on four way turn assignment at "
<< std::setprecision(12) << toFloating(coord.lat) << " " << toFloating(coord.lon);
for (const auto &candidate : turn_candidates)
{
const auto &out_data = node_based_graph->GetEdgeData(candidate.eid);
util::SimpleLogger().Write(logWARNING)
<< "Candidate: " << candidate.toString() << " Name: " << out_data.name_id
<< " Road Class: " << (int)out_data.road_classification.road_class
<< " At: " << localizer(node_based_graph->GetTarget(candidate.eid));
}
}
}
#if PRINT_DEBUG_CANDIDATES #if PRINT_DEBUG_CANDIDATES
std::cout << "Basic Turn Candidates:\n"; std::cout << "Basic Turn Candidates:\n";
for (auto tc : turn_candidates) for (auto tc : turn_candidates)
@ -1319,8 +1409,8 @@ optimizeCandidates(const EdgeID via_eid,
{ {
util::SimpleLogger().Write(logWARNING) util::SimpleLogger().Write(logWARNING)
<< "[warning] conflicting turn angles, identical road duplicated? " << "[warning] conflicting turn angles, identical road duplicated? "
<< node_info_list[node_based_graph->GetTarget(via_eid)].lat << " " << std::setprecision(12) << node_info_list[node_based_graph->GetTarget(via_eid)].lat
<< node_info_list[node_based_graph->GetTarget(via_eid)].lon << std::endl; << " " << node_info_list[node_based_graph->GetTarget(via_eid)].lon << std::endl;
} }
if (isConflict(turn.instruction, left.instruction)) if (isConflict(turn.instruction, left.instruction))
{ {
@ -1972,7 +2062,7 @@ void assignFork(const EdgeID via_edge,
const auto &in_data = node_based_graph->GetEdgeData(via_edge); const auto &in_data = node_based_graph->GetEdgeData(via_edge);
{ // left fork { // left fork
const auto &out_data = node_based_graph->GetEdgeData(left.eid); const auto &out_data = node_based_graph->GetEdgeData(left.eid);
if (angularDeviation(left.angle, 180) < FUZZY_ANGLE_DIFFERENCE) if (angularDeviation(left.angle, 180) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
{ {
if (requiresAnnouncedment(in_data, out_data)) if (requiresAnnouncedment(in_data, out_data))
{ {
@ -1990,7 +2080,7 @@ void assignFork(const EdgeID via_edge,
} }
{ // right fork { // right fork
const auto &out_data = node_based_graph->GetEdgeData(right.eid); const auto &out_data = node_based_graph->GetEdgeData(right.eid);
if (angularDeviation(right.angle, 180) < FUZZY_ANGLE_DIFFERENCE) if (angularDeviation(right.angle, 180) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
{ {
if (requiresAnnouncedment(in_data, out_data)) if (requiresAnnouncedment(in_data, out_data))
{ {
@ -2015,7 +2105,7 @@ void assignFork(const EdgeID via_edge,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph) const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph)
{ {
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft}; left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
if (angularDeviation(center.angle, 180) < FUZZY_ANGLE_DIFFERENCE) if (angularDeviation(center.angle, 180) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
{ {
const auto &in_data = node_based_graph->GetEdgeData(via_edge); const auto &in_data = node_based_graph->GetEdgeData(via_edge);
const auto &out_data = node_based_graph->GetEdgeData(center.eid); const auto &out_data = node_based_graph->GetEdgeData(center.eid);