Skip to content

Commit

Permalink
restructured to only return valid turns to the outside
Browse files Browse the repository at this point in the history
  • Loading branch information
Moritz Kobitzsch committed Mar 17, 2016
1 parent 8c1765f commit d2ac23c
Show file tree
Hide file tree
Showing 3 changed files with 875 additions and 871 deletions.
141 changes: 80 additions & 61 deletions include/extractor/guidance/turn_analysis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,51 @@ namespace extractor
namespace guidance
{

struct TurnCandidate
// What is exposed to the outside
struct TurnOperation
{
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 : public TurnOperation
{
ConnectedRoad(const EdgeID eid = SPECIAL_EDGEID,
const double angle = 0,
const TurnInstruction instruction = {TurnType::Invalid, DirectionModifier::UTurn},
const bool entry_allowed = false);

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] ";
std::string result = "[connection] ";
result += std::to_string(eid);
result += " valid: ";
result += std::to_string(valid);
result += " allows entry: ";
result += std::to_string(entry_allowed);
result += " angle: ";
result += std::to_string(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);
return result;
}
};

class TurnAnalysis
{

public:
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
Expand All @@ -59,7 +77,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;
Expand All @@ -69,11 +87,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
Expand All @@ -87,90 +106,84 @@ 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(const NodeID from_node,
const EdgeID via_eid,
std::vector<ConnectedRoad> intersection) const;

// TODO distinguish roundabouts and rotaries
// TODO handle bike/walk cases that allow crossing a roundabout!

// 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,
std::vector<ConnectedRoad> handleRoundabouts(const NodeID from,
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;
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,
std::vector<ConnectedRoad> handleOneWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> intersection) const;

// Mode Changes, new names...
std::vector<TurnCandidate> handleTwoWayTurn(const NodeID from,
std::vector<ConnectedRoad> handleTwoWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> intersection) const;

// Forks, T intersections and similar
std::vector<TurnCandidate> handleThreeWayTurn(const NodeID from,
std::vector<ConnectedRoad> handleThreeWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;

// Normal Intersection. Can still contain forks...
std::vector<TurnCandidate> handleFourWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> intersection) const;

// Fallback for turns of high complexion
std::vector<TurnCandidate> handleComplexTurn(const NodeID from,
std::vector<ConnectedRoad> handleComplexTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
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 NodeID from, const EdgeID via_edge, std::vector<ConnectedRoad> intersection) const;

std::vector<TurnCandidate> handleFromMotorway(const NodeID from,
std::vector<ConnectedRoad> handleFromMotorway(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> intersection) const;

std::vector<TurnCandidate> handleMotorwayRamp(const NodeID from,
std::vector<ConnectedRoad> handleMotorwayRamp(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
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;
std::vector<ConnectedRoad> intersection) const;

// Utility function to handle direction modifier conflicts if reasonably possible
std::vector<TurnCandidate> handleConflicts(const NodeID from,
std::vector<ConnectedRoad> handleConflicts(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> intersection) const;

// node_u -- (edge_1) --> node_v -- (edge_2) --> node_w
TurnInstruction AnalyzeTurn(const NodeID node_u,
Expand All @@ -181,25 +194,31 @@ class TurnAnalysis
const double angle) 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 &center,
TurnCandidate &right) const;
ConnectedRoad &left,
ConnectedRoad &center,
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;

//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;
std::vector<ConnectedRoad>
fallbackTurnAssignmentMotorway(std::vector<ConnectedRoad> intersection) 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 EdgeID via_edge, const std::vector<ConnectedRoad> &intersection) 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

Expand Down
7 changes: 2 additions & 5 deletions src/extractor/edge_based_graph_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,15 +316,12 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
}

++node_based_edge_counter;
auto turn_candidates = turn_analysis.getTurns(node_u, edge_from_u);
auto possible_turns = turn_analysis.getTurns(node_u, edge_from_u);

const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u);

for (const auto turn : turn_candidates)
for (const auto turn : possible_turns)
{
if (!turn.valid)
continue;

const double turn_angle = turn.angle;

// only add an edge if turn is not prohibited
Expand Down
Loading

0 comments on commit d2ac23c

Please sign in to comment.