implement basic turn handling

This commit is contained in:
Moritz Kobitzsch 2016-03-07 14:52:26 +01:00 committed by Patrick Niklaus
parent 29fff4f51b
commit a674028c37
5 changed files with 947 additions and 631 deletions

View File

@ -249,10 +249,11 @@ inline double angularDeviation(const double angle, const double from)
return std::min(360 - deviation, deviation); return std::min(360 - deviation, deviation);
} }
inline double getAngularPenalty(const double angle, TurnInstruction instruction) inline double getAngularPenalty(const double angle, DirectionModifier modifier)
{ {
// these are not aligned with getTurnDirection but represent an ideal center
const double center[] = {0, 45, 90, 135, 180, 225, 270, 315}; const double center[] = {0, 45, 90, 135, 180, 225, 270, 315};
return angularDeviation(center[static_cast<int>(instruction.direction_modifier)], angle); return angularDeviation(center[static_cast<int>(modifier)], angle);
} }
inline double getTurnConfidence(const double angle, TurnInstruction instruction) inline double getTurnConfidence(const double angle, TurnInstruction instruction)
@ -262,8 +263,8 @@ inline double getTurnConfidence(const double angle, TurnInstruction instruction)
if (!isBasic(instruction.type) || instruction.direction_modifier == DirectionModifier::UTurn) if (!isBasic(instruction.type) || instruction.direction_modifier == DirectionModifier::UTurn)
return 1.0; return 1.0;
const double deviations[] = {0, 45, 50, 35, 10, 35, 50, 45}; const double deviations[] = {0, 45, 50, 30, 20, 30, 50, 45};
const double difference = getAngularPenalty(angle, instruction); const double difference = getAngularPenalty(angle, instruction.direction_modifier);
const double max_deviation = deviations[static_cast<int>(instruction.direction_modifier)]; const double max_deviation = deviations[static_cast<int>(instruction.direction_modifier)];
return 1.0 - (difference / max_deviation) * (difference / max_deviation); return 1.0 - (difference / max_deviation) * (difference / max_deviation);
} }
@ -281,7 +282,7 @@ inline DirectionModifier getTurnDirection(const double angle)
return DirectionModifier::Right; return DirectionModifier::Right;
if (angle >= 140 && angle < 170) if (angle >= 140 && angle < 170)
return DirectionModifier::SlightRight; return DirectionModifier::SlightRight;
if (angle >= 170 && angle <= 190) if (angle >= 165 && angle <= 195)
return DirectionModifier::Straight; return DirectionModifier::Straight;
if (angle > 190 && angle <= 220) if (angle > 190 && angle <= 220)
return DirectionModifier::SlightLeft; return DirectionModifier::SlightLeft;
@ -295,10 +296,14 @@ inline DirectionModifier getTurnDirection(const double angle)
// swaps left <-> right modifier types // swaps left <-> right modifier types
inline DirectionModifier mirrorDirectionModifier(const DirectionModifier modifier) inline DirectionModifier mirrorDirectionModifier(const DirectionModifier modifier)
{ {
const constexpr DirectionModifier results[] = { const constexpr DirectionModifier results[] = {DirectionModifier::UTurn,
DirectionModifier::UTurn, DirectionModifier::SharpLeft, DirectionModifier::Left, DirectionModifier::SharpLeft,
DirectionModifier::SlightLeft, DirectionModifier::Straight, DirectionModifier::SlightRight, DirectionModifier::Left,
DirectionModifier::Right, DirectionModifier::SharpRight}; DirectionModifier::SlightLeft,
DirectionModifier::Straight,
DirectionModifier::SlightRight,
DirectionModifier::Right,
DirectionModifier::SharpRight};
return results[modifier]; return results[modifier];
} }
@ -315,6 +320,17 @@ inline bool isLowPriorityRoadClass(const FunctionalRoadClass road_class)
road_class == FunctionalRoadClass::SERVICE; road_class == FunctionalRoadClass::SERVICE;
} }
inline bool isDistinct(const DirectionModifier first, const DirectionModifier second)
{
if ((first + 1) % detail::num_direction_modifiers == second)
return false;
if ((second + 1) % detail::num_direction_modifiers == first)
return false;
return true;
}
} // namespace guidance } // namespace guidance
} // namespace extractor } // namespace extractor
} // namespace osrm } // namespace osrm

View File

