advanced guidance on 5.0

This commit is contained in:
Moritz Kobitzsch
2016-02-24 10:29:23 +01:00
committed by Patrick Niklaus
parent 33f083b213
commit ef1e0e14ec
37 changed files with 1638 additions and 412 deletions
+30 -23
View File
@@ -5,15 +5,17 @@
#include "extractor/edge_based_edge.hpp"
#include "extractor/speed_profile.hpp"
#include "util/typedefs.hpp"
#include "extractor/restriction_map.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "util/deallocating_vector.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/query_node.hpp"
#include "extractor/turn_instructions.hpp"
#include "engine/guidance/turn_instruction.hpp"
#include "util/node_based_graph.hpp"
#include "extractor/restriction_map.hpp"
#include "util/typedefs.hpp"
#include "util/deallocating_vector.hpp"
#include <algorithm>
#include <cstdint>
@@ -68,12 +70,12 @@ class EdgeBasedGraphFactory
// with known angle.
// Handles special cases like u-turns and roundabouts
// For basic turns, the turn based on the angle-classification is returned
TurnInstruction AnalyzeTurn(const NodeID u,
const EdgeID e1,
const NodeID v,
const EdgeID e2,
const NodeID w,
const double angle) const;
engine::guidance::TurnInstruction AnalyzeTurn(const NodeID u,
const EdgeID e1,
const NodeID v,
const EdgeID e2,
const NodeID w,
const double angle) const;
std::int32_t GetTurnPenalty(double angle, lua_State *lua_state) const;
@@ -130,9 +132,9 @@ class EdgeBasedGraphFactory
{
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?
double angle; // the approximated angle of the turn
engine::guidance::TurnInstruction instruction; // a proposed instruction
double confidence; // how close to the border is the turn?
std::string toString() const
{
@@ -143,7 +145,8 @@ class EdgeBasedGraphFactory
result += " angle: ";
result += std::to_string(angle);
result += " instruction: ";
result += std::to_string(static_cast<std::int32_t>(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;
@@ -153,19 +156,23 @@ class EdgeBasedGraphFactory
// Use In Order to generate base turns
// cannot be const due to the counters...
std::vector<TurnCandidate> getTurnCandidates(NodeID from, EdgeID via_edge);
std::vector<TurnCandidate> optimizeCandidates(NodeID via_edge,
std::vector<TurnCandidate> getTurnCandidates(const NodeID from, const EdgeID via_edge);
std::vector<TurnCandidate> optimizeCandidates(const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<TurnCandidate> suppressTurns(EdgeID via_edge,
std::vector<TurnCandidate> optimizeRamps(const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
QueryNode getRepresentativeCoordinate(const NodeID src,
const NodeID tgt,
const EdgeID via_eid,
bool INVERTED) const;
engine::guidance::TurnType
checkForkAndEnd(const EdgeID via_edge, const std::vector<TurnCandidate> &turn_candidates) const;
std::vector<TurnCandidate> handleForkAndEnd(const engine::guidance::TurnType type,
std::vector<TurnCandidate> turn_candidates) const;
bool isObviousChoice(EdgeID coming_from_eid,
std::size_t turn_index,
std::vector<TurnCandidate> suppressTurns(const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
bool isObviousChoice(const EdgeID coming_from_eid,
const std::size_t turn_index,
const std::vector<TurnCandidate> &turn_candidates) const;
std::size_t restricted_turns_counter;
+3
View File
@@ -3,6 +3,7 @@
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
#include "engine/guidance/classification_data.hpp"
#include <string>
#include <vector>
@@ -33,6 +34,7 @@ struct ExtractionWay
name.clear();
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
road_classification_data.invalidate();
}
// These accessors exists because it's not possible to take the address of a bitfield,
@@ -51,6 +53,7 @@ struct ExtractionWay
bool is_startpoint;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
engine::guidance::RoadClassificationData road_classification_data;
};
}
}
+11 -5
View File
@@ -9,6 +9,7 @@
#include "osrm/coordinate.hpp"
#include <utility>
#include "engine/guidance/classification_data.hpp"
namespace osrm
{
@@ -50,7 +51,8 @@ struct InternalExtractorEdge
false,
true,
TRAVEL_MODE_INACCESSIBLE,
false)
false,
engine::guidance::RoadClassificationData::INVALID())
{
}
@@ -64,7 +66,8 @@ struct InternalExtractorEdge
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
bool is_split)
bool is_split,
engine::guidance::RoadClassificationData road_classification)
: result(OSMNodeID(source),
OSMNodeID(target),
name_id,
@@ -75,7 +78,8 @@ struct InternalExtractorEdge
access_restricted,
startpoint,
travel_mode,
is_split),
is_split,
std::move(road_classification)),
weight_data(std::move(weight_data))
{
}
@@ -91,12 +95,14 @@ struct InternalExtractorEdge
static InternalExtractorEdge min_osm_value()
{
return InternalExtractorEdge(MIN_OSM_NODEID, MIN_OSM_NODEID, 0, WeightData(), false, false,
false, false, true, TRAVEL_MODE_INACCESSIBLE, false);
false, false, true, TRAVEL_MODE_INACCESSIBLE, false,
engine::guidance::RoadClassificationData::INVALID());
}
static InternalExtractorEdge max_osm_value()
{
return InternalExtractorEdge(MAX_OSM_NODEID, MAX_OSM_NODEID, 0, WeightData(), false, false,
false, false, true, TRAVEL_MODE_INACCESSIBLE, false);
false, false, true, TRAVEL_MODE_INACCESSIBLE, false,
engine::guidance::RoadClassificationData::INVALID());
}
static InternalExtractorEdge min_internal_value()
+27 -16
View File
@@ -4,6 +4,8 @@
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
#include "engine/guidance/classification_data.hpp"
namespace osrm
{
namespace extractor
@@ -23,7 +25,8 @@ struct NodeBasedEdge
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
bool is_split);
bool is_split,
engine::guidance::RoadClassificationData road_classification);
bool operator<(const NodeBasedEdge &other) const;
@@ -38,6 +41,7 @@ struct NodeBasedEdge
bool startpoint : 1;
bool is_split : 1;
TravelMode travel_mode : 4;
engine::guidance::RoadClassificationData road_classification;
};
struct NodeBasedEdgeWithOSM : NodeBasedEdge
@@ -52,7 +56,8 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
bool is_split);
bool is_split,
engine::guidance::RoadClassificationData road_classification);
OSMNodeID osm_source_id;
OSMNodeID osm_target_id;
@@ -65,6 +70,7 @@ inline NodeBasedEdge::NodeBasedEdge()
backward(false), roundabout(false), access_restricted(false), startpoint(true),
is_split(false), travel_mode(false)
{
road_classification.invalidate();
}
inline NodeBasedEdge::NodeBasedEdge(NodeID source,
@@ -77,10 +83,12 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
bool is_split)
bool is_split,
engine::guidance::RoadClassificationData road_classification)
: source(source), target(target), name_id(name_id), weight(weight), forward(forward),
backward(backward), roundabout(roundabout), access_restricted(access_restricted),
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode)
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode),
road_classification(std::move(road_classification))
{
}
@@ -101,17 +109,19 @@ inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
return source < other.source;
}
inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
OSMNodeID target,
NodeID name_id,
EdgeWeight weight,
bool forward,
bool backward,
bool roundabout,
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
bool is_split)
inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(
OSMNodeID source,
OSMNodeID target,
NodeID name_id,
EdgeWeight weight,
bool forward,
bool backward,
bool roundabout,
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
bool is_split,
engine::guidance::RoadClassificationData road_classification)
: NodeBasedEdge(SPECIAL_NODEID,
SPECIAL_NODEID,
name_id,
@@ -122,7 +132,8 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
access_restricted,
startpoint,
travel_mode,
is_split),
is_split,
std::move(road_classification)),
osm_source_id(std::move(source)), osm_target_id(std::move(target))
{
}
+5 -4
View File
@@ -2,7 +2,7 @@
#define ORIGINAL_EDGE_DATA_HPP
#include "extractor/travel_mode.hpp"
#include "extractor/turn_instructions.hpp"
#include "engine/guidance/turn_instruction.hpp"
#include "util/typedefs.hpp"
#include <limits>
@@ -16,7 +16,7 @@ struct OriginalEdgeData
{
explicit OriginalEdgeData(NodeID via_node,
unsigned name_id,
TurnInstruction turn_instruction,
engine::guidance::TurnInstruction turn_instruction,
TravelMode travel_mode)
: via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
travel_mode(travel_mode)
@@ -25,14 +25,15 @@ struct OriginalEdgeData
OriginalEdgeData()
: via_node(std::numeric_limits<unsigned>::max()),
name_id(std::numeric_limits<unsigned>::max()), turn_instruction(TurnInstruction::NoTurn),
name_id(std::numeric_limits<unsigned>::max()),
turn_instruction(engine::guidance::TurnInstruction::INVALID()),
travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
NodeID via_node;
unsigned name_id;
TurnInstruction turn_instruction;
engine::guidance::TurnInstruction turn_instruction;
TravelMode travel_mode;
};
}
-182
View File
@@ -1,182 +0,0 @@
#ifndef TURN_INSTRUCTIONS_HPP
#define TURN_INSTRUCTIONS_HPP
#include <algorithm>
#include <cmath>
#include <boost/assert.hpp>
namespace osrm
{
namespace extractor
{
enum class TurnInstruction : unsigned char
{
NoTurn = 0,
GoStraight,
TurnSlightRight,
TurnRight,
TurnSharpRight,
UTurn,
TurnSharpLeft,
TurnLeft,
TurnSlightLeft,
ReachViaLocation,
HeadOn,
EnterRoundAbout,
LeaveRoundAbout,
StayOnRoundAbout,
StartAtEndOfStreet,
ReachedYourDestination,
NameChanges,
EnterAgainstAllowedDirection,
LeaveAgainstAllowedDirection,
InverseAccessRestrictionFlag = 127,
AccessRestrictionFlag = 128,
AccessRestrictionPenalty = 129
};
// shiftable turns to left and right
const constexpr bool shiftable_left[] = {false, false, true, true, true, false, false, true, true};
const constexpr bool shiftable_right[] = {false, false, true, true, false, false, true, true, true};
inline TurnInstruction shiftTurnToLeft(TurnInstruction turn)
{
BOOST_ASSERT_MSG(static_cast<int>(turn) < 9,
"Shift turn only supports basic turn instructions");
if (turn > TurnInstruction::TurnSlightLeft)
return turn;
else
return shiftable_left[static_cast<int>(turn)]
? (static_cast<TurnInstruction>(static_cast<int>(turn) - 1))
: turn;
}
inline TurnInstruction shiftTurnToRight(TurnInstruction turn)
{
BOOST_ASSERT_MSG(static_cast<int>(turn) < 9,
"Shift turn only supports basic turn instructions");
if (turn > TurnInstruction::TurnSlightLeft)
return turn;
else
return shiftable_right[static_cast<int>(turn)]
? (static_cast<TurnInstruction>(static_cast<int>(turn) + 1))
: turn;
}
inline double angularDeviation(const double angle, const double from)
{
const double deviation = std::abs(angle - from);
return std::min(360 - deviation, deviation);
}
inline double getAngularPenalty(const double angle, TurnInstruction instruction)
{
BOOST_ASSERT_MSG(static_cast<int>(instruction) < 9,
"Angular penalty only supports basic turn instructions");
const double center[] = {180, 180, 135, 90, 45,
0, 315, 270, 225}; // centers of turns from getTurnDirection
return angularDeviation(center[static_cast<int>(instruction)], angle);
}
inline double getTurnConfidence(const double angle, TurnInstruction instruction)
{
// special handling of U-Turns and Roundabout
if (instruction >= TurnInstruction::HeadOn || instruction == TurnInstruction::UTurn ||
instruction == TurnInstruction::NoTurn || instruction == TurnInstruction::EnterRoundAbout ||
instruction == TurnInstruction::StayOnRoundAbout || instruction == TurnInstruction::LeaveRoundAbout )
return 1.0;
BOOST_ASSERT_MSG(static_cast<int>(instruction) < 9,
"Turn confidence only supports basic turn instructions");
const double deviations[] = {10, 10, 35, 50, 45, 0, 45, 50, 35};
const double difference = getAngularPenalty(angle, instruction);
const double max_deviation = deviations[static_cast<int>(instruction)];
return 1.0 - (difference / max_deviation) * (difference / max_deviation);
}
// Translates between angles and their human-friendly directional representation
inline TurnInstruction getTurnDirection(const double angle)
{
// An angle of zero is a u-turn
// 180 goes perfectly straight
// 0-180 are right turns
// 180-360 are left turns
if (angle > 0 && angle < 60)
return TurnInstruction::TurnSharpRight;
if (angle >= 60 && angle < 140)
return TurnInstruction::TurnRight;
if (angle >= 140 && angle < 170)
return TurnInstruction::TurnSlightRight;
if (angle >= 170 && angle <= 190)
return TurnInstruction::GoStraight;
if (angle > 190 && angle <= 220)
return TurnInstruction::TurnSlightLeft;
if (angle > 220 && angle <= 300)
return TurnInstruction::TurnLeft;
if (angle > 300 && angle < 360)
return TurnInstruction::TurnSharpLeft;
return TurnInstruction::UTurn;
}
// Decides if a turn is needed to be done for the current instruction
inline bool isTurnNecessary(const TurnInstruction turn_instruction)
{
if (TurnInstruction::NoTurn == turn_instruction ||
TurnInstruction::StayOnRoundAbout == turn_instruction)
{
return false;
}
return true;
}
inline bool resolve(TurnInstruction &to_resolve, const TurnInstruction neighbor, bool resolve_right)
{
const auto shifted_turn =
resolve_right ? shiftTurnToRight(to_resolve) : shiftTurnToLeft(to_resolve);
if (shifted_turn == neighbor || shifted_turn == to_resolve)
return false;
to_resolve = shifted_turn;
return true;
}
inline bool resolveTransitive(TurnInstruction &first,
TurnInstruction &second,
const TurnInstruction third,
bool resolve_right)
{
if (resolve(second, third, resolve_right))
{
first = resolve_right ? shiftTurnToRight(first) : shiftTurnToLeft(first);
return true;
}
return false;
}
inline bool isSlightTurn(const TurnInstruction turn)
{
return turn == TurnInstruction::GoStraight || turn == TurnInstruction::TurnSlightRight ||
turn == TurnInstruction::TurnSlightLeft || turn == TurnInstruction::NoTurn;
}
inline bool isSharpTurn(const TurnInstruction turn)
{
return turn == TurnInstruction::TurnSharpLeft || turn == TurnInstruction::TurnSharpRight;
}
inline bool isStraight(const TurnInstruction turn)
{
return turn == TurnInstruction::GoStraight || turn == TurnInstruction::NoTurn;
}
inline bool isConflict(const TurnInstruction first, const TurnInstruction second)
{
return first == second || (isStraight(first) && isStraight(second));
}
}
}
#endif /* TURN_INSTRUCTIONS_HPP */