enter and exit roundabout feature - currently not showing turn
This commit is contained in:
parent
daf2bbf991
commit
d8af074ff6
@ -152,7 +152,6 @@ class RouteAPI : public BaseAPI
|
|||||||
leg_geometry.locations.begin() + step.geometry_end));
|
leg_geometry.locations.begin() + step.geometry_end));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return json::makeRoute(route,
|
return json::makeRoute(route,
|
||||||
json::makeRouteLegs(std::move(legs), std::move(step_geometries)),
|
json::makeRouteLegs(std::move(legs), std::move(step_geometries)),
|
||||||
std::move(json_overview));
|
std::move(json_overview));
|
||||||
|
@ -171,13 +171,17 @@ inline bool entersRoundabout(const TurnInstruction instruction)
|
|||||||
return (instruction.type == TurnType::EnterRoundabout ||
|
return (instruction.type == TurnType::EnterRoundabout ||
|
||||||
instruction.type == TurnType::EnterRotary ||
|
instruction.type == TurnType::EnterRotary ||
|
||||||
instruction.type == TurnType::EnterRoundaboutAtExit ||
|
instruction.type == TurnType::EnterRoundaboutAtExit ||
|
||||||
instruction.type == TurnType::EnterRotaryAtExit);
|
instruction.type == TurnType::EnterRotaryAtExit ||
|
||||||
|
instruction.type == TurnType::EnterAndExitRoundabout ||
|
||||||
|
instruction.type == TurnType::EnterAndExitRotary);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool leavesRoundabout(const TurnInstruction instruction)
|
inline bool leavesRoundabout(const TurnInstruction instruction)
|
||||||
{
|
{
|
||||||
return (instruction.type == TurnType::ExitRoundabout ||
|
return (instruction.type == TurnType::ExitRoundabout ||
|
||||||
instruction.type == TurnType::ExitRotary);
|
instruction.type == TurnType::ExitRotary ||
|
||||||
|
instruction.type == TurnType::EnterAndExitRoundabout ||
|
||||||
|
instruction.type == TurnType::EnterAndExitRotary);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool staysOnRoundabout(const TurnInstruction instruction)
|
inline bool staysOnRoundabout(const TurnInstruction instruction)
|
||||||
@ -384,7 +388,7 @@ inline DirectionModifier bearingToDirectionModifier(const std::string &bearing)
|
|||||||
|
|
||||||
inline DirectionModifier bearingToDirectionModifier(const double angle)
|
inline DirectionModifier bearingToDirectionModifier(const double angle)
|
||||||
{
|
{
|
||||||
return bearingToDirectionModifier( util::bearing::get(angle) );
|
return bearingToDirectionModifier(util::bearing::get(angle));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isHighway(FunctionalRoadClass road_class)
|
inline bool isHighway(FunctionalRoadClass road_class)
|
||||||
|
@ -1,243 +0,0 @@
|
|||||||
#ifndef OSRM_GUIDANCE_INSTRUCTION_SYMBOLS_HPP
|
|
||||||
#define OSRM_GUIDANCE_INSTRUCTION_SYMBOLS_HPP
|
|
||||||
|
|
||||||
#include "guidance/turn_instruction.hpp"
|
|
||||||
#include "guidance/guidance_toolkit.hpp"
|
|
||||||
|
|
||||||
#include "util/simple_logger.hpp"
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
namespace guidance
|
|
||||||
{
|
|
||||||
|
|
||||||
enum class InstructionSymbol : 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
|
|
||||||
};
|
|
||||||
|
|
||||||
inline InstructionSymbol directTranslation(const DirectionModifier direction_modifier)
|
|
||||||
{
|
|
||||||
const constexpr InstructionSymbol translation[] = {
|
|
||||||
InstructionSymbol::UTurn, InstructionSymbol::TurnSharpRight,
|
|
||||||
InstructionSymbol::TurnRight, InstructionSymbol::TurnSlightRight,
|
|
||||||
InstructionSymbol::GoStraight, InstructionSymbol::TurnSlightLeft,
|
|
||||||
InstructionSymbol::TurnLeft, InstructionSymbol::TurnSharpLeft};
|
|
||||||
return translation[direction_modifier];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool canTranslateDirectly(const TurnType type)
|
|
||||||
{
|
|
||||||
return type == TurnType::Continue // remain on a street
|
|
||||||
|| type == TurnType::NewName // no turn, but name changes
|
|
||||||
|| type == TurnType::Turn // basic turn
|
|
||||||
|| type == TurnType::Ramp // special turn (highway ramp exits)
|
|
||||||
|| type == TurnType::Fork // fork road splitting up
|
|
||||||
|| type == TurnType::EndOfRoad || type == TurnType::Restriction ||
|
|
||||||
type == TurnType::Merge || type == TurnType::Notification;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline InstructionSymbol getSymbol(const TurnInstruction instruction)
|
|
||||||
{
|
|
||||||
if (canTranslateDirectly(instruction.type))
|
|
||||||
{
|
|
||||||
return directTranslation(instruction.direction_modifier);
|
|
||||||
}
|
|
||||||
else if (instruction.type == TurnType::EnterRoundabout ||
|
|
||||||
instruction.type == TurnType::EnterRotary)
|
|
||||||
{
|
|
||||||
return InstructionSymbol::EnterRoundAbout;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
util::SimpleLogger().Write(logDEBUG)
|
|
||||||
<< "Unreasonable request for symbol: "
|
|
||||||
<< std::to_string(static_cast<int>(instruction.type)) << " "
|
|
||||||
<< std::to_string(static_cast<int>(instruction.direction_modifier));
|
|
||||||
return InstructionSymbol::NoTurn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline InstructionSymbol getLocationSymbol(const LocationType type)
|
|
||||||
{
|
|
||||||
if (type == LocationType::Start)
|
|
||||||
return InstructionSymbol::HeadOn;
|
|
||||||
if (type == LocationType::Intermediate)
|
|
||||||
return InstructionSymbol::ReachViaLocation;
|
|
||||||
if (type == LocationType::Destination)
|
|
||||||
return InstructionSymbol::ReachedYourDestination;
|
|
||||||
return InstructionSymbol::NoTurn;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// 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
|
|
||||||
|
|
||||||
} // namespace guidance
|
|
||||||
} // namespace engine
|
|
||||||
} // namespace osrm
|
|
||||||
|
|
||||||
#endif /* OSRM_GUIDANCE_INSTRUCTION_SYMBOLS_HPP */
|
|
@ -60,9 +60,11 @@ enum TurnType // at the moment we can support 32 turn types, without increasing
|
|||||||
EndOfRoad, // T intersection
|
EndOfRoad, // T intersection
|
||||||
EnterRoundabout, // Entering a small Roundabout
|
EnterRoundabout, // Entering a small Roundabout
|
||||||
EnterRoundaboutAtExit, // Entering a small Roundabout at a countable exit
|
EnterRoundaboutAtExit, // Entering a small Roundabout at a countable exit
|
||||||
|
EnterAndExitRoundabout, // Touching a roundabout
|
||||||
ExitRoundabout, // Exiting a small Roundabout
|
ExitRoundabout, // Exiting a small Roundabout
|
||||||
EnterRotary, // Enter a rotary
|
EnterRotary, // Enter a rotary
|
||||||
EnterRotaryAtExit, // Enter A Rotary at a countable exit
|
EnterRotaryAtExit, // Enter A Rotary at a countable exit
|
||||||
|
EnterAndExitRotary, // Touching a rotary
|
||||||
ExitRotary, // Exit a rotary
|
ExitRotary, // Exit a rotary
|
||||||
StayOnRoundabout, // Continue on Either a small or a large Roundabout
|
StayOnRoundabout, // Continue on Either a small or a large Roundabout
|
||||||
Restriction, // Cross a Barrier, requires barrier penalties instead of full block
|
Restriction, // Cross a Barrier, requires barrier penalties instead of full block
|
||||||
@ -82,7 +84,7 @@ inline bool isValidModifier( const TurnType type, const DirectionModifier modifi
|
|||||||
const constexpr char *turn_type_names[] = {"invalid",
|
const constexpr char *turn_type_names[] = {"invalid",
|
||||||
"no turn",
|
"no turn",
|
||||||
"waypoint",
|
"waypoint",
|
||||||
"passing intersection",
|
"invalid",
|
||||||
"new name",
|
"new name",
|
||||||
"continue",
|
"continue",
|
||||||
"turn",
|
"turn",
|
||||||
@ -91,10 +93,12 @@ const constexpr char *turn_type_names[] = {"invalid",
|
|||||||
"fork",
|
"fork",
|
||||||
"end of road",
|
"end of road",
|
||||||
"roundabout",
|
"roundabout",
|
||||||
"invalid"
|
"invalid",
|
||||||
|
"roundabout",
|
||||||
"invalid",
|
"invalid",
|
||||||
"traffic circle",
|
"traffic circle",
|
||||||
"invalid",
|
"invalid",
|
||||||
|
"traffic circle",
|
||||||
"invalid",
|
"invalid",
|
||||||
"invalid",
|
"invalid",
|
||||||
"restriction",
|
"restriction",
|
||||||
|
@ -267,6 +267,7 @@ class BasePlugin
|
|||||||
// we didn't found a fitting node, return error
|
// we didn't found a fitting node, return error
|
||||||
if (!phantom_node_pairs[i].first.IsValid(facade.GetNumberOfNodes()))
|
if (!phantom_node_pairs[i].first.IsValid(facade.GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
|
//TODO document why?
|
||||||
phantom_node_pairs.pop_back();
|
phantom_node_pairs.pop_back();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ struct TurnCandidate
|
|||||||
namespace turn_analysis
|
namespace turn_analysis
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// the entry into the turn analysis
|
||||||
std::vector<TurnCandidate>
|
std::vector<TurnCandidate>
|
||||||
getTurns(const NodeID from_node,
|
getTurns(const NodeID from_node,
|
||||||
const EdgeID via_eid,
|
const EdgeID via_eid,
|
||||||
@ -50,6 +51,34 @@ getTurns(const NodeID from_node,
|
|||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const CompressedEdgeContainer &compressed_edge_container);
|
const CompressedEdgeContainer &compressed_edge_container);
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// Check for restrictions/barriers and generate a list of valid and invalid turns present at the
|
||||||
|
// node reached
|
||||||
|
// from `from_node` via `via_eid`
|
||||||
|
std::vector<TurnCandidate>
|
||||||
|
getTurnCandidates(const NodeID from_node,
|
||||||
|
const EdgeID via_eid,
|
||||||
|
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph,
|
||||||
|
const std::vector<QueryNode> &node_info_list,
|
||||||
|
const std::shared_ptr<RestrictionMap const> restriction_map,
|
||||||
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
|
const CompressedEdgeContainer &compressed_edge_container);
|
||||||
|
|
||||||
|
// handle roundabouts
|
||||||
|
// TODO distinguish roundabouts and rotaries
|
||||||
|
std::vector<TurnCandidate>
|
||||||
|
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::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
|
||||||
|
|
||||||
|
// handle intersections
|
||||||
|
|
||||||
std::vector<TurnCandidate>
|
std::vector<TurnCandidate>
|
||||||
setTurnTypes(const NodeID from,
|
setTurnTypes(const NodeID from,
|
||||||
const EdgeID via_edge,
|
const EdgeID via_edge,
|
||||||
@ -84,15 +113,6 @@ suppressTurns(const EdgeID via_eid,
|
|||||||
std::vector<TurnCandidate> turn_candidates,
|
std::vector<TurnCandidate> turn_candidates,
|
||||||
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
|
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
|
||||||
|
|
||||||
std::vector<TurnCandidate>
|
|
||||||
getTurnCandidates(const NodeID from_node,
|
|
||||||
const EdgeID via_eid,
|
|
||||||
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph,
|
|
||||||
const std::vector<QueryNode> &node_info_list,
|
|
||||||
const std::shared_ptr<RestrictionMap const> restriction_map,
|
|
||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
|
||||||
const CompressedEdgeContainer &compressed_edge_container);
|
|
||||||
|
|
||||||
// node_u -- (edge_1) --> node_v -- (edge_2) --> node_w
|
// node_u -- (edge_1) --> node_v -- (edge_2) --> node_w
|
||||||
engine::guidance::TurnInstruction
|
engine::guidance::TurnInstruction
|
||||||
AnalyzeTurn(const NodeID node_u,
|
AnalyzeTurn(const NodeID node_u,
|
||||||
@ -102,6 +122,7 @@ AnalyzeTurn(const NodeID node_u,
|
|||||||
const NodeID node_w,
|
const NodeID node_w,
|
||||||
const double angle,
|
const double angle,
|
||||||
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
|
const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph);
|
||||||
|
} // namespace detail
|
||||||
} // namespace turn_analysis
|
} // namespace turn_analysis
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -3,11 +3,8 @@
|
|||||||
|
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace util
|
namespace util
|
||||||
|
@ -85,7 +85,7 @@ std::string modeToString(const extractor::TravelMode mode)
|
|||||||
token = "river downstream";
|
token = "river downstream";
|
||||||
break;
|
break;
|
||||||
case TRAVEL_MODE_ROUTE:
|
case TRAVEL_MODE_ROUTE:
|
||||||
token = "rout";
|
token = "route";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
token = "other";
|
token = "other";
|
||||||
@ -106,7 +106,7 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
|
|||||||
step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location);
|
step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location);
|
||||||
step_maneuver.values["bearing_before"] = maneuver.bearing_before;
|
step_maneuver.values["bearing_before"] = maneuver.bearing_before;
|
||||||
step_maneuver.values["bearing_after"] = maneuver.bearing_after;
|
step_maneuver.values["bearing_after"] = maneuver.bearing_after;
|
||||||
if( maneuver.exit != 0 )
|
if (maneuver.exit != 0)
|
||||||
step_maneuver.values["exit"] = maneuver.exit;
|
step_maneuver.values["exit"] = maneuver.exit;
|
||||||
return step_maneuver;
|
return step_maneuver;
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ util::json::Array makeRouteLegs(std::vector<guidance::RouteLeg> legs,
|
|||||||
|
|
||||||
return json_legs;
|
return json_legs;
|
||||||
}
|
}
|
||||||
}
|
} // namespace json
|
||||||
}
|
} // namespace api
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -84,7 +84,7 @@ void print(const std::vector<std::vector<PathData>> &leg_data)
|
|||||||
|
|
||||||
std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> leg_data)
|
std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> leg_data)
|
||||||
{
|
{
|
||||||
if( leg_data.empty() )
|
if (leg_data.empty())
|
||||||
return leg_data;
|
return leg_data;
|
||||||
|
|
||||||
#define PRINT_DEBUG 0
|
#define PRINT_DEBUG 0
|
||||||
@ -98,12 +98,12 @@ std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>
|
|||||||
bool on_roundabout = false;
|
bool on_roundabout = false;
|
||||||
for (auto &path_data : leg_data)
|
for (auto &path_data : leg_data)
|
||||||
{
|
{
|
||||||
if( not path_data.empty() )
|
if (not path_data.empty())
|
||||||
path_data[0].exit = carry_exit;
|
path_data[0].exit = carry_exit;
|
||||||
|
|
||||||
for (std::size_t data_index = 0; data_index + 1 < path_data.size(); ++data_index)
|
for (std::size_t data_index = 0; data_index + 1 < path_data.size(); ++data_index)
|
||||||
{
|
{
|
||||||
if (entersRoundabout(path_data[data_index].turn_instruction) )
|
if (entersRoundabout(path_data[data_index].turn_instruction))
|
||||||
{
|
{
|
||||||
path_data[data_index].exit += 1;
|
path_data[data_index].exit += 1;
|
||||||
on_roundabout = true;
|
on_roundabout = true;
|
||||||
@ -118,7 +118,7 @@ std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>
|
|||||||
{
|
{
|
||||||
if (!on_roundabout)
|
if (!on_roundabout)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(leg_data[0][0].turn_instruction.type == TurnType::NO_TURN() );
|
BOOST_ASSERT(leg_data[0][0].turn_instruction.type == TurnType::NO_TURN());
|
||||||
if (path_data[data_index].turn_instruction.type == ExitRoundabout)
|
if (path_data[data_index].turn_instruction.type == ExitRoundabout)
|
||||||
leg_data[0][0].turn_instruction.type = TurnType::EnterRoundabout;
|
leg_data[0][0].turn_instruction.type = TurnType::EnterRoundabout;
|
||||||
if (path_data[data_index].turn_instruction.type == ExitRotary)
|
if (path_data[data_index].turn_instruction.type == ExitRotary)
|
||||||
@ -160,15 +160,16 @@ std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>
|
|||||||
{
|
{
|
||||||
if (entersRoundabout(path_data[data_index - 1].turn_instruction))
|
if (entersRoundabout(path_data[data_index - 1].turn_instruction))
|
||||||
{
|
{
|
||||||
if( !on_roundabout )
|
if (!on_roundabout && !leavesRoundabout(path_data[data_index - 1].turn_instruction))
|
||||||
path_data[data_index-1].exit = 0;
|
path_data[data_index - 1].exit = 0;
|
||||||
on_roundabout = false;
|
on_roundabout = false;
|
||||||
}
|
}
|
||||||
if (on_roundabout)
|
if (on_roundabout)
|
||||||
{
|
{
|
||||||
path_data[data_index - 2].exit = path_data[data_index - 1].exit;
|
path_data[data_index - 2].exit = path_data[data_index - 1].exit;
|
||||||
}
|
}
|
||||||
if (leavesRoundabout(path_data[data_index - 1].turn_instruction))
|
if (leavesRoundabout(path_data[data_index - 1].turn_instruction) &&
|
||||||
|
!entersRoundabout(path_data[data_index - 1].turn_instruction))
|
||||||
{
|
{
|
||||||
path_data[data_index - 2].exit = path_data[data_index - 1].exit;
|
path_data[data_index - 2].exit = path_data[data_index - 1].exit;
|
||||||
on_roundabout = true;
|
on_roundabout = true;
|
||||||
@ -191,7 +192,8 @@ std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>
|
|||||||
{
|
{
|
||||||
for (auto &data : path_data)
|
for (auto &data : path_data)
|
||||||
{
|
{
|
||||||
if (isSilent(data.turn_instruction) || leavesRoundabout(data.turn_instruction))
|
if (isSilent(data.turn_instruction) || (leavesRoundabout(data.turn_instruction) &&
|
||||||
|
!entersRoundabout(data.turn_instruction)))
|
||||||
{
|
{
|
||||||
data.turn_instruction = TurnInstruction::NO_TURN();
|
data.turn_instruction = TurnInstruction::NO_TURN();
|
||||||
data.exit = 0;
|
data.exit = 0;
|
||||||
|
@ -43,6 +43,7 @@ using engine::guidance::isSlightTurn;
|
|||||||
using engine::guidance::isSlightModifier;
|
using engine::guidance::isSlightModifier;
|
||||||
using engine::guidance::mirrorDirectionModifier;
|
using engine::guidance::mirrorDirectionModifier;
|
||||||
|
|
||||||
|
#define PRINT_DEBUG_CANDIDATES 0
|
||||||
std::vector<TurnCandidate>
|
std::vector<TurnCandidate>
|
||||||
getTurns(const NodeID from,
|
getTurns(const NodeID from,
|
||||||
const EdgeID via_edge,
|
const EdgeID via_edge,
|
||||||
@ -52,12 +53,36 @@ getTurns(const NodeID from,
|
|||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const CompressedEdgeContainer &compressed_edge_container)
|
const CompressedEdgeContainer &compressed_edge_container)
|
||||||
{
|
{
|
||||||
auto turn_candidates = turn_analysis::getTurnCandidates(
|
auto turn_candidates =
|
||||||
from, via_edge, node_based_graph, node_info_list, restriction_map, barrier_nodes,
|
detail::getTurnCandidates(from, via_edge, node_based_graph, node_info_list, restriction_map,
|
||||||
compressed_edge_container);
|
barrier_nodes, compressed_edge_container);
|
||||||
|
|
||||||
|
// main priority: roundabouts
|
||||||
|
const auto &in_edge_data = node_based_graph->GetEdgeData(via_edge);
|
||||||
|
bool on_roundabout = in_edge_data.roundabout;
|
||||||
|
bool can_enter_roundabout = false;
|
||||||
|
bool can_exit_roundabout = false;
|
||||||
|
for (const auto &candidate : turn_candidates)
|
||||||
|
{
|
||||||
|
if (node_based_graph->GetEdgeData(candidate.eid).roundabout)
|
||||||
|
{
|
||||||
|
can_enter_roundabout = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
can_exit_roundabout = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (on_roundabout || can_enter_roundabout)
|
||||||
|
{
|
||||||
|
return detail::handleRoundabouts(from, via_edge, on_roundabout, can_enter_roundabout,
|
||||||
|
can_exit_roundabout, std::move(turn_candidates),
|
||||||
|
node_based_graph);
|
||||||
|
}
|
||||||
|
|
||||||
turn_candidates =
|
turn_candidates =
|
||||||
turn_analysis::setTurnTypes(from, via_edge, std::move(turn_candidates), node_based_graph);
|
detail::setTurnTypes(from, via_edge, std::move(turn_candidates), node_based_graph);
|
||||||
#define PRINT_DEBUG_CANDIDATES 0
|
|
||||||
#if PRINT_DEBUG_CANDIDATES
|
#if PRINT_DEBUG_CANDIDATES
|
||||||
std::cout << "Initial Candidates:\n";
|
std::cout << "Initial Candidates:\n";
|
||||||
for (auto tc : turn_candidates)
|
for (auto tc : turn_candidates)
|
||||||
@ -65,7 +90,7 @@ getTurns(const NodeID from,
|
|||||||
<< (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class
|
<< (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
turn_candidates = turn_analysis::optimizeCandidates(via_edge, std::move(turn_candidates),
|
turn_candidates = detail::optimizeCandidates(via_edge, std::move(turn_candidates),
|
||||||
node_based_graph, node_info_list);
|
node_based_graph, node_info_list);
|
||||||
#if PRINT_DEBUG_CANDIDATES
|
#if PRINT_DEBUG_CANDIDATES
|
||||||
std::cout << "Optimized Candidates:\n";
|
std::cout << "Optimized Candidates:\n";
|
||||||
@ -74,8 +99,7 @@ getTurns(const NodeID from,
|
|||||||
<< (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class
|
<< (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
turn_candidates =
|
turn_candidates = detail::suppressTurns(via_edge, std::move(turn_candidates), node_based_graph);
|
||||||
turn_analysis::suppressTurns(via_edge, std::move(turn_candidates), node_based_graph);
|
|
||||||
#if PRINT_DEBUG_CANDIDATES
|
#if PRINT_DEBUG_CANDIDATES
|
||||||
std::cout << "Suppressed Candidates:\n";
|
std::cout << "Suppressed Candidates:\n";
|
||||||
for (auto tc : turn_candidates)
|
for (auto tc : turn_candidates)
|
||||||
@ -86,6 +110,93 @@ getTurns(const NodeID from,
|
|||||||
return turn_candidates;
|
return turn_candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<TurnCandidate>
|
||||||
|
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::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph)
|
||||||
|
{
|
||||||
|
(void)from;
|
||||||
|
// TODO requires differentiation between roundabouts and rotaries
|
||||||
|
NodeID node_v = node_based_graph->GetTarget(via_edge);
|
||||||
|
if (on_roundabout)
|
||||||
|
{
|
||||||
|
// Shoule hopefully have only a single exit and continue
|
||||||
|
// at least for cars. How about bikes?
|
||||||
|
for (auto &candidate : turn_candidates)
|
||||||
|
{
|
||||||
|
const auto &out_data = node_based_graph->GetEdgeData(candidate.eid);
|
||||||
|
if (out_data.roundabout)
|
||||||
|
{
|
||||||
|
// TODO can forks happen in roundabouts? E.g. required lane changes
|
||||||
|
if (1 == node_based_graph->GetDirectedOutDegree(node_v))
|
||||||
|
{
|
||||||
|
// No turn possible.
|
||||||
|
candidate.instruction = TurnInstruction::NO_TURN();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
candidate.instruction =
|
||||||
|
TurnInstruction::REMAIN_ROUNDABOUT(getTurnDirection(candidate.angle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
candidate.instruction =
|
||||||
|
TurnInstruction::EXIT_ROUNDABOUT(getTurnDirection(candidate.angle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if PRINT_DEBUG_CANDIDATES
|
||||||
|
std::cout << "On Roundabout Candidates:\n";
|
||||||
|
for (auto tc : turn_candidates)
|
||||||
|
std::cout << "\t" << tc.toString() << " "
|
||||||
|
<< (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class
|
||||||
|
<< std::endl;
|
||||||
|
#endif
|
||||||
|
return turn_candidates;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void)can_enter_roundabout;
|
||||||
|
BOOST_ASSERT(can_enter_roundabout);
|
||||||
|
for (auto &candidate : turn_candidates)
|
||||||
|
{
|
||||||
|
const auto &out_data = node_based_graph->GetEdgeData(candidate.eid);
|
||||||
|
if (out_data.roundabout)
|
||||||
|
{
|
||||||
|
candidate.instruction =
|
||||||
|
TurnInstruction::ENTER_ROUNDABOUT(getTurnDirection(candidate.angle));
|
||||||
|
if (can_exit_roundabout)
|
||||||
|
{
|
||||||
|
if (candidate.instruction.type == TurnType::EnterRotary)
|
||||||
|
candidate.instruction.type = TurnType::EnterRotaryAtExit;
|
||||||
|
if (candidate.instruction.type == TurnType::EnterRoundabout)
|
||||||
|
candidate.instruction.type = TurnType::EnterRoundaboutAtExit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
candidate.instruction = {TurnType::EnterAndExitRoundabout,
|
||||||
|
getTurnDirection(candidate.angle)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if PRINT_DEBUG_CANDIDATES
|
||||||
|
std::cout << "Into Roundabout Candidates:\n";
|
||||||
|
for (auto tc : turn_candidates)
|
||||||
|
std::cout << "\t" << tc.toString() << " "
|
||||||
|
<< (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class
|
||||||
|
<< std::endl;
|
||||||
|
#endif
|
||||||
|
return turn_candidates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<TurnCandidate>
|
std::vector<TurnCandidate>
|
||||||
setTurnTypes(const NodeID from,
|
setTurnTypes(const NodeID from,
|
||||||
const EdgeID via_edge,
|
const EdgeID via_edge,
|
||||||
@ -839,6 +950,7 @@ AnalyzeTurn(const NodeID node_u,
|
|||||||
return {TurnType::Turn, getTurnDirection(angle)};
|
return {TurnType::Turn, getTurnDirection(angle)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // anemspace detail
|
||||||
} // namespace turn_analysis
|
} // namespace turn_analysis
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // nameNspace osrm
|
||||||
|
Loading…
Reference in New Issue
Block a user