restructured to only return valid turns to the outside + cleanup
This commit is contained in:
committed by
Patrick Niklaus
parent
71c0d5253d
commit
0cc23dec6f
@@ -17,7 +17,6 @@
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -391,6 +390,9 @@ inline bool requiresNameAnnounced(const std::string &from, const std::string &to
|
||||
|
||||
inline int getPriority( const FunctionalRoadClass road_class )
|
||||
{
|
||||
//The road priorities indicate which roads can bee seen as more or less equal.
|
||||
//They are used in Fork-Discovery. Possibly should be moved to profiles post v5?
|
||||
//A fork can happen between road types that are at most 1 priority apart from each other
|
||||
const constexpr int road_priority[] = {10, 0, 10, 2, 10, 4, 10, 6, 10, 8, 10, 11, 10, 12, 10, 14};
|
||||
return road_priority[static_cast<int>(road_class)];
|
||||
}
|
||||
@@ -398,6 +400,9 @@ inline int getPriority( const FunctionalRoadClass road_class )
|
||||
inline bool canBeSeenAsFork(const FunctionalRoadClass first, const FunctionalRoadClass second)
|
||||
{
|
||||
// forks require similar road categories
|
||||
// Based on the priorities assigned above, we can set forks only if the road priorities match closely.
|
||||
// Potentially we could include features like number of lanes here and others?
|
||||
// Should also be moved to profiles
|
||||
return std::abs(getPriority(first) - getPriority(second)) <= 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,33 +23,49 @@ namespace extractor
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
struct TurnCandidate
|
||||
// What is exposed to the outside
|
||||
struct TurnOperation final
|
||||
{
|
||||
EdgeID eid; // the id of the arc
|
||||
bool valid; // a turn may be relevant to good instructions, even if we cannot take the road
|
||||
double angle; // the approximated angle of the turn
|
||||
TurnInstruction instruction; // a proposed instruction
|
||||
double confidence; // how close to the border is the turn?
|
||||
EdgeID eid;
|
||||
double angle;
|
||||
TurnInstruction instruction;
|
||||
};
|
||||
|
||||
// For the turn analysis, we require a full list of all connected roads to determine the outcome.
|
||||
// Invalid turns can influence the perceived angles
|
||||
//
|
||||
// aaa(2)aa
|
||||
// a - bbbbb
|
||||
// aaa(1)aa
|
||||
//
|
||||
// will not be perceived as a turn from (1) -> b, and as a U-turn from (1) -> (2).
|
||||
// In addition, they can influence whether a turn is obvious or not.
|
||||
struct ConnectedRoad final
|
||||
{
|
||||
ConnectedRoad(const TurnOperation turn, const bool entry_allowed = false);
|
||||
|
||||
TurnOperation turn;
|
||||
bool entry_allowed; // a turn may be relevant to good instructions, even if we cannot take
|
||||
// the road
|
||||
|
||||
std::string toString() const
|
||||
{
|
||||
std::string result = "[turn] ";
|
||||
result += std::to_string(eid);
|
||||
result += " valid: ";
|
||||
result += std::to_string(valid);
|
||||
std::string result = "[connection] ";
|
||||
result += std::to_string(turn.eid);
|
||||
result += " allows entry: ";
|
||||
result += std::to_string(entry_allowed);
|
||||
result += " angle: ";
|
||||
result += std::to_string(angle);
|
||||
result += std::to_string(turn.angle);
|
||||
result += " instruction: ";
|
||||
result += std::to_string(static_cast<std::int32_t>(instruction.type)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(instruction.direction_modifier));
|
||||
result += " confidence: ";
|
||||
result += std::to_string(confidence);
|
||||
result += std::to_string(static_cast<std::int32_t>(turn.instruction.type)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(turn.instruction.direction_modifier));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class TurnAnalysis
|
||||
{
|
||||
|
||||
public:
|
||||
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
@@ -59,7 +75,7 @@ class TurnAnalysis
|
||||
const util::NameTable &name_table);
|
||||
|
||||
// the entry into the turn analysis
|
||||
std::vector<TurnCandidate> getTurns(const NodeID from_node, const EdgeID via_eid) const;
|
||||
std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const;
|
||||
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
@@ -69,11 +85,12 @@ class TurnAnalysis
|
||||
const CompressedEdgeContainer &compressed_edge_container;
|
||||
const util::NameTable &name_table;
|
||||
|
||||
// Check for restrictions/barriers and generate a list of valid and invalid turns present at the
|
||||
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
|
||||
// the
|
||||
// node reached
|
||||
// from `from_node` via `via_eid`
|
||||
// The resulting candidates have to be analysed for their actual instructions later on.
|
||||
std::vector<TurnCandidate> getTurnCandidates(const NodeID from_node,
|
||||
std::vector<ConnectedRoad> getConnectedRoads(const NodeID from_node,
|
||||
const EdgeID via_eid) const;
|
||||
|
||||
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
|
||||
@@ -87,10 +104,7 @@ class TurnAnalysis
|
||||
//
|
||||
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
|
||||
// 160
|
||||
std::vector<TurnCandidate>
|
||||
mergeSegregatedRoads(const NodeID from_node,
|
||||
const EdgeID via_eid,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
std::vector<ConnectedRoad> mergeSegregatedRoads(std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
// TODO distinguish roundabouts and rotaries
|
||||
// TODO handle bike/walk cases that allow crossing a roundabout!
|
||||
@@ -98,108 +112,86 @@ class TurnAnalysis
|
||||
// Processing of roundabouts
|
||||
// Produces instructions to enter/exit a roundabout or to stay on it.
|
||||
// Performs the distinction between roundabout and rotaries.
|
||||
std::vector<TurnCandidate> handleRoundabouts(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<ConnectedRoad> handleRoundabouts(const EdgeID via_edge,
|
||||
const bool on_roundabout,
|
||||
const bool can_enter_roundabout,
|
||||
const bool can_exit_roundabout,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
// Indicates a Junction containing a motoryway
|
||||
bool isMotorwayJunction(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
const std::vector<TurnCandidate> &turn_candidates) const;
|
||||
bool isMotorwayJunction(const EdgeID via_edge,
|
||||
const std::vector<ConnectedRoad> &intersection) const;
|
||||
|
||||
// Decide whether a turn is a turn or a ramp access
|
||||
TurnType findBasicTurnType(const EdgeID via_edge, const TurnCandidate &candidate) const;
|
||||
TurnType findBasicTurnType(const EdgeID via_edge, const ConnectedRoad &candidate) const;
|
||||
|
||||
// Get the Instruction for an obvious turn
|
||||
// Instruction will be a silent instruction
|
||||
TurnInstruction getInstructionForObvious(const std::size_t number_of_candidates,
|
||||
const EdgeID via_edge,
|
||||
const TurnCandidate &candidate) const;
|
||||
const ConnectedRoad &candidate) const;
|
||||
|
||||
// Helper Function that decides between NoTurn or NewName
|
||||
TurnInstruction
|
||||
noTurnOrNewName(const NodeID from, const EdgeID via_edge, const TurnCandidate &candidate) const;
|
||||
noTurnOrNewName(const NodeID from, const EdgeID via_edge, const ConnectedRoad &candidate) const;
|
||||
|
||||
// Basic Turn Handling
|
||||
|
||||
// Dead end.
|
||||
std::vector<TurnCandidate> handleOneWayTurn(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
std::vector<ConnectedRoad> handleOneWayTurn(std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
// Mode Changes, new names...
|
||||
std::vector<TurnCandidate> handleTwoWayTurn(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
std::vector<ConnectedRoad> handleTwoWayTurn(const EdgeID via_edge,
|
||||
std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
// Forks, T intersections and similar
|
||||
std::vector<TurnCandidate> handleThreeWayTurn(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
std::vector<ConnectedRoad> handleThreeWayTurn(const EdgeID via_edge,
|
||||
std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
// Normal Intersection. Can still contain forks...
|
||||
std::vector<TurnCandidate> handleFourWayTurn(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
|
||||
// Fallback for turns of high complexion
|
||||
std::vector<TurnCandidate> handleComplexTurn(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
// Handling of turns larger then degree three
|
||||
std::vector<ConnectedRoad> handleComplexTurn(const EdgeID via_edge,
|
||||
std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
// Any Junction containing motorways
|
||||
std::vector<TurnCandidate> handleMotorwayJunction(
|
||||
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const;
|
||||
std::vector<ConnectedRoad> handleMotorwayJunction(
|
||||
const EdgeID via_edge, std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
std::vector<TurnCandidate> handleFromMotorway(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
std::vector<ConnectedRoad> handleFromMotorway(const EdgeID via_edge,
|
||||
std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
std::vector<TurnCandidate> handleMotorwayRamp(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
std::vector<ConnectedRoad> handleMotorwayRamp(const EdgeID via_edge,
|
||||
std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
// Utility function, setting basic turn types. Prepares for normal turn handling.
|
||||
std::vector<TurnCandidate> setTurnTypes(const NodeID from,
|
||||
std::vector<ConnectedRoad> setTurnTypes(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
|
||||
// Utility function to handle direction modifier conflicts if reasonably possible
|
||||
std::vector<TurnCandidate> handleConflicts(const NodeID from,
|
||||
const EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
|
||||
// node_u -- (edge_1) --> node_v -- (edge_2) --> node_w
|
||||
TurnInstruction AnalyzeTurn(const NodeID node_u,
|
||||
const EdgeID edge1,
|
||||
const NodeID node_v,
|
||||
const EdgeID edge2,
|
||||
const NodeID node_w,
|
||||
const double angle) const;
|
||||
std::vector<ConnectedRoad> intersection) const;
|
||||
|
||||
// Assignment of specific turn types
|
||||
void assignFork(const EdgeID via_edge, TurnCandidate &left, TurnCandidate &right) const;
|
||||
void assignFork(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
|
||||
void assignFork(const EdgeID via_edge,
|
||||
TurnCandidate &left,
|
||||
TurnCandidate ¢er,
|
||||
TurnCandidate &right) const;
|
||||
ConnectedRoad &left,
|
||||
ConnectedRoad ¢er,
|
||||
ConnectedRoad &right) const;
|
||||
|
||||
void
|
||||
handleDistinctConflict(const EdgeID via_edge, TurnCandidate &left, TurnCandidate &right) const;
|
||||
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
|
||||
|
||||
// Type specific fallbacks
|
||||
std::vector<TurnCandidate>
|
||||
fallbackTurnAssignmentMotorway(std::vector<TurnCandidate> turn_candidates) const;
|
||||
std::vector<ConnectedRoad>
|
||||
fallbackTurnAssignmentMotorway(std::vector<ConnectedRoad> intersection) 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;
|
||||
// Classification
|
||||
std::size_t findObviousTurn(const EdgeID via_edge,
|
||||
const std::vector<ConnectedRoad> &intersection) const;
|
||||
std::pair<std::size_t, std::size_t>
|
||||
findFork(const std::vector<ConnectedRoad> &intersection) 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;
|
||||
std::vector<ConnectedRoad> assignLeftTurns(const EdgeID via_edge,
|
||||
std::vector<ConnectedRoad> intersection,
|
||||
const std::size_t starting_at) const;
|
||||
std::vector<ConnectedRoad> assignRightTurns(const EdgeID via_edge,
|
||||
std::vector<ConnectedRoad> intersection,
|
||||
const std::size_t up_to) const;
|
||||
|
||||
}; // class TurnAnalysis
|
||||
|
||||
|
||||
Reference in New Issue
Block a user