modify turn angles and instructions
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
#include "extractor/restriction_map.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
@@ -23,6 +25,7 @@
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
@@ -70,10 +73,18 @@ class EdgeBasedGraphFactory
|
||||
|
||||
unsigned GetHighestEdgeID();
|
||||
|
||||
TurnInstruction
|
||||
AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, const double angle) const;
|
||||
// Basic analysis of a turn (u --(e1)-- v --(e2)-- w)
|
||||
// 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;
|
||||
|
||||
int GetTurnPenalty(double angle, lua_State *lua_state) const;
|
||||
std::int32_t GetTurnPenalty(double angle, lua_State *lua_state) const;
|
||||
|
||||
private:
|
||||
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
|
||||
@@ -123,8 +134,54 @@ class EdgeBasedGraphFactory
|
||||
|
||||
void FlushVectorToStream(std::ofstream &edge_data_file,
|
||||
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||
|
||||
struct TurnCandidate
|
||||
{
|
||||
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?
|
||||
|
||||
std::string toString() const
|
||||
{
|
||||
std::string result = "[turn] ";
|
||||
result += std::to_string(eid);
|
||||
result += " valid: ";
|
||||
result += std::to_string(valid);
|
||||
result += " angle: ";
|
||||
result += std::to_string(angle);
|
||||
result += " instruction: ";
|
||||
result += std::to_string(static_cast<std::int32_t>(instruction));
|
||||
result += " confidence: ";
|
||||
result += std::to_string(confidence);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// 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> turn_candidates) const;
|
||||
std::vector<TurnCandidate> suppressTurns(EdgeID via_edge,
|
||||
std::vector<TurnCandidate> turn_candidates) const;
|
||||
|
||||
QueryNode getRepresentativeCoordinate(const NodeID src,
|
||||
const NodeID tgt,
|
||||
const EdgeID via_eid,
|
||||
bool INVERTED) const;
|
||||
|
||||
bool isObviousChoice(EdgeID coming_from_eid,
|
||||
std::size_t turn_index,
|
||||
const std::vector<TurnCandidate> &turn_candidates) const;
|
||||
|
||||
std::size_t restricted_turns_counter;
|
||||
std::size_t skipped_uturns_counter;
|
||||
std::size_t skipped_barrier_turns_counter;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */
|
||||
|
||||
@@ -17,7 +17,7 @@ struct QueryNode
|
||||
using key_type = OSMNodeID; // type of NodeID
|
||||
using value_type = int; // type of lat,lons
|
||||
|
||||
explicit QueryNode(int lat, int lon, OSMNodeID node_id)
|
||||
explicit QueryNode(int lat, int lon, key_type node_id)
|
||||
: lat(lat), lon(lon), node_id(std::move(node_id))
|
||||
{
|
||||
}
|
||||
@@ -29,7 +29,7 @@ struct QueryNode
|
||||
|
||||
int lat;
|
||||
int lon;
|
||||
OSMNodeID node_id;
|
||||
key_type node_id;
|
||||
|
||||
static QueryNode min_value()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#ifndef TURN_INSTRUCTIONS_HPP
|
||||
#define TURN_INSTRUCTIONS_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
@@ -24,6 +29,7 @@ enum class TurnInstruction : unsigned char
|
||||
StayOnRoundAbout,
|
||||
StartAtEndOfStreet,
|
||||
ReachedYourDestination,
|
||||
NameChanges,
|
||||
EnterAgainstAllowedDirection,
|
||||
LeaveAgainstAllowedDirection,
|
||||
InverseAccessRestrictionFlag = 127,
|
||||
@@ -31,37 +37,87 @@ enum class TurnInstruction : unsigned char
|
||||
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)
|
||||
{
|
||||
if (angle >= 23 && angle < 67)
|
||||
{
|
||||
// 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 >= 67 && angle < 113)
|
||||
{
|
||||
if (angle >= 60 && angle < 140)
|
||||
return TurnInstruction::TurnRight;
|
||||
}
|
||||
if (angle >= 113 && angle < 158)
|
||||
{
|
||||
if (angle >= 140 && angle < 170)
|
||||
return TurnInstruction::TurnSlightRight;
|
||||
}
|
||||
if (angle >= 158 && angle < 202)
|
||||
{
|
||||
if (angle >= 170 && angle <= 190)
|
||||
return TurnInstruction::GoStraight;
|
||||
}
|
||||
if (angle >= 202 && angle < 248)
|
||||
{
|
||||
if (angle > 190 && angle <= 220)
|
||||
return TurnInstruction::TurnSlightLeft;
|
||||
}
|
||||
if (angle >= 248 && angle < 292)
|
||||
{
|
||||
if (angle > 220 && angle <= 300)
|
||||
return TurnInstruction::TurnLeft;
|
||||
}
|
||||
if (angle >= 292 && angle < 336)
|
||||
{
|
||||
if (angle > 300 && angle < 360)
|
||||
return TurnInstruction::TurnSharpLeft;
|
||||
}
|
||||
return TurnInstruction::UTurn;
|
||||
}
|
||||
|
||||
@@ -75,6 +131,51 @@ inline bool isTurnNecessary(const TurnInstruction turn_instruction)
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user