modify turn angles and instructions

This commit is contained in:
Moritz Kobitzsch
2016-01-29 12:42:08 +01:00
parent ab9426e260
commit f14352f494
18 changed files with 936 additions and 230 deletions
+62 -5
View File
@@ -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_ */
+2 -2
View File
@@ -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()
{
+122 -21
View File
@@ -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));
}
}
}