@ -11,6 +11,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <utility>
#include <unordered_set> #include <unordered_set>
namespace osrm namespace osrm
@ -149,11 +150,13 @@ class TurnAnalysis
std::vector<TurnCandidate> handleMotorwayJunction( std::vector<TurnCandidate> handleMotorwayJunction(
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const; const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const;
std::vector<TurnCandidate> handleFromMotorway( std::vector<TurnCandidate> handleFromMotorway(const NodeID from,
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const; const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<TurnCandidate> handleMotorwayRamp( std::vector<TurnCandidate> handleMotorwayRamp(const NodeID from,
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const; const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
// Utility function, setting basic turn types. Prepares for normal turn handling. // Utility function, setting basic turn types. Prepares for normal turn handling.
std::vector<TurnCandidate> setTurnTypes(const NodeID from, std::vector<TurnCandidate> setTurnTypes(const NodeID from,
@ -165,20 +168,6 @@ class TurnAnalysis
const EdgeID via_edge, const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const; std::vector<TurnCandidate> turn_candidates) const;
// Old fallbacks, to be removed
std::vector<TurnCandidate> optimizeRamps(const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<TurnCandidate> optimizeCandidates(const EdgeID via_eid,
std::vector<TurnCandidate> turn_candidates) const;
bool isObviousChoice(const EdgeID via_eid,
const std::size_t turn_index,
const std::vector<TurnCandidate> &turn_candidates) const;
std::vector<TurnCandidate> suppressTurns(const EdgeID via_eid,
std::vector<TurnCandidate> turn_candidates) const;
// node_u -- (edge_1) --> node_v -- (edge_2) --> node_w // node_u -- (edge_1) --> node_v -- (edge_2) --> node_w
TurnInstruction AnalyzeTurn(const NodeID node_u, TurnInstruction AnalyzeTurn(const NodeID node_u,
const EdgeID edge1, const EdgeID edge1,
@ -194,10 +183,20 @@ class TurnAnalysis
TurnCandidate &center, TurnCandidate &center,
TurnCandidate &right) const; TurnCandidate &right) const;
//Type specific fallbacks void
handleDistinctConflict(const EdgeID via_edge, TurnCandidate &left, TurnCandidate &right) const;
// Type specific fallbacks
std::vector<TurnCandidate> std::vector<TurnCandidate>
fallbackTurnAssignmentMotorway(std::vector<TurnCandidate> turn_candidates) const; fallbackTurnAssignmentMotorway(std::vector<TurnCandidate> turn_candidates) const;
//Classification
std::size_t findObviousTurn( const EdgeID via_edge, const std::vector<TurnCandidate> &turn_candidates) const;
std::pair<std::size_t,std::size_t> findFork( const EdgeID via_edge, const std::vector<TurnCandidate> &turn_candidates) const;
std::vector<TurnCandidate> assignLeftTurns( const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates, const std::size_t starting_at ) const;
std::vector<TurnCandidate> assignRightTurns( const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates, const std::size_t up_to ) const;
}; // class TurnAnalysis }; // class TurnAnalysis
} // namespace guidance } // namespace guidance

View File

@ -42,8 +42,16 @@ enum TurnType // at the moment we can support 32 turn types, without increasing
NewName, // no turn, but name changes NewName, // no turn, but name changes
Continue, // remain on a street Continue, // remain on a street
Turn, // basic turn Turn, // basic turn
FirstTurn, // First of x turns
SecondTurn, // Second of x turns
ThirdTurn, // Third of x turns
FourthTurn, // Fourth of x turns
Merge, // merge onto a street Merge, // merge onto a street
Ramp, // special turn (highway ramp exits) Ramp, // special turn (highway ramp exits)
FirstRamp, // first turn onto a ramp
SecondRamp, // second turn onto a ramp
ThirdRamp, // third turn onto a ramp
FourthRamp, // fourth turn onto a ramp
Fork, // fork road splitting up Fork, // fork road splitting up
EndOfRoad, // T intersection EndOfRoad, // T intersection
EnterRoundabout, // Entering a small Roundabout EnterRoundabout, // Entering a small Roundabout

View File

@ -28,23 +28,17 @@ namespace json
namespace detail namespace detail
{ {
const constexpr char *modifier_names[] = {"uturn", const constexpr char *modifier_names[] = {"uturn", "sharp right", "right", "slight right",
"sharp right", "straight", "slight left", "left", "sharp left"};
"right",
"slight right",
"straight",
"slight left",
"left",
"sharp left"};
// translations of TurnTypes. Not all types are exposed to the outside world. // translations of TurnTypes. Not all types are exposed to the outside world.
// invalid types should never be returned as part of the API // invalid types should never be returned as part of the API
const constexpr char *turn_type_names[] = { const constexpr char *turn_type_names[] = {
"invalid", "no turn", "invalid", "new name", "continue", "turn", "invalid", "no turn", "invalid", "new name", "continue", "turn",
"merge", "ramp", "fork", "end of road", "roundabout", "invalid", "turn", "turn", "turn", "merge", "ramp", "ramp",
"ramp", "ramp", "fork", "end of road", "roundabout", "invalid",
"roundabout", "invalid", "traffic circle", "invalid", "traffic circle", "invalid", "roundabout", "invalid", "traffic circle", "invalid", "traffic circle", "invalid",
"invalid", "restriction", "notification"}; "invalid", "restriction", "notification"};
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"}; const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
// Check whether to include a modifier in the result of the API // Check whether to include a modifier in the result of the API
@ -56,6 +50,23 @@ inline bool isValidModifier(const guidance::StepManeuver maneuver)
return true; return true;
} }
inline bool isMultiTurn(const TurnType type)
{
return (type == TurnType::FirstTurn || type == TurnType::SecondTurn ||
type == TurnType::ThirdTurn);
}
inline std::string getCount(const TurnType type)
{
if (type == TurnType::FirstTurn)
return "1";
if (type == TurnType::SecondTurn)
return "2";
if (type == TurnType::ThirdTurn)
return "3";
return "0";
}
std::string instructionTypeToString(const TurnType type) std::string instructionTypeToString(const TurnType type)
{ {
return turn_type_names[static_cast<std::size_t>(type)]; return turn_type_names[static_cast<std::size_t>(type)];
@ -141,6 +152,8 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
else else
step_maneuver.values["type"] = detail::waypointTypeToString(maneuver.waypoint_type); step_maneuver.values["type"] = detail::waypointTypeToString(maneuver.waypoint_type);
if (detail::isMultiTurn(maneuver.instruction.type))
step_maneuver.values["count"] = detail::getCount(maneuver.instruction.type);
if (detail::isValidModifier(maneuver)) if (detail::isValidModifier(maneuver))
step_maneuver.values["modifier"] = step_maneuver.values["modifier"] =
detail::instructionModifierToString(maneuver.instruction.direction_modifier); detail::instructionModifierToString(maneuver.instruction.direction_modifier);

File diff suppressed because it is too large Load Diff