bugfixing/classification

This commit is contained in:
Moritz Kobitzsch 2016-03-03 15:36:03 +01:00 committed by Patrick Niklaus
parent b08b360f38
commit 58628a4bfc
17 changed files with 214 additions and 121 deletions

View File

@ -76,7 +76,8 @@ class BaseDataFacade
virtual void GetUncompressedWeights(const EdgeID id, virtual void GetUncompressedWeights(const EdgeID id,
std::vector<EdgeWeight> &result_weights) const = 0; std::vector<EdgeWeight> &result_weights) const = 0;
virtual extractor::guidance::TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const = 0; virtual extractor::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const unsigned id) const = 0;
virtual extractor::TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0; virtual extractor::TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0;

View File

@ -329,7 +329,8 @@ class InternalDataFacade final : public BaseDataFacade
return m_coordinate_list->at(id); return m_coordinate_list->at(id);
} }
extractor::guidance::TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final extractor::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const unsigned id) const override final
{ {
return m_turn_instruction_list.at(id); return m_turn_instruction_list.at(id);
} }

View File

@ -147,11 +147,13 @@ class SharedDataFacade final : public BaseDataFacade
travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]); travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]);
m_travel_mode_list = std::move(travel_mode_list); m_travel_mode_list = std::move(travel_mode_list);
auto turn_instruction_list_ptr = data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>( auto turn_instruction_list_ptr =
shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION); data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>(
typename util::ShM<extractor::guidance::TurnInstruction, true>::vector turn_instruction_list( shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION);
turn_instruction_list_ptr, typename util::ShM<extractor::guidance::TurnInstruction, true>::vector
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]); turn_instruction_list(
turn_instruction_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]);
m_turn_instruction_list = std::move(turn_instruction_list); m_turn_instruction_list = std::move(turn_instruction_list);
auto name_id_list_ptr = data_layout->GetBlockPtr<unsigned>( auto name_id_list_ptr = data_layout->GetBlockPtr<unsigned>(
@ -237,8 +239,7 @@ class SharedDataFacade final : public BaseDataFacade
} }
data_timestamp_ptr = static_cast<storage::SharedDataTimestamp *>( data_timestamp_ptr = static_cast<storage::SharedDataTimestamp *>(
storage::makeSharedMemory(storage::CURRENT_REGIONS, storage::makeSharedMemory(storage::CURRENT_REGIONS,
sizeof(storage::SharedDataTimestamp), false, false) sizeof(storage::SharedDataTimestamp), false, false)->Ptr());
->Ptr());
CURRENT_LAYOUT = storage::LAYOUT_NONE; CURRENT_LAYOUT = storage::LAYOUT_NONE;
CURRENT_DATA = storage::DATA_NONE; CURRENT_DATA = storage::DATA_NONE;
CURRENT_TIMESTAMP = 0; CURRENT_TIMESTAMP = 0;
@ -309,8 +310,8 @@ class SharedDataFacade final : public BaseDataFacade
LoadNames(); LoadNames();
LoadCoreInformation(); LoadCoreInformation();
util::SimpleLogger().Write() << "number of geometries: " util::SimpleLogger().Write()
<< m_coordinate_list->size(); << "number of geometries: " << m_coordinate_list->size();
for (unsigned i = 0; i < m_coordinate_list->size(); ++i) for (unsigned i = 0; i < m_coordinate_list->size(); ++i)
{ {
if (!GetCoordinateOfNode(i).IsValid()) if (!GetCoordinateOfNode(i).IsValid())
@ -400,7 +401,8 @@ class SharedDataFacade final : public BaseDataFacade
return m_via_node_list.at(id); return m_via_node_list.at(id);
} }
extractor::guidance::TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final extractor::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const unsigned id) const override final
{ {
return m_turn_instruction_list.at(id); return m_turn_instruction_list.at(id);
} }

View File

