From 8322a7ccaf6b0954b5f3988e9826c92f6c739163 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Thu, 3 Mar 2016 15:36:03 +0100 Subject: [PATCH] bugfixing/classification --- include/engine/datafacade/datafacade_base.hpp | 3 +- .../engine/datafacade/internal_datafacade.hpp | 3 +- .../engine/datafacade/shared_datafacade.hpp | 22 ++-- include/engine/guidance/assemble_geometry.hpp | 3 +- include/engine/guidance/assemble_leg.hpp | 2 +- include/engine/guidance/assemble_steps.hpp | 54 +++++--- include/engine/guidance/toolkit.hpp | 3 +- include/engine/plugins/plugin_base.hpp | 2 +- .../routing_algorithms/routing_base.hpp | 10 +- .../guidance/classification_data.hpp | 2 +- include/extractor/guidance/toolkit.hpp | 60 ++++----- src/engine/api/json_factory.cpp | 16 ++- src/engine/guidance/post_processing.cpp | 3 +- src/engine/plugins/viaroute.cpp | 4 +- src/extractor/edge_based_graph_factory.cpp | 6 +- src/extractor/extractor_callbacks.cpp | 20 ++- src/extractor/guidance/turn_analysis.cpp | 122 ++++++++++++++---- 17 files changed, 214 insertions(+), 121 deletions(-) diff --git a/include/engine/datafacade/datafacade_base.hpp b/include/engine/datafacade/datafacade_base.hpp index 7fb17c786..25be82293 100644 --- a/include/engine/datafacade/datafacade_base.hpp +++ b/include/engine/datafacade/datafacade_base.hpp @@ -76,7 +76,8 @@ class BaseDataFacade virtual void GetUncompressedWeights(const EdgeID id, std::vector &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; diff --git a/include/engine/datafacade/internal_datafacade.hpp b/include/engine/datafacade/internal_datafacade.hpp index 7d12a5166..fbe699766 100644 --- a/include/engine/datafacade/internal_datafacade.hpp +++ b/include/engine/datafacade/internal_datafacade.hpp @@ -329,7 +329,8 @@ class InternalDataFacade final : public BaseDataFacade 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); } diff --git a/include/engine/datafacade/shared_datafacade.hpp b/include/engine/datafacade/shared_datafacade.hpp index fbf367f42..d0bdfbbf8 100644 --- a/include/engine/datafacade/shared_datafacade.hpp +++ b/include/engine/datafacade/shared_datafacade.hpp @@ -147,11 +147,13 @@ class SharedDataFacade final : public BaseDataFacade travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]); m_travel_mode_list = std::move(travel_mode_list); - auto turn_instruction_list_ptr = data_layout->GetBlockPtr( - shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION); - typename util::ShM::vector turn_instruction_list( - turn_instruction_list_ptr, - data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]); + auto turn_instruction_list_ptr = + data_layout->GetBlockPtr( + shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION); + typename util::ShM::vector + turn_instruction_list( + turn_instruction_list_ptr, + data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]); m_turn_instruction_list = std::move(turn_instruction_list); auto name_id_list_ptr = data_layout->GetBlockPtr( @@ -237,8 +239,7 @@ class SharedDataFacade final : public BaseDataFacade } data_timestamp_ptr = static_cast( storage::makeSharedMemory(storage::CURRENT_REGIONS, - sizeof(storage::SharedDataTimestamp), false, false) - ->Ptr()); + sizeof(storage::SharedDataTimestamp), false, false)->Ptr()); CURRENT_LAYOUT = storage::LAYOUT_NONE; CURRENT_DATA = storage::DATA_NONE; CURRENT_TIMESTAMP = 0; @@ -309,8 +310,8 @@ class SharedDataFacade final : public BaseDataFacade LoadNames(); LoadCoreInformation(); - util::SimpleLogger().Write() << "number of geometries: " - << m_coordinate_list->size(); + util::SimpleLogger().Write() + << "number of geometries: " << m_coordinate_list->size(); for (unsigned i = 0; i < m_coordinate_list->size(); ++i) { if (!GetCoordinateOfNode(i).IsValid()) @@ -400,7 +401,8 @@ class SharedDataFacade final : public BaseDataFacade 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); } diff --git a/include/engine/guidance/assemble_geometry.hpp b/include/engine/guidance/assemble_geometry.hpp index 27e3bf3c1..a841ce38a 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -5,6 +5,7 @@ #include "engine/phantom_node.hpp" #include "engine/guidance/route_step.hpp" #include "engine/guidance/leg_geometry.hpp" +#include "engine/guidance/toolkit.hpp" #include "util/coordinate_calculation.hpp" #include "util/coordinate.hpp" #include "extractor/guidance/turn_instruction.hpp" @@ -49,7 +50,7 @@ LegGeometry assembleGeometry(const DataFacadeT &facade, current_distance += 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_offsets.push_back(geometry.locations.size()); diff --git a/include/engine/guidance/assemble_leg.hpp b/include/engine/guidance/assemble_leg.hpp index f0f855e71..fc91aac7b 100644 --- a/include/engine/guidance/assemble_leg.hpp +++ b/include/engine/guidance/assemble_leg.hpp @@ -134,7 +134,7 @@ RouteLeg assembleLeg(const DataFacadeT &facade, // `forward_weight`: duration of (d,t) // `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. // As such we want to slice of the duration for (a,s) and add the duration for // (c,d,t) diff --git a/include/engine/guidance/assemble_steps.hpp b/include/engine/guidance/assemble_steps.hpp index bc459ebdc..787bc29fe 100644 --- a/include/engine/guidance/assemble_steps.hpp +++ b/include/engine/guidance/assemble_steps.hpp @@ -104,18 +104,26 @@ std::vector assembleSteps(const DataFacadeT &facade, { const auto name = facade.get_name_for_id(path_point.name_id); const auto distance = leg_geometry.segment_distances[segment_index]; - steps.push_back(RouteStep{ - path_point.name_id, name, path_point.duration_until_turn / 10.0, distance, - path_point.travel_mode, maneuver, leg_geometry.FrontIndex(segment_index), - leg_geometry.BackIndex(segment_index) + 1}); + steps.push_back(RouteStep{path_point.name_id, + name, + path_point.duration_until_turn / 10.0, + distance, + path_point.travel_mode, + maneuver, + leg_geometry.FrontIndex(segment_index), + leg_geometry.BackIndex(segment_index) + 1}); maneuver = detail::stepManeuverFromGeometry( path_point.turn_instruction, leg_geometry, segment_index, path_point.exit); 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), - target_duration, distance, target_mode, maneuver, + steps.push_back(RouteStep{target_node.name_id, + facade.get_name_for_id(target_node.name_id), + target_duration, + distance, + target_mode, + maneuver, leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1}); } @@ -126,15 +134,20 @@ std::vector assembleSteps(const DataFacadeT &facade, // |-------------t target_duration // x---*---*---*---z compressed edge // |-------| duration - StepManeuver maneuver = {source_node.location, 0., 0., + StepManeuver maneuver = {source_node.location, + 0., + 0., extractor::guidance::TurnInstruction{ extractor::guidance::TurnType::Location, initial_modifier}, 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, - leg_geometry.segment_distances[segment_index], source_mode, - std::move(maneuver), leg_geometry.FrontIndex(segment_index), + leg_geometry.segment_distances[segment_index], + source_mode, + std::move(maneuver), + leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1}); } @@ -146,13 +159,20 @@ std::vector assembleSteps(const DataFacadeT &facade, target_location.get())) : extractor::guidance::DirectionModifier::UTurn; // This step has length zero, the only reason we need it is the target location - steps.push_back(RouteStep{ - target_node.name_id, facade.get_name_for_id(target_node.name_id), 0., 0., target_mode, - 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()}); + steps.push_back( + RouteStep{target_node.name_id, + facade.get_name_for_id(target_node.name_id), + 0., + 0., + target_mode, + 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; } diff --git a/include/engine/guidance/toolkit.hpp b/include/engine/guidance/toolkit.hpp index 000382823..e9cbcf5e3 100644 --- a/include/engine/guidance/toolkit.hpp +++ b/include/engine/guidance/toolkit.hpp @@ -14,7 +14,8 @@ namespace guidance // Silent Turn Instructions are not to be mentioned to the outside world but 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; } diff --git a/include/engine/plugins/plugin_base.hpp b/include/engine/plugins/plugin_base.hpp index d80832088..aec9dd02a 100644 --- a/include/engine/plugins/plugin_base.hpp +++ b/include/engine/plugins/plugin_base.hpp @@ -267,7 +267,7 @@ class BasePlugin // we didn't find a fitting node, return error if (!phantom_node_pairs[i].first.IsValid(facade.GetNumberOfNodes())) { - //TODO document why? + // TODO document why? phantom_node_pairs.pop_back(); break; } diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index fbd035cde..b9932ae6b 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -283,8 +283,7 @@ template class BasicRoutingInterface { BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut"); unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id); - const auto turn_instruction = - facade->GetTurnInstructionForEdgeID(ed.id); + const auto turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id); const extractor::TravelMode travel_mode = (unpacked_path.empty() && start_traversed_in_reverse) ? phantom_node_pair.source_phantom.backward_travel_mode @@ -320,9 +319,10 @@ template class BasicRoutingInterface BOOST_ASSERT(start_index < end_index); for (std::size_t i = start_index; i < end_index; ++i) { - unpacked_path.push_back(PathData{id_vector[i], name_index, weight_vector[i], - extractor::guidance::TurnInstruction::NO_TURN(), - travel_mode, INVALID_EXIT_NR}); + unpacked_path.push_back( + PathData{id_vector[i], name_index, weight_vector[i], + extractor::guidance::TurnInstruction::NO_TURN(), travel_mode, + INVALID_EXIT_NR}); } BOOST_ASSERT(unpacked_path.size() > 0); unpacked_path.back().turn_instruction = turn_instruction; diff --git a/include/extractor/guidance/classification_data.hpp b/include/extractor/guidance/classification_data.hpp index 212ad0cdf..93a85c434 100644 --- a/include/extractor/guidance/classification_data.hpp +++ b/include/extractor/guidance/classification_data.hpp @@ -41,7 +41,7 @@ enum class FunctionalRoadClass : short 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 = []() { std::unordered_map hash; diff --git a/include/extractor/guidance/toolkit.hpp b/include/extractor/guidance/toolkit.hpp index 3c8e15f46..f43930f00 100644 --- a/include/extractor/guidance/toolkit.hpp +++ b/include/extractor/guidance/toolkit.hpp @@ -132,15 +132,13 @@ getRepresentativeCoordinate(const NodeID from_node, } // shift an instruction around the degree circle in CCW order -inline DirectionModifier -forcedShiftCCW(const DirectionModifier modifier) +inline DirectionModifier forcedShiftCCW(const DirectionModifier modifier) { - return static_cast( - (static_cast(modifier) + 1) % detail::num_direction_modifiers); + return static_cast((static_cast(modifier) + 1) % + detail::num_direction_modifiers); } -inline DirectionModifier -shiftCCW(const DirectionModifier modifier) +inline DirectionModifier shiftCCW(const DirectionModifier modifier) { if (detail::shiftable_ccw[static_cast(modifier)]) return forcedShiftCCW(modifier); @@ -149,16 +147,14 @@ shiftCCW(const DirectionModifier modifier) } // shift an instruction around the degree circle in CW order -inline DirectionModifier -forcedShiftCW(const DirectionModifier modifier) +inline DirectionModifier forcedShiftCW(const DirectionModifier modifier) { return static_cast( (static_cast(modifier) + detail::num_direction_modifiers - 1) % detail::num_direction_modifiers); } -inline DirectionModifier -shiftCW(const DirectionModifier modifier) +inline DirectionModifier shiftCW(const DirectionModifier modifier) { if (detail::shiftable_cw[static_cast(modifier)]) return forcedShiftCW(modifier); @@ -168,19 +164,15 @@ shiftCW(const DirectionModifier modifier) inline bool isBasic(const TurnType type) { - return type == TurnType::Turn || - type == TurnType::EndOfRoad; + return type == TurnType::Turn || type == TurnType::EndOfRoad; } inline bool isUturn(const TurnInstruction instruction) { - return isBasic(instruction.type) && - instruction.direction_modifier == DirectionModifier::UTurn; + return isBasic(instruction.type) && instruction.direction_modifier == DirectionModifier::UTurn; } -inline bool resolve(TurnInstruction &to_resolve, - const TurnInstruction neighbor, - bool resolve_cw) +inline bool resolve(TurnInstruction &to_resolve, const TurnInstruction neighbor, bool resolve_cw) { const auto shifted_turn = resolve_cw ? shiftCW(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) { - return isBasic(turn.type) && - (turn.direction_modifier == DirectionModifier::SharpLeft || - turn.direction_modifier == DirectionModifier::SharpRight); + return isBasic(turn.type) && (turn.direction_modifier == DirectionModifier::SharpLeft || + turn.direction_modifier == DirectionModifier::SharpRight); } inline bool isStraight(const TurnInstruction turn) @@ -234,8 +225,7 @@ inline bool isStraight(const TurnInstruction turn) turn.direction_modifier == DirectionModifier::Straight; } -inline bool isConflict(const TurnInstruction first, - const TurnInstruction second) +inline bool isConflict(const TurnInstruction first, const TurnInstruction second) { return (first.type == second.type && first.direction_modifier == second.direction_modifier) || (isStraight(first) && isStraight(second)); @@ -244,8 +234,7 @@ inline bool isConflict(const TurnInstruction first, inline DiscreteAngle discretizeAngle(const double angle) { BOOST_ASSERT(angle >= 0. && angle <= 360.); - return DiscreteAngle( - static_cast(angle / detail::discrete_angle_step_size)); + return DiscreteAngle(static_cast(angle / detail::discrete_angle_step_size)); } 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 - if (!isBasic(instruction.type) || - instruction.direction_modifier == DirectionModifier::UTurn) + if (!isBasic(instruction.type) || instruction.direction_modifier == DirectionModifier::UTurn) return 1.0; 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 -inline DirectionModifier -mirrorDirectionModifier(const DirectionModifier modifier) +inline DirectionModifier mirrorDirectionModifier(const DirectionModifier modifier) { - const constexpr DirectionModifier results[] = { - DirectionModifier::UTurn, - DirectionModifier::SharpLeft, - DirectionModifier::Left, - DirectionModifier::SlightLeft, - DirectionModifier::Straight, - DirectionModifier::SlightRight, - DirectionModifier::Right, - DirectionModifier::SharpRight}; + const constexpr DirectionModifier results[] = {DirectionModifier::UTurn, + DirectionModifier::SharpLeft, + DirectionModifier::Left, + DirectionModifier::SlightLeft, + DirectionModifier::Straight, + DirectionModifier::SlightRight, + DirectionModifier::Right, + DirectionModifier::SharpRight}; return results[modifier]; } diff --git a/src/engine/api/json_factory.cpp b/src/engine/api/json_factory.cpp index 41e9f33f9..6ad7574df 100644 --- a/src/engine/api/json_factory.cpp +++ b/src/engine/api/json_factory.cpp @@ -28,8 +28,14 @@ namespace json namespace detail { -const constexpr char *modifier_names[] = {"uturn", "sharp right", "right", "slight right", - "straight", "slight left", "left", "sharp left"}; +const constexpr char *modifier_names[] = {"uturn", + "sharp right", + "right", + "slight right", + "straight", + "slight left", + "left", + "sharp left"}; // translations of TurnTypes. Not all types are exposed to the outside world. // 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"}; // Check whether to include a modifier in the result of the API -inline bool isValidModifier(const TurnType type, - const DirectionModifier modifier) +inline bool isValidModifier(const TurnType type, const DirectionModifier modifier) { if (type == TurnType::Location && modifier != DirectionModifier::Left && - modifier != DirectionModifier::Straight && - modifier != DirectionModifier::Right) + modifier != DirectionModifier::Straight && modifier != DirectionModifier::Right) return false; return true; } diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index 7cb016097..85cb69b46 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -51,8 +51,7 @@ PathData mergeInto(PathData destination, const PathData &source) BOOST_ASSERT(canMergeTrivially(destination, source)); return detail::forwardInto(destination, source); } - if (source.turn_instruction == TurnType::Suppressed && - detail::canMergeTrivially(destination, source)) + if (source.turn_instruction.type == TurnType::Suppressed) { return detail::forwardInto(destination, source); } diff --git a/src/engine/plugins/viaroute.cpp b/src/engine/plugins/viaroute.cpp index 333923bba..2cf98f869 100644 --- a/src/engine/plugins/viaroute.cpp +++ b/src/engine/plugins/viaroute.cpp @@ -59,8 +59,8 @@ Status ViaRoutePlugin::HandleRequest(const api::RouteParameters &route_parameter auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs); InternalRouteResult raw_route; - auto build_phantom_pairs = [&raw_route](const PhantomNode &first_node, - const PhantomNode &second_node) + auto build_phantom_pairs = + [&raw_route](const PhantomNode &first_node, const PhantomNode &second_node) { raw_route.segment_end_coordinates.push_back(PhantomNodes{first_node, second_node}); }; diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index 4a1ece193..04186829e 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -316,9 +316,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( } ++node_based_edge_counter; - auto turn_candidates = guidance::getTurns( - node_u, edge_from_u, m_node_based_graph, m_node_info_list, m_restriction_map, - m_barrier_nodes, m_compressed_edge_container); + auto turn_candidates = + guidance::getTurns(node_u, edge_from_u, m_node_based_graph, m_node_info_list, + m_restriction_map, m_barrier_nodes, m_compressed_edge_container); const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u); diff --git a/src/extractor/extractor_callbacks.cpp b/src/extractor/extractor_callbacks.cpp index a289ec63f..998c0740c 100644 --- a/src/extractor/extractor_callbacks.cpp +++ b/src/extractor/extractor_callbacks.cpp @@ -41,7 +41,9 @@ void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node, external_memory.all_nodes_list.push_back( {util::toFixed(util::FloatLongitude(input_node.location().lon())), 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( @@ -123,8 +125,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti if (forward_weight_data.type == InternalExtractorEdge::WeightType::INVALID && backward_weight_data.type == InternalExtractorEdge::WeightType::INVALID) { - util::SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " - << input_way.id(); + util::SimpleLogger().Write(logDEBUG) + << "found way with bogus speed, id: " << input_way.id(); return; } @@ -185,9 +187,11 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti }); 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()[1].ref()), OSMNodeID(input_way.nodes()[0].ref())}); + OSMNodeID(input_way.nodes()[1].ref()), + OSMNodeID(input_way.nodes()[0].ref())}); } else { @@ -219,9 +223,11 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti } 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()[1].ref()), OSMNodeID(input_way.nodes()[0].ref())}); + OSMNodeID(input_way.nodes()[1].ref()), + OSMNodeID(input_way.nodes()[0].ref())}); } } } diff --git a/src/extractor/guidance/turn_analysis.cpp b/src/extractor/guidance/turn_analysis.cpp index 14afbac26..8a0f15d34 100644 --- a/src/extractor/guidance/turn_analysis.cpp +++ b/src/extractor/guidance/turn_analysis.cpp @@ -1,6 +1,7 @@ #include "extractor/guidance/turn_analysis.hpp" #include "util/simple_logger.hpp" +#include "util/coordinate.hpp" #include @@ -28,6 +29,22 @@ const unsigned constexpr INVALID_NAME_ID = 0; using EdgeData = util::NodeBasedDynamicGraph::EdgeData; +struct Localizer +{ + const std::vector *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 std::vector getTurns(const NodeID from, @@ -38,6 +55,7 @@ getTurns(const NodeID from, const std::unordered_set &barrier_nodes, const CompressedEdgeContainer &compressed_edge_container) { + localizer.node_info_list = &node_info_list; auto turn_candidates = detail::getTurnCandidates(from, via_edge, node_based_graph, node_info_list, restriction_map, barrier_nodes, compressed_edge_container); @@ -264,20 +282,29 @@ inline std::vector fallbackTurnAssignmentMotorway( std::vector turn_candidates, const std::shared_ptr node_based_graph) { + util::SimpleLogger().Write(logWARNING) << "Fallback turn assignment"; 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) continue; - const auto &out_data = node_based_graph->GetEdgeData(candidate.eid); + const auto type = isMotorwayClass(out_data.road_classification.road_class) ? TurnType::Merge : TurnType::Turn; if (angularDeviation(candidate.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE) candidate.instruction = {type, DirectionModifier::Straight}; else { - candidate.instruction = {type, candidate.angle > STRAIGHT_ANGLE - ? DirectionModifier::SlightLeft - : DirectionModifier::SlightRight}; + candidate.instruction = {type, + candidate.angle > STRAIGHT_ANGLE + ? DirectionModifier::SlightLeft + : DirectionModifier::SlightRight}; } } return turn_candidates; @@ -380,7 +407,7 @@ handleFromMotorway(const NodeID from, else { // 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() << " candidates, " << countValid(turn_candidates) << " valid ones."; fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); @@ -454,7 +481,16 @@ handleFromMotorway(const NodeID from, // handle motorway forks 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 " "2 exiting motorways or additional ramps!" @@ -485,8 +521,9 @@ handleMotorwayRamp(const NodeID from, std::vector turn_candidates, const std::shared_ptr node_based_graph) { + unsigned num_valid_turns = countValid(turn_candidates); // ramp straight into a motorway/ramp - if (turn_candidates.size() == 2) + if (num_valid_turns == 1) { BOOST_ASSERT(!turn_candidates[0].valid); BOOST_ASSERT(isMotorwayClass(turn_candidates[1].eid, node_based_graph)); @@ -498,8 +535,6 @@ handleMotorwayRamp(const NodeID from, } 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 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 { // FALLBACK, hopefully this should never been reached - util::SimpleLogger().Write(logDEBUG) << "Reached fallback on motorway ramp with " - << turn_candidates.size() << " candidates and " - << countValid(turn_candidates) << " valid turns."; + util::SimpleLogger().Write(logWARNING) << "Reached fallback on motorway ramp with " + << turn_candidates.size() << " candidates and " + << countValid(turn_candidates) << " valid turns."; fallbackTurnAssignmentMotorway(turn_candidates, node_based_graph); } @@ -672,17 +731,31 @@ bool isMotorwayJunction(const NodeID from, { (void)from; + bool has_motorway = false; + bool has_normal_roads = false; + for (const auto &candidate : turn_candidates) { const auto &out_data = node_based_graph->GetEdgeData(candidate.eid); - if (candidate.valid && - (out_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY || - out_data.road_classification.road_class == FunctionalRoadClass::TRUNK)) - return true; + // not merging or forking? + if ((angularDeviation(candidate.angle, 0) > 35 && + angularDeviation(candidate.angle, 180) > 35) || + (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); - 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; } @@ -933,8 +1006,8 @@ handleThreeWayTurn(const NodeID from, node_based_graph->GetEdgeData(turn_candidates[1].eid).name_id == node_based_graph->GetEdgeData(turn_candidates[2].eid).name_id) { - const auto findTurn = [isObviousOfTwo](const TurnCandidate turn, - const TurnCandidate other) -> TurnInstruction + const auto findTurn = [isObviousOfTwo](const TurnCandidate turn, const TurnCandidate other) + -> TurnInstruction { return {isObviousOfTwo(turn, other) ? TurnType::Merge : TurnType::Turn, getTurnDirection(turn.angle)}; @@ -1185,7 +1258,7 @@ optimizeCandidates(const EdgeID via_eid, auto &left = turn_candidates[getLeft(turn_index)]; if (turn.angle == left.angle) { - util::SimpleLogger().Write(logDEBUG) + util::SimpleLogger().Write(logWARNING) << "[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)].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 hasValidRatio = [&](const TurnCandidate &left, const TurnCandidate ¢er, - const TurnCandidate &right) + const auto hasValidRatio = + [&](const TurnCandidate &left, const TurnCandidate ¢er, const TurnCandidate &right) { auto angle_left = (left.angle > 180) ? angularDeviation(left.angle, STRAIGHT_ANGLE) : 180; auto angle_right = @@ -1688,9 +1761,8 @@ mergeSegregatedRoads(const NodeID from_node, std::cout << "Second: " << second_data.name_id << " " << second_data.travel_mode << " " << second_data.road_classification.road_class << " " << turn_candidates[second].angle << " " << second_data.reversed << std::endl; - std::cout << "Deviation: " - << angularDeviation(turn_candidates[first].angle, turn_candidates[second].angle) - << std::endl; + std::cout << "Deviation: " << angularDeviation(turn_candidates[first].angle, + turn_candidates[second].angle) << std::endl; #endif return first_data.name_id != INVALID_NAME_ID && first_data.name_id == second_data.name_id &&