diff --git a/CHANGELOG.md b/CHANGELOG.md index 28ffa7238..440325c5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ # UNRELEASED - - Changes from 5.14.1: - - Bugfixes: + - Changes from 5.14.1: + - Bugfixes: - FIXED #4727: Erroring when a old .core file is present. + - Node.js Bindings: + - ADDED: Exposed new `max_radiuses_map_matching` option from `EngingConfig` options + - Tools: + - ADDED: New osrm-routed `max_radiuses_map_matching` command line flag to optionally set a maximum radius for map matching # 5.14.1 - Changes from 5.14.0 diff --git a/include/engine/engine.hpp b/include/engine/engine.hpp index dd3852914..42a64277e 100644 --- a/include/engine/engine.hpp +++ b/include/engine/engine.hpp @@ -53,12 +53,12 @@ template class Engine final : public EngineInterface { public: explicit Engine(const EngineConfig &config) - : route_plugin(config.max_locations_viaroute, config.max_alternatives), // - table_plugin(config.max_locations_distance_table), // - nearest_plugin(config.max_results_nearest), // - trip_plugin(config.max_locations_trip), // - match_plugin(config.max_locations_map_matching), // - tile_plugin() // + : route_plugin(config.max_locations_viaroute, config.max_alternatives), // + table_plugin(config.max_locations_distance_table), // + nearest_plugin(config.max_results_nearest), // + trip_plugin(config.max_locations_trip), // + match_plugin(config.max_locations_map_matching, config.max_radius_map_matching), // + tile_plugin() // { if (config.use_shared_memory) diff --git a/include/engine/engine_config.hpp b/include/engine/engine_config.hpp index 15cbb19b0..f53db2129 100644 --- a/include/engine/engine_config.hpp +++ b/include/engine/engine_config.hpp @@ -84,6 +84,7 @@ struct EngineConfig final int max_locations_viaroute = -1; int max_locations_distance_table = -1; int max_locations_map_matching = -1; + double max_radius_map_matching = -1.0; int max_results_nearest = -1; int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user bool use_shared_memory = true; diff --git a/include/engine/plugins/match.hpp b/include/engine/plugins/match.hpp index 61a5b92f1..7a6f932d0 100644 --- a/include/engine/plugins/match.hpp +++ b/include/engine/plugins/match.hpp @@ -24,8 +24,9 @@ class MatchPlugin : public BasePlugin using CandidateLists = routing_algorithms::CandidateLists; static const constexpr double RADIUS_MULTIPLIER = 3; - MatchPlugin(const int max_locations_map_matching) - : max_locations_map_matching(max_locations_map_matching) + MatchPlugin(const int max_locations_map_matching, const double max_radius_map_matching) + : max_locations_map_matching(max_locations_map_matching), + max_radius_map_matching(max_radius_map_matching) { } @@ -35,6 +36,7 @@ class MatchPlugin : public BasePlugin private: const int max_locations_map_matching; + const double max_radius_map_matching; }; } } diff --git a/include/nodejs/node_osrm_support.hpp b/include/nodejs/node_osrm_support.hpp index 8452a5499..3e793775f 100644 --- a/include/nodejs/node_osrm_support.hpp +++ b/include/nodejs/node_osrm_support.hpp @@ -186,6 +186,8 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo params->Get(Nan::New("max_locations_map_matching").ToLocalChecked()); auto max_results_nearest = params->Get(Nan::New("max_results_nearest").ToLocalChecked()); auto max_alternatives = params->Get(Nan::New("max_alternatives").ToLocalChecked()); + auto max_radius_map_matching = + params->Get(Nan::New("max_radius_map_matching").ToLocalChecked()); if (!max_locations_trip->IsUndefined() && !max_locations_trip->IsNumber()) { @@ -233,6 +235,9 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo engine_config->max_results_nearest = static_cast(max_results_nearest->NumberValue()); if (max_alternatives->IsNumber()) engine_config->max_alternatives = static_cast(max_alternatives->NumberValue()); + if (max_radius_map_matching->IsNumber()) + engine_config->max_radius_map_matching = + static_cast(max_radius_map_matching->NumberValue()); return engine_config; } diff --git a/src/engine/engine_config.cpp b/src/engine/engine_config.cpp index d516582b9..94f1f0a56 100644 --- a/src/engine/engine_config.cpp +++ b/src/engine/engine_config.cpp @@ -11,12 +11,13 @@ bool EngineConfig::IsValid() const // leads to an empty path const bool all_path_are_empty = storage_config.GetPath("").empty(); - const auto unlimited_or_more_than = [](const int v, const int limit) { + const auto unlimited_or_more_than = [](const auto v, const auto limit) { return v == -1 || v > limit; }; const bool limits_valid = unlimited_or_more_than(max_locations_distance_table, 2) && unlimited_or_more_than(max_locations_map_matching, 2) && + unlimited_or_more_than(max_radius_map_matching, 0) && unlimited_or_more_than(max_locations_trip, 2) && unlimited_or_more_than(max_locations_viaroute, 2) && unlimited_or_more_than(max_results_nearest, 0) && diff --git a/src/engine/plugins/match.cpp b/src/engine/plugins/match.cpp index 7e5d3e976..961b1864f 100644 --- a/src/engine/plugins/match.cpp +++ b/src/engine/plugins/match.cpp @@ -139,6 +139,17 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, return Error("InvalidValue", "Invalid coordinate value.", json_result); } + if (max_radius_map_matching > 0 && std::any_of(parameters.radiuses.begin(), + parameters.radiuses.end(), + [&](const auto &radius) { + if (!radius) + return false; + return *radius > max_radius_map_matching; + })) + { + return Error("TooBig", "Radius search size is too large for map matching.", json_result); + } + // Check for same or increasing timestamps. Impl. note: Incontrast to `sort(first, // last, less_equal)` checking `greater` in reverse meets irreflexive requirements. const auto time_increases_monotonically = std::is_sorted( diff --git a/src/nodejs/node_osrm.cpp b/src/nodejs/node_osrm.cpp index e3bec3f6b..f4a63256b 100644 --- a/src/nodejs/node_osrm.cpp +++ b/src/nodejs/node_osrm.cpp @@ -76,8 +76,9 @@ NAN_MODULE_INIT(Engine::Init) * @param {Number} [options.max_locations_viaroute] Max. locations supported in viaroute query (default: unlimited). * @param {Number} [options.max_locations_distance_table] Max. locations supported in distance table query (default: unlimited). * @param {Number} [options.max_locations_map_matching] Max. locations supported in map-matching query (default: unlimited). + * @param {Number} [options.max_radius_map_matching] Max. radius size supported in map matching query (default: 5). * @param {Number} [options.max_results_nearest] Max. results supported in nearest query (default: unlimited). - * @param {Number} [options.max_alternatives] Max.number of alternatives supported in alternative routes query (default: 3). + * @param {Number} [options.max_alternatives] Max. number of alternatives supported in alternative routes query (default: 3). * * @class OSRM * diff --git a/src/tools/routed.cpp b/src/tools/routed.cpp index c208e13d1..b65ff09f7 100644 --- a/src/tools/routed.cpp +++ b/src/tools/routed.cpp @@ -133,7 +133,10 @@ inline unsigned generateServerProgramOptions(const int argc, "Max. results supported in nearest query") // ("max-alternatives", value(&config.max_alternatives)->default_value(3), - "Max. number of alternatives supported in the MLD route query"); + "Max. number of alternatives supported in the MLD route query") // + ("max-matching-radius", + value(&config.max_radius_map_matching)->default_value(5), + "Max. radius size supported in map matching query"); // hidden options, will be allowed on command line, but will not be shown to the user boost::program_options::options_description hidden_options("Hidden options"); diff --git a/unit_tests/library/limits.cpp b/unit_tests/library/limits.cpp index 368e6224e..a48a7f983 100644 --- a/unit_tests/library/limits.cpp +++ b/unit_tests/library/limits.cpp @@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(test_table_limits) BOOST_CHECK(code == "TooBig"); // per the New-Server API spec } -BOOST_AUTO_TEST_CASE(test_match_limits) +BOOST_AUTO_TEST_CASE(test_match_coordinate_limits) { using namespace osrm; @@ -131,6 +131,38 @@ BOOST_AUTO_TEST_CASE(test_match_limits) BOOST_CHECK(code == "TooBig"); // per the New-Server API spec } +BOOST_AUTO_TEST_CASE(test_match_radiuses_limits) +{ + using namespace osrm; + + EngineConfig config; + config.storage_config = {OSRM_TEST_DATA_DIR "/ch/monaco.osrm"}; + config.use_shared_memory = false; + config.max_radius_map_matching = 2.0; + + OSRM osrm{config}; + + MatchParameters params; + osrm::util::Coordinate coord1 = {osrm::util::FloatLongitude{7.41748809814453}, + osrm::util::FloatLatitude{43.73558473009846}}; + osrm::util::Coordinate coord2 = {osrm::util::FloatLongitude{7.417193055152893}, + osrm::util::FloatLatitude{43.735162245104775}}; + params.coordinates.emplace_back(coord1); + params.coordinates.emplace_back(coord2); + params.radiuses.emplace_back(3.0); + params.radiuses.emplace_back(2.0); + + json::Object result; + + const auto rc = osrm.Match(params, result); + + BOOST_CHECK(rc == Status::Error); + + // Make sure we're not accidentally hitting a guard code path before + const auto code = result.values["code"].get().value; + BOOST_CHECK(code == "TooBig"); // per the New-Server API spec +} + BOOST_AUTO_TEST_CASE(test_nearest_limits) { using namespace osrm; diff --git a/unit_tests/server/parameters_parser.cpp b/unit_tests/server/parameters_parser.cpp index c02f0df1e..7318b72fe 100644 --- a/unit_tests/server/parameters_parser.cpp +++ b/unit_tests/server/parameters_parser.cpp @@ -74,8 +74,6 @@ BOOST_AUTO_TEST_CASE(invalid_route_urls) BOOST_CHECK_EQUAL(testInvalidOptions("1,2;3,4?annotations=true,false"), 24UL); BOOST_CHECK_EQUAL( testInvalidOptions("1,2;3,4?annotations=&overview=simplified"), 20UL); - - // BOOST_CHECK_EQUAL(testInvalidOptions(), ); } BOOST_AUTO_TEST_CASE(invalid_table_urls) @@ -559,6 +557,22 @@ BOOST_AUTO_TEST_CASE(valid_match_urls) CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates); } +BOOST_AUTO_TEST_CASE(invalid_match_urls) +{ + std::vector coords_1 = {{util::FloatLongitude{1}, util::FloatLatitude{2}}, + {util::FloatLongitude{3}, util::FloatLatitude{4}}}; + + MatchParameters reference_1{}; + reference_1.coordinates = coords_1; + auto result_1 = parseParameters("1,2;3,4?radiuses=unlimited;60"); + BOOST_CHECK(result_1); + CHECK_EQUAL_RANGE(reference_1.timestamps, result_1->timestamps); + CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings); + BOOST_CHECK(reference_1.radiuses != result_1->radiuses); + CHECK_EQUAL_RANGE(reference_1.approaches, result_1->approaches); + CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates); +} + BOOST_AUTO_TEST_CASE(valid_nearest_urls) { std::vector coords_1 = {{util::FloatLongitude{1}, util::FloatLatitude{2}}};