@ -5,6 +5,7 @@
#include "engine/phantom_node.hpp" #include "engine/phantom_node.hpp"
#include "engine/guidance/route_step.hpp" #include "engine/guidance/route_step.hpp"
#include "engine/guidance/leg_geometry.hpp" #include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/toolkit.hpp"
#include "util/coordinate_calculation.hpp" #include "util/coordinate_calculation.hpp"
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include "extractor/guidance/turn_instruction.hpp" #include "extractor/guidance/turn_instruction.hpp"
@ -49,7 +50,7 @@ LegGeometry assembleGeometry(const DataFacadeT &facade,
current_distance += current_distance +=
util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate); util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate);
if (path_point.turn_instruction != extractor::guidance::TurnInstruction::NO_TURN()) if (!isSilent(path_point.turn_instruction))
{ {
geometry.segment_distances.push_back(current_distance); geometry.segment_distances.push_back(current_distance);
geometry.segment_offsets.push_back(geometry.locations.size()); geometry.segment_offsets.push_back(geometry.locations.size());

View File

@ -134,7 +134,7 @@ RouteLeg assembleLeg(const DataFacadeT &facade,
// `forward_weight`: duration of (d,t) // `forward_weight`: duration of (d,t)
// `forward_offset`: duration of (c, d) // `forward_offset`: duration of (c, d)
// //
// The PathData will contain entries of b, c and d. But only c will contain //TODO discuss, this should not be the case after danpats fixes // The PathData will contain entries of b, c and d. But only c will contain
// a duration value since its the only point associated with a turn. // a duration value since its the only point associated with a turn.
// As such we want to slice of the duration for (a,s) and add the duration for // As such we want to slice of the duration for (a,s) and add the duration for
// (c,d,t) // (c,d,t)

View File

@ -104,18 +104,26 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
{ {
const auto name = facade.get_name_for_id(path_point.name_id); const auto name = facade.get_name_for_id(path_point.name_id);
const auto distance = leg_geometry.segment_distances[segment_index]; const auto distance = leg_geometry.segment_distances[segment_index];
steps.push_back(RouteStep{ steps.push_back(RouteStep{path_point.name_id,
path_point.name_id, name, path_point.duration_until_turn / 10.0, distance, name,
path_point.travel_mode, maneuver, leg_geometry.FrontIndex(segment_index), path_point.duration_until_turn / 10.0,
leg_geometry.BackIndex(segment_index) + 1}); distance,
path_point.travel_mode,
maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1});
maneuver = detail::stepManeuverFromGeometry( maneuver = detail::stepManeuverFromGeometry(
path_point.turn_instruction, leg_geometry, segment_index, path_point.exit); path_point.turn_instruction, leg_geometry, segment_index, path_point.exit);
segment_index++; segment_index++;
} }
} }
const auto distance = leg_geometry.segment_distances[segment_index]; const auto distance = leg_geometry.segment_distances[segment_index];
steps.push_back(RouteStep{target_node.name_id, facade.get_name_for_id(target_node.name_id), steps.push_back(RouteStep{target_node.name_id,
target_duration, distance, target_mode, maneuver, facade.get_name_for_id(target_node.name_id),
target_duration,
distance,
target_mode,
maneuver,
leg_geometry.FrontIndex(segment_index), leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1}); leg_geometry.BackIndex(segment_index) + 1});
} }
@ -126,15 +134,20 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
// |-------------t target_duration // |-------------t target_duration
// x---*---*---*---z compressed edge // x---*---*---*---z compressed edge
// |-------| duration // |-------| duration
StepManeuver maneuver = {source_node.location, 0., 0., StepManeuver maneuver = {source_node.location,
0.,
0.,
extractor::guidance::TurnInstruction{ extractor::guidance::TurnInstruction{
extractor::guidance::TurnType::Location, initial_modifier}, extractor::guidance::TurnType::Location, initial_modifier},
INVALID_EXIT_NR}; INVALID_EXIT_NR};
steps.push_back(RouteStep{source_node.name_id, facade.get_name_for_id(source_node.name_id), steps.push_back(RouteStep{source_node.name_id,
facade.get_name_for_id(source_node.name_id),
target_duration - source_duration, target_duration - source_duration,
leg_geometry.segment_distances[segment_index], source_mode, leg_geometry.segment_distances[segment_index],
std::move(maneuver), leg_geometry.FrontIndex(segment_index), source_mode,
std::move(maneuver),
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1}); leg_geometry.BackIndex(segment_index) + 1});
} }
@ -146,13 +159,20 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
target_location.get())) target_location.get()))
: extractor::guidance::DirectionModifier::UTurn; : extractor::guidance::DirectionModifier::UTurn;
// This step has length zero, the only reason we need it is the target location // This step has length zero, the only reason we need it is the target location
steps.push_back(RouteStep{ steps.push_back(
target_node.name_id, facade.get_name_for_id(target_node.name_id), 0., 0., target_mode, RouteStep{target_node.name_id,
StepManeuver{target_node.location, 0., 0., facade.get_name_for_id(target_node.name_id),
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::Location, 0.,
final_modifier}, 0.,
INVALID_EXIT_NR}, target_mode,
leg_geometry.locations.size(), leg_geometry.locations.size()}); StepManeuver{target_node.location,
0.,
0.,
extractor::guidance::TurnInstruction{
extractor::guidance::TurnType::Location, final_modifier},
INVALID_EXIT_NR},
leg_geometry.locations.size(),
leg_geometry.locations.size()});
return steps; return steps;
} }

