advanced guidance on 5.0
This commit is contained in:
committed by
Patrick Niklaus
parent
33f083b213
commit
ef1e0e14ec
@@ -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,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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
Reference in New Issue
Block a user