improved fork handling

This commit is contained in:
Moritz Kobitzsch 2016-03-04 12:17:06 +01:00 committed by Patrick Niklaus
parent c337d55d45
commit a1f1da4c16
2 changed files with 160 additions and 20 deletions

View File

@ -221,6 +221,17 @@ AnalyzeTurn(const NodeID node_u,
const double angle, const double angle,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph); const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
// Assignment of specific turn types
void assignFork(const EdgeID via_edge,
TurnCandidate &left,
TurnCandidate &right,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
void assignFork(const EdgeID via_edge,
TurnCandidate &left,
TurnCandidate &center,
TurnCandidate &right,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
} // namespace detail } // namespace detail
} // namespace guidance } // namespace guidance
} // namespace extractor } // namespace extractor

View File

@ -4,6 +4,7 @@
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include <cstddef> #include <cstddef>
#include <limits>
namespace osrm namespace osrm
{ {
@ -29,6 +30,11 @@ const unsigned constexpr INVALID_NAME_ID = 0;
using EdgeData = util::NodeBasedDynamicGraph::EdgeData; using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
bool requiresAnnouncedment(const EdgeData &from, const EdgeData &to)
{
return !from.IsCompatibleTo(to);
}
struct Localizer struct Localizer
{ {
const std::vector<QueryNode> *node_info_list = nullptr; const std::vector<QueryNode> *node_info_list = nullptr;
@ -282,7 +288,6 @@ inline std::vector<TurnCandidate> fallbackTurnAssignmentMotorway(
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)
{ {
util::SimpleLogger().Write(logWARNING) << "Fallback turn assignment";
for (auto &candidate : turn_candidates) for (auto &candidate : turn_candidates)
{ {
const auto &out_data = node_based_graph->GetEdgeData(candidate.eid); const auto &out_data = node_based_graph->GetEdgeData(candidate.eid);
@ -390,8 +395,7 @@ handleFromMotorway(const NodeID from,
// splitting ramp at the end of a highway // splitting ramp at the end of a highway
if (turn_candidates[1].valid && turn_candidates[2].valid) if (turn_candidates[1].valid && turn_candidates[2].valid)
{ {
turn_candidates[1].instruction = {TurnType::Fork, DirectionModifier::SlightRight}; assignFork(via_edge, turn_candidates[2], turn_candidates[1], node_based_graph);
turn_candidates[2].instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
} }
else else
{ {
@ -404,11 +408,13 @@ handleFromMotorway(const NodeID from,
getTurnDirection(turn_candidates[2].angle)}; getTurnDirection(turn_candidates[2].angle)};
} }
} }
else else if (countValid(turn_candidates)) // check whether turns exist at all
{ {
// FALLBACK, this should hopefully never be reached // FALLBACK, this should hopefully never be reached
auto coord = localizer(node_based_graph->GetTarget(via_edge));
util::SimpleLogger().Write(logWARNING) util::SimpleLogger().Write(logWARNING)
<< "Fallback reached from motorway, no continue angle, " << turn_candidates.size() << "Fallback reached from motorway at " << toFloating(coord.lat) << " "
<< toFloating(coord.lon) << ", no continue angle, " << turn_candidates.size()
<< " candidates, " << countValid(turn_candidates) << " valid ones."; << " candidates, " << countValid(turn_candidates) << " valid ones.";
fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph);
} }
@ -486,21 +492,71 @@ handleFromMotorway(const NodeID from,
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);
util::SimpleLogger().Write(logWARNING) util::SimpleLogger().Write(logWARNING)
<< "Disable U-Turn on a freeway at " << "Disabled U-Turn on a freeway at "
<< localizer(node_based_graph->GetTarget(via_edge)); << localizer(node_based_graph->GetTarget(via_edge));
turn_candidates[0].valid = false; // UTURN on the freeway turn_candidates[0].valid = false; // UTURN on the freeway
} }
else if (exiting_motorways != 2 || turn_candidates.size() != 3) else if (exiting_motorways == 2)
{ {
util::SimpleLogger().Write(logWARNING) << "Found motorway junction with more than " // standard fork
"2 exiting motorways or additional ramps!" std::size_t first_valid = std::numeric_limits<std::size_t>::max(),
<< std::endl; second_valid = std::numeric_limits<std::size_t>::max();
fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); for (std::size_t i = 0; i < turn_candidates.size(); ++i)
{
if (turn_candidates[i].valid &&
isMotorwayClass(turn_candidates[i].eid, node_based_graph))
{
if (first_valid < turn_candidates.size())
{
second_valid = i;
break;
}
else
{
first_valid = i;
}
}
}
assignFork(via_edge, turn_candidates[second_valid], turn_candidates[first_valid],
node_based_graph);
}
else if (exiting_motorways == 3)
{
// triple fork
std::size_t first_valid = std::numeric_limits<std::size_t>::max(),
second_valid = std::numeric_limits<std::size_t>::max(),
third_valid = std::numeric_limits<std::size_t>::max();
for (std::size_t i = 0; i < turn_candidates.size(); ++i)
{
if (turn_candidates[i].valid &&
isMotorwayClass(turn_candidates[i].eid, node_based_graph))
{
if (second_valid < turn_candidates.size())
{
third_valid = i;
break;
}
else if (first_valid < turn_candidates.size())
{
second_valid = i;
}
else
{
first_valid = i;
}
}
}
assignFork(via_edge, turn_candidates[third_valid], turn_candidates[second_valid],
turn_candidates[first_valid], node_based_graph);
} }
else else
{ {
turn_candidates[1].instruction = {TurnType::Fork, DirectionModifier::SlightRight}; auto coord = localizer(node_based_graph->GetTarget(via_edge));
turn_candidates[2].instruction = {TurnType::Fork, DirectionModifier::SlightLeft}; util::SimpleLogger().Write(logWARNING)
<< "Found motorway junction with more than "
"2 exiting motorways or additional ramps at " << toFloating(coord.lat) << " "
<< toFloating(coord.lon);
fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph);
} }
} // done for more than one highway exit } // done for more than one highway exit
} }
@ -596,8 +652,8 @@ 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))
{ {
turn_candidates[1].instruction = {TurnType::Merge, DirectionModifier::SlightRight}; assignFork(via_edge, turn_candidates[2], turn_candidates[1],
turn_candidates[2].instruction = {TurnType::Merge, DirectionModifier::SlightLeft}; node_based_graph);
} }
else else
{ {
@ -743,11 +799,13 @@ bool isMotorwayJunction(const NodeID from,
angularDeviation(candidate.angle, 180) > 35) || angularDeviation(candidate.angle, 180) > 35) ||
(candidate.valid && angularDeviation(candidate.angle, 0) < 35)) (candidate.valid && angularDeviation(candidate.angle, 0) < 35))
return false; return false;
else if (candidate.valid && else if (out_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY ||
(out_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY || out_data.road_classification.road_class == FunctionalRoadClass::TRUNK)
out_data.road_classification.road_class == FunctionalRoadClass::TRUNK)) {
has_motorway = true; if (candidate.valid)
else if (candidate.valid && !isRampClass(out_data.road_classification.road_class)) has_motorway = true;
}
else if (!isRampClass(out_data.road_classification.road_class))
has_normal_roads = true; has_normal_roads = true;
} }
@ -1906,6 +1964,77 @@ handleConflicts(const NodeID from,
return turn_candidates; return turn_candidates;
} }
void assignFork(const EdgeID via_edge,
TurnCandidate &left,
TurnCandidate &right,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph)
{
const auto &in_data = node_based_graph->GetEdgeData(via_edge);
{ // left fork
const auto &out_data = node_based_graph->GetEdgeData(left.eid);
if (angularDeviation(left.angle, 180) < FUZZY_ANGLE_DIFFERENCE)
{
if (requiresAnnouncedment(in_data, out_data))
{
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
}
else
{
left.instruction = {TurnType::Suppressed, DirectionModifier::Straight};
}
}
else
{
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
}
}
{ // right fork
const auto &out_data = node_based_graph->GetEdgeData(right.eid);
if (angularDeviation(right.angle, 180) < FUZZY_ANGLE_DIFFERENCE)
{
if (requiresAnnouncedment(in_data, out_data))
{
right.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
}
else
{
right.instruction = {TurnType::Suppressed, DirectionModifier::Straight};
}
}
else
{
right.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
}
}
}
void assignFork(const EdgeID via_edge,
TurnCandidate &left,
TurnCandidate &center,
TurnCandidate &right,
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph)
{
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
if (angularDeviation(center.angle, 180) < FUZZY_ANGLE_DIFFERENCE)
{
const auto &in_data = node_based_graph->GetEdgeData(via_edge);
const auto &out_data = node_based_graph->GetEdgeData(center.eid);
if (requiresAnnouncedment(in_data, out_data))
{
center.instruction = {TurnType::Fork, DirectionModifier::Straight};
}
else
{
center.instruction = {TurnType::Suppressed, DirectionModifier::Straight};
}
}
else
{
center.instruction = {TurnType::Fork, DirectionModifier::Straight};
}
right.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
}
} // anemspace detail } // anemspace detail
} // namespace guidance } // namespace guidance
} // namespace extractor } // namespace extractor