View File

@ -14,7 +14,8 @@ namespace guidance
// Silent Turn Instructions are not to be mentioned to the outside world but // Silent Turn Instructions are not to be mentioned to the outside world but
inline bool isSilent(const extractor::guidance::TurnInstruction instruction) inline bool isSilent(const extractor::guidance::TurnInstruction instruction)
{ {
return instruction.type == extractor::guidance::TurnType::NoTurn || instruction.type == extractor::guidance::TurnType::Suppressed || return instruction.type == extractor::guidance::TurnType::NoTurn ||
instruction.type == extractor::guidance::TurnType::Suppressed ||
instruction.type == extractor::guidance::TurnType::StayOnRoundabout; instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
} }

View File

@ -267,7 +267,7 @@ class BasePlugin
// we didn't find a fitting node, return error // we didn't find 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? // TODO document why?
phantom_node_pairs.pop_back(); phantom_node_pairs.pop_back();
break; break;
} }

View File

@ -283,8 +283,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
{ {
BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut"); BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id); unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
const auto turn_instruction = const auto turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id);
facade->GetTurnInstructionForEdgeID(ed.id);
const extractor::TravelMode travel_mode = const extractor::TravelMode travel_mode =
(unpacked_path.empty() && start_traversed_in_reverse) (unpacked_path.empty() && start_traversed_in_reverse)
? phantom_node_pair.source_phantom.backward_travel_mode ? phantom_node_pair.source_phantom.backward_travel_mode
@ -320,9 +319,10 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
BOOST_ASSERT(start_index < end_index); BOOST_ASSERT(start_index < end_index);
for (std::size_t i = start_index; i < end_index; ++i) for (std::size_t i = start_index; i < end_index; ++i)
{ {
unpacked_path.push_back(PathData{id_vector[i], name_index, weight_vector[i], unpacked_path.push_back(
extractor::guidance::TurnInstruction::NO_TURN(), PathData{id_vector[i], name_index, weight_vector[i],
travel_mode, INVALID_EXIT_NR}); extractor::guidance::TurnInstruction::NO_TURN(), travel_mode,
INVALID_EXIT_NR});
} }
BOOST_ASSERT(unpacked_path.size() > 0); BOOST_ASSERT(unpacked_path.size() > 0);
unpacked_path.back().turn_instruction = turn_instruction; unpacked_path.back().turn_instruction = turn_instruction;

View File

@ -41,7 +41,7 @@ enum class FunctionalRoadClass : short
inline FunctionalRoadClass functionalRoadClassFromTag(std::string const &value) inline FunctionalRoadClass functionalRoadClassFromTag(std::string const &value)
{ {
//FIXME at some point this should be part of the profiles // FIXME at some point this should be part of the profiles
const static auto initializeClassHash = []() const static auto initializeClassHash = []()
{ {
std::unordered_map<std::string, FunctionalRoadClass> hash; std::unordered_map<std::string, FunctionalRoadClass> hash;

View File

@ -132,15 +132,13 @@ getRepresentativeCoordinate(const NodeID from_node,
} }
// shift an instruction around the degree circle in CCW order // shift an instruction around the degree circle in CCW order
inline DirectionModifier inline DirectionModifier forcedShiftCCW(const DirectionModifier modifier)
forcedShiftCCW(const DirectionModifier modifier)
{ {
return static_cast<DirectionModifier>( return static_cast<DirectionModifier>((static_cast<uint32_t>(modifier) + 1) %
(static_cast<uint32_t>(modifier) + 1) % detail::num_direction_modifiers); detail::num_direction_modifiers);
} }
inline DirectionModifier inline DirectionModifier shiftCCW(const DirectionModifier modifier)
shiftCCW(const DirectionModifier modifier)
{ {
if (detail::shiftable_ccw[static_cast<int>(modifier)]) if (detail::shiftable_ccw[static_cast<int>(modifier)])
return forcedShiftCCW(modifier); return forcedShiftCCW(modifier);
@ -149,16 +147,14 @@ shiftCCW(const DirectionModifier modifier)
} }
// shift an instruction around the degree circle in CW order // shift an instruction around the degree circle in CW order
inline DirectionModifier inline DirectionModifier forcedShiftCW(const DirectionModifier modifier)
forcedShiftCW(const DirectionModifier modifier)
{ {
return static_cast<DirectionModifier>( return static_cast<DirectionModifier>(
(static_cast<uint32_t>(modifier) + detail::num_direction_modifiers - 1) % (static_cast<uint32_t>(modifier) + detail::num_direction_modifiers - 1) %
detail::num_direction_modifiers); detail::num_direction_modifiers);
} }
inline DirectionModifier inline DirectionModifier shiftCW(const DirectionModifier modifier)
shiftCW(const DirectionModifier modifier)
{ {
if (detail::shiftable_cw[static_cast<int>(modifier)]) if (detail::shiftable_cw[static_cast<int>(modifier)])
return forcedShiftCW(modifier); return forcedShiftCW(modifier);
@ -168,19 +164,15 @@ shiftCW(const DirectionModifier modifier)
inline bool isBasic(const TurnType type) inline bool isBasic(const TurnType type)
{ {
return type == TurnType::Turn || return type == TurnType::Turn || type == TurnType::EndOfRoad;
type == TurnType::EndOfRoad;
} }
inline bool isUturn(const TurnInstruction instruction) inline bool isUturn(const TurnInstruction instruction)
{ {
return isBasic(instruction.type) && return isBasic(instruction.type) && instruction.direction_modifier == DirectionModifier::UTurn;
instruction.direction_modifier == DirectionModifier::UTurn;
} }
inline bool resolve(TurnInstruction &to_resolve, inline bool resolve(TurnInstruction &to_resolve, const TurnInstruction neighbor, bool resolve_cw)
const TurnInstruction neighbor,
bool resolve_cw)
{ {
const auto shifted_turn = resolve_cw ? shiftCW(to_resolve.direction_modifier) const auto shifted_turn = resolve_cw ? shiftCW(to_resolve.direction_modifier)
: shiftCCW(to_resolve.direction_modifier); : shiftCCW(to_resolve.direction_modifier);
@ -223,9 +215,8 @@ inline bool isSlightModifier(const DirectionModifier direction_modifier)
inline bool isSharpTurn(const TurnInstruction turn) inline bool isSharpTurn(const TurnInstruction turn)
{ {
return isBasic(turn.type) && return isBasic(turn.type) && (turn.direction_modifier == DirectionModifier::SharpLeft ||
(turn.direction_modifier == DirectionModifier::SharpLeft || turn.direction_modifier == DirectionModifier::SharpRight);
turn.direction_modifier == DirectionModifier::SharpRight);
} }
inline bool isStraight(const TurnInstruction turn) inline bool isStraight(const TurnInstruction turn)
@ -234,8 +225,7 @@ inline bool isStraight(const TurnInstruction turn)
turn.direction_modifier == DirectionModifier::Straight; turn.direction_modifier == DirectionModifier::Straight;
} }
inline bool isConflict(const TurnInstruction first, inline bool isConflict(const TurnInstruction first, const TurnInstruction second)
const TurnInstruction second)
{ {
return (first.type == second.type && first.direction_modifier == second.direction_modifier) || return (first.type == second.type && first.direction_modifier == second.direction_modifier) ||
(isStraight(first) && isStraight(second)); (isStraight(first) && isStraight(second));
@ -244,8 +234,7 @@ inline bool isConflict(const TurnInstruction first,
inline DiscreteAngle discretizeAngle(const double angle) inline DiscreteAngle discretizeAngle(const double angle)
{ {
BOOST_ASSERT(angle >= 0. && angle <= 360.); BOOST_ASSERT(angle >= 0. && angle <= 360.);
return DiscreteAngle( return DiscreteAngle(static_cast<uint8_t>(angle / detail::discrete_angle_step_size));
static_cast<uint8_t>(angle / detail::discrete_angle_step_size));
} }
inline double angleFromDiscreteAngle(const DiscreteAngle angle) inline double angleFromDiscreteAngle(const DiscreteAngle angle)
@ -269,8 +258,7 @@ inline double getTurnConfidence(const double angle, TurnInstruction instruction)
{ {
// special handling of U-Turns and Roundabout // special handling of U-Turns and Roundabout
if (!isBasic(instruction.type) || if (!isBasic(instruction.type) || instruction.direction_modifier == DirectionModifier::UTurn)
instruction.direction_modifier == DirectionModifier::UTurn)
return 1.0; return 1.0;
const double deviations[] = {0, 45, 50, 35, 10, 35, 50, 45}; const double deviations[] = {0, 45, 50, 35, 10, 35, 50, 45};
@ -304,18 +292,16 @@ inline DirectionModifier getTurnDirection(const double angle)
} }
// swaps left <-> right modifier types // swaps left <-> right modifier types
inline DirectionModifier inline DirectionModifier mirrorDirectionModifier(const DirectionModifier modifier)
mirrorDirectionModifier(const DirectionModifier modifier)
{ {
const constexpr DirectionModifier results[] = { const constexpr DirectionModifier results[] = {DirectionModifier::UTurn,
DirectionModifier::UTurn, DirectionModifier::SharpLeft,
DirectionModifier::SharpLeft, DirectionModifier::Left,
DirectionModifier::Left, DirectionModifier::SlightLeft,
DirectionModifier::SlightLeft, DirectionModifier::Straight,
DirectionModifier::Straight, DirectionModifier::SlightRight,
DirectionModifier::SlightRight, DirectionModifier::Right,
DirectionModifier::Right, DirectionModifier::SharpRight};
DirectionModifier::SharpRight};
return results[modifier]; return results[modifier];
} }

View File

@ -28,8 +28,14 @@ namespace json
namespace detail namespace detail
{ {
const constexpr char *modifier_names[] = {"uturn", "sharp right", "right", "slight right", const constexpr char *modifier_names[] = {"uturn",
"straight", "slight left", "left", "sharp left"}; "sharp right",
"right",
"slight right",
"straight",
"slight left",
"left",
"sharp left"};
// translations of TurnTypes. Not all types are exposed to the outside world. // translations of TurnTypes. Not all types are exposed to the outside world.
// invalid types should never be returned as part of the API // invalid types should never be returned as part of the API
@ -40,12 +46,10 @@ const constexpr char *turn_type_names[] = {
"invalid", "invalid", "restriction", "notification"}; "invalid", "invalid", "restriction", "notification"};
// Check whether to include a modifier in the result of the API // Check whether to include a modifier in the result of the API
inline bool isValidModifier(const TurnType type, inline bool isValidModifier(const TurnType type, const DirectionModifier modifier)
const DirectionModifier modifier)
{ {
if (type == TurnType::Location && modifier != DirectionModifier::Left && if (type == TurnType::Location && modifier != DirectionModifier::Left &&
modifier != DirectionModifier::Straight && modifier != DirectionModifier::Straight && modifier != DirectionModifier::Right)
modifier != DirectionModifier::Right)
return false; return false;
return true; return true;
} }

View File

@ -51,8 +51,7 @@ PathData mergeInto(PathData destination, const PathData &source)
BOOST_ASSERT(canMergeTrivially(destination, source)); BOOST_ASSERT(canMergeTrivially(destination, source));
return detail::forwardInto(destination, source); return detail::forwardInto(destination, source);
} }
if (source.turn_instruction == TurnType::Suppressed && if (source.turn_instruction.type == TurnType::Suppressed)
detail::canMergeTrivially(destination, source))
{ {
return detail::forwardInto(destination, source); return detail::forwardInto(destination, source);
} }

View File

@ -59,8 +59,8 @@ Status ViaRoutePlugin::HandleRequest(const api::RouteParameters &route_parameter
auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs); auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs);
InternalRouteResult raw_route; InternalRouteResult raw_route;
auto build_phantom_pairs = [&raw_route](const PhantomNode &first_node, auto build_phantom_pairs =
const PhantomNode &second_node) [&raw_route](const PhantomNode &first_node, const PhantomNode &second_node)
{ {
raw_route.segment_end_coordinates.push_back(PhantomNodes{first_node, second_node}); raw_route.segment_end_coordinates.push_back(PhantomNodes{first_node, second_node});
}; };

View File

@ -316,9 +316,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
} }
++node_based_edge_counter; ++node_based_edge_counter;
auto turn_candidates = guidance::getTurns( auto turn_candidates =
node_u, edge_from_u, m_node_based_graph, m_node_info_list, m_restriction_map, guidance::getTurns(node_u, edge_from_u, m_node_based_graph, m_node_info_list,
m_barrier_nodes, m_compressed_edge_container); m_restriction_map, m_barrier_nodes, m_compressed_edge_container);
const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u); const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u);

View File

@ -41,7 +41,9 @@ void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node,
external_memory.all_nodes_list.push_back( external_memory.all_nodes_list.push_back(
{util::toFixed(util::FloatLongitude(input_node.location().lon())), {util::toFixed(util::FloatLongitude(input_node.location().lon())),
util::toFixed(util::FloatLatitude(input_node.location().lat())), util::toFixed(util::FloatLatitude(input_node.location().lat())),
OSMNodeID(input_node.id()), result_node.barrier, result_node.traffic_lights}); OSMNodeID(input_node.id()),
result_node.barrier,
result_node.traffic_lights});
} }
void ExtractorCallbacks::ProcessRestriction( void ExtractorCallbacks::ProcessRestriction(
@ -123,8 +125,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
if (forward_weight_data.type == InternalExtractorEdge::WeightType::INVALID && if (forward_weight_data.type == InternalExtractorEdge::WeightType::INVALID &&
backward_weight_data.type == InternalExtractorEdge::WeightType::INVALID) backward_weight_data.type == InternalExtractorEdge::WeightType::INVALID)
{ {
util::SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " util::SimpleLogger().Write(logDEBUG)
<< input_way.id(); << "found way with bogus speed, id: " << input_way.id();
return; return;
} }
@ -185,9 +187,11 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
}); });
external_memory.way_start_end_id_list.push_back( external_memory.way_start_end_id_list.push_back(
{OSMWayID(input_way.id()), OSMNodeID(input_way.nodes().back().ref()), {OSMWayID(input_way.id()),
OSMNodeID(input_way.nodes().back().ref()),
OSMNodeID(input_way.nodes()[input_way.nodes().size() - 2].ref()), OSMNodeID(input_way.nodes()[input_way.nodes().size() - 2].ref()),
OSMNodeID(input_way.nodes()[1].ref()), OSMNodeID(input_way.nodes()[0].ref())}); OSMNodeID(input_way.nodes()[1].ref()),
OSMNodeID(input_way.nodes()[0].ref())});
} }
else else
{ {
@ -219,9 +223,11 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
} }
external_memory.way_start_end_id_list.push_back( external_memory.way_start_end_id_list.push_back(
{OSMWayID(input_way.id()), OSMNodeID(input_way.nodes().back().ref()), {OSMWayID(input_way.id()),
OSMNodeID(input_way.nodes().back().ref()),
OSMNodeID(input_way.nodes()[input_way.nodes().size() - 2].ref()), OSMNodeID(input_way.nodes()[input_way.nodes().size() - 2].ref()),
OSMNodeID(input_way.nodes()[1].ref()), OSMNodeID(input_way.nodes()[0].ref())}); OSMNodeID(input_way.nodes()[1].ref()),
OSMNodeID(input_way.nodes()[0].ref())});
} }
} }
} }

