From b5228dcda01359ead1c84f1980a03110b566029e Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 22 Jan 2015 23:53:35 +0100 Subject: [PATCH] Detect possible uturns in the data. To make them work, we have to disable PhantomNode splitting for this coordinates. --- CMakeLists.txt | 2 +- plugins/map_matching.hpp | 39 +++++++++++++++++++++-------- routing_algorithms/map_matching.hpp | 11 +++++--- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b957d5dce..e3dac8ba9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,7 @@ file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp util/co set(PrepareSources prepare.cpp ${PrepareGlob}) add_executable(osrm-prepare ${PrepareSources} $ $ $ $ $ $ $ $) -file(GLOB ServerGlob server/*.cpp) +file(GLOB ServerGlob server/*.cpp util/compute_angle.cpp) file(GLOB DescriptorGlob descriptors/*.cpp) file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp util/bearing.cpp) list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 641d198ca..3fad436be 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -27,6 +27,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../util/integer_range.hpp" #include "../data_structures/search_engine.hpp" #include "../routing_algorithms/map_matching.hpp" +#include "../util/compute_angle.hpp" #include "../util/simple_logger.hpp" #include "../util/string_util.hpp" #include "../descriptors/descriptor_base.hpp" @@ -68,22 +69,39 @@ template class MapMatchingPlugin : public BasePlugin return 400; } - InternalRouteResult raw_route; + const auto& input_coords = route_parameters.coordinates; Matching::CandidateLists candidate_lists; + std::vector uturn_indicators(false, input_coords.size()); double last_distance = coordinate_calculation::great_circle_distance( - route_parameters.coordinates[0], - route_parameters.coordinates[1]); - for (const auto current_coordinate : osrm::irange(0, route_parameters.coordinates.size())) + input_coords[0], + input_coords[1]); + for (const auto current_coordinate : osrm::irange(0, input_coords.size())) { if (0 < current_coordinate) + { last_distance = coordinate_calculation::great_circle_distance( - route_parameters.coordinates[current_coordinate - 1], - route_parameters.coordinates[current_coordinate]); + input_coords[current_coordinate - 1], + input_coords[current_coordinate]); + } + + if (input_coords.size()-1 > current_coordinate && 0 < current_coordinate) + { + double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates( + input_coords[current_coordinate-1], + input_coords[current_coordinate], + input_coords[current_coordinate+1]); + + // sharp turns indicate a possible uturn + if (turn_angle < 100.0 || turn_angle > 260.0) + { + uturn_indicators[current_coordinate] = true; + } + } std::vector> candidates; if (!facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance( - route_parameters.coordinates[current_coordinate], + input_coords[current_coordinate], candidates, last_distance/2.0, 5, @@ -98,8 +116,10 @@ template class MapMatchingPlugin : public BasePlugin // call the actual map matching std::vector matched_nodes; JSON::Object debug_info; - search_engine_ptr->map_matching(candidate_lists, route_parameters.coordinates, matched_nodes, debug_info); + search_engine_ptr->map_matching(candidate_lists, input_coords, uturn_indicators, matched_nodes, debug_info); + + InternalRouteResult raw_route; PhantomNodes current_phantom_node_pair; for (unsigned i = 0; i < matched_nodes.size() - 1; ++i) { @@ -110,8 +130,7 @@ template class MapMatchingPlugin : public BasePlugin if (2 > matched_nodes.size()) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } search_engine_ptr->shortest_path( diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 8432c548c..8ebd8778b 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -276,7 +276,8 @@ template class MapMatching final // TODO optimize: a lot of copying that could probably be avoided void expandCandidates(const Matching::CandidateLists &candidates_lists, - Matching::CandidateLists &expanded_lists) const + Matching::CandidateLists &expanded_lists, + const std::vector& uturn_indicators) const { // expand list of PhantomNodes to be single-directional expanded_lists.resize(candidates_lists.size()); @@ -284,8 +285,8 @@ template class MapMatching final { for (const auto& candidate : candidates_lists[i]) { - // bi-directional edge, split phantom node - if (candidate.first.forward_node_id != SPECIAL_NODEID && candidate.first.reverse_node_id != SPECIAL_NODEID) + // bi-directional edge, split phantom node if we don't expect a uturn + if (!uturn_indicators[i] && candidate.first.forward_node_id != SPECIAL_NODEID && candidate.first.reverse_node_id != SPECIAL_NODEID) { PhantomNode forward_node(candidate.first); PhantomNode reverse_node(candidate.first); @@ -304,13 +305,15 @@ template class MapMatching final void operator()(const Matching::CandidateLists &candidates_lists, const std::vector coordinate_list, + const std::vector& uturn_indicators, std::vector& matched_nodes, JSON::Object& _debug_info) const { BOOST_ASSERT(candidates_lists.size() == coordinate_list.size()); + BOOST_ASSERT(candidates_lists.size() == uturn_indicators.size()); Matching::CandidateLists timestamp_list; - expandCandidates(candidates_lists, timestamp_list); + expandCandidates(candidates_lists, timestamp_list, uturn_indicators); std::vector breakage(timestamp_list.size(), true);