View File

@ -1,6 +1,7 @@
#include "extractor/guidance/turn_analysis.hpp" #include "extractor/guidance/turn_analysis.hpp"
#include "util/simple_logger.hpp" #include "util/simple_logger.hpp"
#include "util/coordinate.hpp"
#include <cstddef> #include <cstddef>
@ -28,6 +29,22 @@ const unsigned constexpr INVALID_NAME_ID = 0;
using EdgeData = util::NodeBasedDynamicGraph::EdgeData; using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
struct Localizer
{
const std::vector<QueryNode> *node_info_list = nullptr;
util::Coordinate operator()(const NodeID nid)
{
if (node_info_list)
{
return {(*node_info_list)[nid].lon, (*node_info_list)[nid].lat};
}
return {};
}
};
static Localizer localizer;
#define PRINT_DEBUG_CANDIDATES 0 #define PRINT_DEBUG_CANDIDATES 0
std::vector<TurnCandidate> std::vector<TurnCandidate>
getTurns(const NodeID from, getTurns(const NodeID from,
@ -38,6 +55,7 @@ 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)
{ {
localizer.node_info_list = &node_info_list;
auto turn_candidates = auto turn_candidates =
detail::getTurnCandidates(from, via_edge, node_based_graph, node_info_list, restriction_map, detail::getTurnCandidates(from, via_edge, node_based_graph, node_info_list, restriction_map,
barrier_nodes, compressed_edge_container); barrier_nodes, compressed_edge_container);
@ -264,20 +282,29 @@ inline std::vector<TurnCandidate> fallbackTurnAssignmentMotorway(
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)
{ {
util::SimpleLogger().Write(logWARNING) << "Fallback turn assignment";
for (auto &candidate : turn_candidates) for (auto &candidate : turn_candidates)
{ {
const auto &out_data = node_based_graph->GetEdgeData(candidate.eid);
util::SimpleLogger().Write(logWARNING)
<< "Candidate: " << candidate.toString() << " Name: " << out_data.name_id
<< " Road Class: " << (int)out_data.road_classification.road_class
<< " At: " << localizer(node_based_graph->GetTarget(candidate.eid));
if (!candidate.valid) if (!candidate.valid)
continue; continue;
const auto &out_data = node_based_graph->GetEdgeData(candidate.eid);
const auto type = isMotorwayClass(out_data.road_classification.road_class) ? TurnType::Merge const auto type = isMotorwayClass(out_data.road_classification.road_class) ? TurnType::Merge
: TurnType::Turn; : TurnType::Turn;
if (angularDeviation(candidate.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE) if (angularDeviation(candidate.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE)
candidate.instruction = {type, DirectionModifier::Straight}; candidate.instruction = {type, DirectionModifier::Straight};
else else
{ {
candidate.instruction = {type, candidate.angle > STRAIGHT_ANGLE candidate.instruction = {type,
? DirectionModifier::SlightLeft candidate.angle > STRAIGHT_ANGLE
: DirectionModifier::SlightRight}; ? DirectionModifier::SlightLeft
: DirectionModifier::SlightRight};
} }
} }
return turn_candidates; return turn_candidates;
@ -380,7 +407,7 @@ handleFromMotorway(const NodeID from,
else else
{ {
// FALLBACK, this should hopefully never be reached // FALLBACK, this should hopefully never be reached
util::SimpleLogger().Write(logDEBUG) util::SimpleLogger().Write(logWARNING)
<< "Fallback reached from motorway, no continue angle, " << turn_candidates.size() << "Fallback reached from motorway, no continue angle, " << turn_candidates.size()
<< " candidates, " << countValid(turn_candidates) << " valid ones."; << " candidates, " << countValid(turn_candidates) << " valid ones.";
fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph);
@ -454,7 +481,16 @@ handleFromMotorway(const NodeID from,
// handle motorway forks // handle motorway forks
else if (exiting_motorways > 1) else if (exiting_motorways > 1)
{ {
if (exiting_motorways != 2 || turn_candidates.size() != 3) if (exiting_motorways == 2 && turn_candidates.size() == 2)
{
turn_candidates[1].instruction =
getInstructionForObvious(from, via_edge, turn_candidates[1], node_based_graph);
util::SimpleLogger().Write(logWARNING)
<< "Disable U-Turn on a freeway at "
<< localizer(node_based_graph->GetTarget(via_edge));
turn_candidates[0].valid = false; // UTURN on the freeway
}
else if (exiting_motorways != 2 || turn_candidates.size() != 3)
{ {
util::SimpleLogger().Write(logWARNING) << "Found motorway junction with more than " util::SimpleLogger().Write(logWARNING) << "Found motorway junction with more than "
"2 exiting motorways or additional ramps!" "2 exiting motorways or additional ramps!"
@ -485,8 +521,9 @@ handleMotorwayRamp(const NodeID from,
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)
{ {
unsigned num_valid_turns = countValid(turn_candidates);
// ramp straight into a motorway/ramp // ramp straight into a motorway/ramp
if (turn_candidates.size() == 2) if (num_valid_turns == 1)
{ {
BOOST_ASSERT(!turn_candidates[0].valid); BOOST_ASSERT(!turn_candidates[0].valid);
BOOST_ASSERT(isMotorwayClass(turn_candidates[1].eid, node_based_graph)); BOOST_ASSERT(isMotorwayClass(turn_candidates[1].eid, node_based_graph));
@ -498,8 +535,6 @@ handleMotorwayRamp(const NodeID from,
} }
else if (turn_candidates.size() == 3) else if (turn_candidates.size() == 3)
{ {
unsigned num_valid_turns = countValid(turn_candidates);
// merging onto a passing highway / or two ramps merging onto the same highway // merging onto a passing highway / or two ramps merging onto the same highway
if (num_valid_turns == 1) if (num_valid_turns == 1)
{ {
@ -587,11 +622,35 @@ handleMotorwayRamp(const NodeID from,
} }
} }
} }
// On - Off Ramp on passing Motorway, Ramp onto Fork(?)
else if (turn_candidates.size() == 4)
{
bool passed_highway_entry = false;
for (auto &candidate : turn_candidates)
{
const auto &edge_data = node_based_graph->GetEdgeData(candidate.eid);
if (!candidate.valid && isMotorwayClass(edge_data.road_classification.road_class))
{
passed_highway_entry = true;
}
else if (isMotorwayClass(edge_data.road_classification.road_class))
{
candidate.instruction = {TurnType::Merge,
passed_highway_entry ? DirectionModifier::SlightRight
: DirectionModifier::SlightLeft};
}
else
{
BOOST_ASSERT(isRampClass(edge_data.road_classification.road_class));
candidate.instruction = {TurnType::Ramp, getTurnDirection(candidate.angle)};
}
}
}
else else
{ // FALLBACK, hopefully this should never been reached { // FALLBACK, hopefully this should never been reached
util::SimpleLogger().Write(logDEBUG) << "Reached fallback on motorway ramp with " util::SimpleLogger().Write(logWARNING) << "Reached fallback on motorway ramp with "
<< turn_candidates.size() << " candidates and " << turn_candidates.size() << " candidates and "
<< countValid(turn_candidates) << " valid turns."; << countValid(turn_candidates) << " valid turns.";
fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph);
} }
@ -672,17 +731,31 @@ bool isMotorwayJunction(const NodeID from,
{ {
(void)from; (void)from;
bool has_motorway = false;
bool has_normal_roads = false;
for (const auto &candidate : turn_candidates) for (const auto &candidate : turn_candidates)
{ {
const auto &out_data = node_based_graph->GetEdgeData(candidate.eid); const auto &out_data = node_based_graph->GetEdgeData(candidate.eid);
if (candidate.valid && // not merging or forking?
(out_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY || if ((angularDeviation(candidate.angle, 0) > 35 &&
out_data.road_classification.road_class == FunctionalRoadClass::TRUNK)) angularDeviation(candidate.angle, 180) > 35) ||
return true; (candidate.valid && angularDeviation(candidate.angle, 0) < 35))
return false;
else if (candidate.valid &&
(out_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY ||
out_data.road_classification.road_class == FunctionalRoadClass::TRUNK))
has_motorway = true;
else if (candidate.valid && !isRampClass(out_data.road_classification.road_class))
has_normal_roads = true;
} }
if (has_normal_roads)
return false;
const auto &in_data = node_based_graph->GetEdgeData(via_edge); const auto &in_data = node_based_graph->GetEdgeData(via_edge);
return in_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY || return has_motorway ||
in_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY ||
in_data.road_classification.road_class == FunctionalRoadClass::TRUNK; in_data.road_classification.road_class == FunctionalRoadClass::TRUNK;
} }
@ -933,8 +1006,8 @@ handleThreeWayTurn(const NodeID from,
node_based_graph->GetEdgeData(turn_candidates[1].eid).name_id == node_based_graph->GetEdgeData(turn_candidates[1].eid).name_id ==
node_based_graph->GetEdgeData(turn_candidates[2].eid).name_id) node_based_graph->GetEdgeData(turn_candidates[2].eid).name_id)
{ {
const auto findTurn = [isObviousOfTwo](const TurnCandidate turn, const auto findTurn = [isObviousOfTwo](const TurnCandidate turn, const TurnCandidate other)
const TurnCandidate other) -> TurnInstruction -> TurnInstruction
{ {
return {isObviousOfTwo(turn, other) ? TurnType::Merge : TurnType::Turn, return {isObviousOfTwo(turn, other) ? TurnType::Merge : TurnType::Turn,
getTurnDirection(turn.angle)}; getTurnDirection(turn.angle)};
@ -1185,7 +1258,7 @@ optimizeCandidates(const EdgeID via_eid,
auto &left = turn_candidates[getLeft(turn_index)]; auto &left = turn_candidates[getLeft(turn_index)];
if (turn.angle == left.angle) if (turn.angle == left.angle)
{ {
util::SimpleLogger().Write(logDEBUG) util::SimpleLogger().Write(logWARNING)
<< "[warning] conflicting turn angles, identical road duplicated? " << "[warning] conflicting turn angles, identical road duplicated? "
<< node_info_list[node_based_graph->GetTarget(via_eid)].lat << " " << node_info_list[node_based_graph->GetTarget(via_eid)].lat << " "
<< node_info_list[node_based_graph->GetTarget(via_eid)].lon << std::endl; << node_info_list[node_based_graph->GetTarget(via_eid)].lon << std::endl;
@ -1356,8 +1429,8 @@ bool isObviousChoice(const EdgeID via_eid,
const auto &candidate_to_the_right = turn_candidates[getRight(turn_index)]; const auto &candidate_to_the_right = turn_candidates[getRight(turn_index)];
const auto hasValidRatio = [&](const TurnCandidate &left, const TurnCandidate &center, const auto hasValidRatio =
const TurnCandidate &right) [&](const TurnCandidate &left, const TurnCandidate &center, const TurnCandidate &right)
{ {
auto angle_left = (left.angle > 180) ? angularDeviation(left.angle, STRAIGHT_ANGLE) : 180; auto angle_left = (left.angle > 180) ? angularDeviation(left.angle, STRAIGHT_ANGLE) : 180;
auto angle_right = auto angle_right =
@ -1688,9 +1761,8 @@ mergeSegregatedRoads(const NodeID from_node,
std::cout << "Second: " << second_data.name_id << " " << second_data.travel_mode << " " std::cout << "Second: " << second_data.name_id << " " << second_data.travel_mode << " "
<< second_data.road_classification.road_class << " " << second_data.road_classification.road_class << " "
<< turn_candidates[second].angle << " " << second_data.reversed << std::endl; << turn_candidates[second].angle << " " << second_data.reversed << std::endl;
std::cout << "Deviation: " std::cout << "Deviation: " << angularDeviation(turn_candidates[first].angle,
<< angularDeviation(turn_candidates[first].angle, turn_candidates[second].angle) turn_candidates[second].angle) << std::endl;
<< std::endl;
#endif #endif
return first_data.name_id != INVALID_NAME_ID && first_data.name_id == second_data.name_id && return first_data.name_id != INVALID_NAME_ID && first_data.name_id == second_data.name_id &&