From 10c1b38139b77ebf39dfb61e146e7745d7901a56 Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 16 Sep 2019 11:24:35 +0300 Subject: [PATCH 01/12] Added new base parameter 'skip_waypoints' --- include/engine/api/base_parameters.hpp | 3 +++ include/server/api/base_parameters_grammar.hpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/include/engine/api/base_parameters.hpp b/include/engine/api/base_parameters.hpp index 4e3628459f5..e7a49378df1 100644 --- a/include/engine/api/base_parameters.hpp +++ b/include/engine/api/base_parameters.hpp @@ -87,6 +87,9 @@ struct BaseParameters // Adds hints to response which can be included in subsequent requests, see `hints` above. bool generate_hints = true; + // Remove waypoints array from the response. + bool skip_waypoints = false; + SnappingType snapping = SnappingType::Default; BaseParameters(const std::vector coordinates_ = {}, diff --git a/include/server/api/base_parameters_grammar.hpp b/include/server/api/base_parameters_grammar.hpp index dc196ae2b0a..0c579120211 100644 --- a/include/server/api/base_parameters_grammar.hpp +++ b/include/server/api/base_parameters_grammar.hpp @@ -152,6 +152,10 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar qi::lit("generate_hints=") > qi::bool_[ph::bind(&engine::api::BaseParameters::generate_hints, qi::_r1) = qi::_1]; + skip_waypoints_rule = + qi::lit("skip_waypoints=") > + qi::bool_[ph::bind(&engine::api::BaseParameters::skip_waypoints, qi::_r1) = qi::_1]; + bearings_rule = qi::lit("bearings=") > (-(qi::short_ > ',' > qi::short_))[ph::bind(add_bearing, qi::_r1, qi::_1)] % ';'; @@ -183,6 +187,7 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar | hints_rule(qi::_r1) // | bearings_rule(qi::_r1) // | generate_hints_rule(qi::_r1) // + | skip_waypoints_rule(qi::_r1) // | approach_rule(qi::_r1) // | exclude_rule(qi::_r1) // | snapping_rule(qi::_r1); @@ -203,6 +208,7 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar qi::rule hints_rule; qi::rule generate_hints_rule; + qi::rule skip_waypoints_rule; qi::rule approach_rule; qi::rule exclude_rule; From 1b47242a5878595b40ec0893d5b532088d0074eb Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 16 Sep 2019 11:44:08 +0300 Subject: [PATCH 02/12] Implemented 'skip_waypoints' for the 'Nearest' service. It actually makes no sence, as the only output on the 'Nearest' service is a list of wypoints. On the other hand it can be used now as a simple health check. --- include/engine/api/nearest_api.hpp | 76 +++++++++++++++++------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/include/engine/api/nearest_api.hpp b/include/engine/api/nearest_api.hpp index a10d424b23b..525fa2dbe12 100644 --- a/include/engine/api/nearest_api.hpp +++ b/include/engine/api/nearest_api.hpp @@ -6,6 +6,7 @@ #include "engine/api/json_factory.hpp" #include "engine/phantom_node.hpp" +#include "base_result.hpp" #include @@ -54,25 +55,30 @@ class NearestAPI final : public BaseAPI data_version_string = fb_result.CreateString(data_timestamp); } - std::vector> waypoints; - waypoints.resize(phantom_nodes.front().size()); - std::transform(phantom_nodes.front().begin(), - phantom_nodes.front().end(), - waypoints.begin(), - [this, &fb_result](const PhantomNodeWithDistance &phantom_with_distance) { - auto &phantom_node = phantom_with_distance.phantom_node; + flatbuffers::Offset>> waypoints_vector; + if (!parameters.skip_waypoints) { + std::vector> waypoints; + waypoints.resize(phantom_nodes.front().size()); + std::transform(phantom_nodes.front().begin(), + phantom_nodes.front().end(), + waypoints.begin(), + [this, &fb_result](const PhantomNodeWithDistance &phantom_with_distance) { + auto &phantom_node = phantom_with_distance.phantom_node; - auto node_values = MakeNodes(phantom_node); - fbresult::Uint64Pair nodes{node_values.first, node_values.second}; + auto node_values = MakeNodes(phantom_node); + fbresult::Uint64Pair nodes{node_values.first, node_values.second}; - auto waypoint = MakeWaypoint(fb_result, phantom_node); - waypoint.add_nodes(&nodes); + auto waypoint = MakeWaypoint(fb_result, phantom_node); + waypoint.add_nodes(&nodes); - return waypoint.Finish(); - }); + return waypoint.Finish(); + }); + + waypoints_vector = fb_result.CreateVector(waypoints); + } - auto waypoints_vector = fb_result.CreateVector(waypoints); fbresult::FBResultBuilder response(fb_result); + response.add_waypoints(waypoints_vector); if (data_version_string) { @@ -83,28 +89,30 @@ class NearestAPI final : public BaseAPI void MakeResponse(const std::vector> &phantom_nodes, util::json::Object &response) const { - util::json::Array waypoints; - waypoints.values.resize(phantom_nodes.front().size()); - std::transform(phantom_nodes.front().begin(), - phantom_nodes.front().end(), - waypoints.values.begin(), - [this](const PhantomNodeWithDistance &phantom_with_distance) { - auto &phantom_node = phantom_with_distance.phantom_node; - auto waypoint = MakeWaypoint(phantom_node); - - util::json::Array nodes; - - auto node_values = MakeNodes(phantom_node); - - nodes.values.push_back(node_values.first); - nodes.values.push_back(node_values.second); - waypoint.values["nodes"] = std::move(nodes); - - return waypoint; - }); + if (!parameters.skip_waypoints) { + util::json::Array waypoints; + waypoints.values.resize(phantom_nodes.front().size()); + std::transform(phantom_nodes.front().begin(), + phantom_nodes.front().end(), + waypoints.values.begin(), + [this](const PhantomNodeWithDistance &phantom_with_distance) { + auto &phantom_node = phantom_with_distance.phantom_node; + auto waypoint = MakeWaypoint(phantom_node); + + util::json::Array nodes; + + auto node_values = MakeNodes(phantom_node); + + nodes.values.push_back(node_values.first); + nodes.values.push_back(node_values.second); + waypoint.values["nodes"] = std::move(nodes); + + return waypoint; + }); + response.values["waypoints"] = std::move(waypoints); + } response.values["code"] = "Ok"; - response.values["waypoints"] = std::move(waypoints); } const NearestParameters ¶meters; From 600f48e15a2de36547b99018ead15813e5fffb56 Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 16 Sep 2019 13:54:25 +0300 Subject: [PATCH 03/12] Implemented 'skip_waypoints' support in 'Route', 'Trip', 'Match' services. --- include/engine/api/match_api.hpp | 4 +++- include/engine/api/route_api.hpp | 9 +++++++-- include/engine/api/trip_api.hpp | 4 +++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/engine/api/match_api.hpp b/include/engine/api/match_api.hpp index 3fb95523b01..19db1ad3a0b 100644 --- a/include/engine/api/match_api.hpp +++ b/include/engine/api/match_api.hpp @@ -83,7 +83,9 @@ class MatchAPI final : public RouteAPI route.values["confidence"] = sub_matchings[index].confidence; routes.values.push_back(std::move(route)); } - response.values["tracepoints"] = MakeTracepoints(sub_matchings); + if (!parameters.skip_waypoints) { + response.values["tracepoints"] = MakeTracepoints(sub_matchings); + } response.values["matchings"] = std::move(routes); response.values["code"] = "Ok"; } diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 6450e6b56e3..ae6d394ee6e 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -109,7 +109,9 @@ class RouteAPI : public BaseAPI route.target_traversed_in_reverse)); } - response.values["waypoints"] = BaseAPI::MakeWaypoints(all_start_end_points); + if (!parameters.skip_waypoints) { + response.values["waypoints"] = BaseAPI::MakeWaypoints(all_start_end_points); + } response.values["routes"] = std::move(jsRoutes); response.values["code"] = "Ok"; auto data_timestamp = facade.GetTimestamp(); @@ -140,7 +142,10 @@ class RouteAPI : public BaseAPI } auto routes_vector = fb_result.CreateVector(routes); - auto waypoints_vector = getWaypoints(); + flatbuffers::Offset>> waypoints_vector; + if (!parameters.skip_waypoints) { + waypoints_vector = getWaypoints(); + } fbresult::FBResultBuilder response(fb_result); response.add_routes(routes_vector); diff --git a/include/engine/api/trip_api.hpp b/include/engine/api/trip_api.hpp index 518d0ec7d6f..1a28d301163 100644 --- a/include/engine/api/trip_api.hpp +++ b/include/engine/api/trip_api.hpp @@ -81,7 +81,9 @@ class TripAPI final : public RouteAPI sub_routes[index].target_traversed_in_reverse); routes.values.push_back(std::move(route)); } - response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms); + if (!parameters.skip_waypoints) { + response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms); + } response.values["trips"] = std::move(routes); response.values["code"] = "Ok"; } From 660c0cc6029f15a5bef33ab9718ade5b9b386de9 Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 16 Sep 2019 14:32:53 +0300 Subject: [PATCH 04/12] Implemented 'skip_waypoints' for the 'Table' service. --- include/engine/api/nearest_api.hpp | 2 +- include/engine/api/route_api.hpp | 1 + include/engine/api/table_api.hpp | 33 ++++++++++++++++++++++-------- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/include/engine/api/nearest_api.hpp b/include/engine/api/nearest_api.hpp index 525fa2dbe12..7f2d519cace 100644 --- a/include/engine/api/nearest_api.hpp +++ b/include/engine/api/nearest_api.hpp @@ -2,11 +2,11 @@ #define ENGINE_API_NEAREST_API_HPP #include "engine/api/base_api.hpp" +#include "engine/api/base_result.hpp" #include "engine/api/nearest_parameters.hpp" #include "engine/api/json_factory.hpp" #include "engine/phantom_node.hpp" -#include "base_result.hpp" #include diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index ae6d394ee6e..ee1cd8d392b 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -3,6 +3,7 @@ #include "extractor/maneuver_override.hpp" #include "engine/api/base_api.hpp" +#include "engine/api/base_result.hpp" #include "engine/api/json_factory.hpp" #include "engine/api/route_parameters.hpp" diff --git a/include/engine/api/table_api.hpp b/include/engine/api/table_api.hpp index 7b6cd1c48e1..bdb9db7a967 100644 --- a/include/engine/api/table_api.hpp +++ b/include/engine/api/table_api.hpp @@ -2,6 +2,7 @@ #define ENGINE_API_TABLE_HPP #include "engine/api/base_api.hpp" +#include "engine/api/base_result.hpp" #include "engine/api/json_factory.hpp" #include "engine/api/table_parameters.hpp" @@ -83,24 +84,32 @@ class TableAPI final : public BaseAPI flatbuffers::Offset>> sources; if (parameters.sources.empty()) { - sources = MakeWaypoints(fb_result, phantoms); + if (!parameters.skip_waypoints) { + sources = MakeWaypoints(fb_result, phantoms); + } number_of_sources = phantoms.size(); } else { - sources = MakeWaypoints(fb_result, phantoms, parameters.sources); + if (!parameters.skip_waypoints) { + sources = MakeWaypoints(fb_result, phantoms, parameters.sources); + } } flatbuffers::Offset>> destinations; if (parameters.destinations.empty()) { - destinations = MakeWaypoints(fb_result, phantoms); + if (!parameters.skip_waypoints) { + destinations = MakeWaypoints(fb_result, phantoms); + } number_of_destinations = phantoms.size(); } else { - destinations = MakeWaypoints(fb_result, phantoms, parameters.destinations); + if (!parameters.skip_waypoints) { + destinations = MakeWaypoints(fb_result, phantoms, parameters.destinations); + } } boost::optional>> durations = boost::none; @@ -162,22 +171,30 @@ class TableAPI final : public BaseAPI // symmetric case if (parameters.sources.empty()) { - response.values["sources"] = MakeWaypoints(phantoms); + if (!parameters.skip_waypoints) { + response.values["sources"] = MakeWaypoints(phantoms); + } number_of_sources = phantoms.size(); } else { - response.values["sources"] = MakeWaypoints(phantoms, parameters.sources); + if (!parameters.skip_waypoints) { + response.values["sources"] = MakeWaypoints(phantoms, parameters.sources); + } } if (parameters.destinations.empty()) { - response.values["destinations"] = MakeWaypoints(phantoms); + if (!parameters.skip_waypoints) { + response.values["destinations"] = MakeWaypoints(phantoms); + } number_of_destinations = phantoms.size(); } else { - response.values["destinations"] = MakeWaypoints(phantoms, parameters.destinations); + if (!parameters.skip_waypoints) { + response.values["destinations"] = MakeWaypoints(phantoms, parameters.destinations); + } } if (parameters.annotations & TableParameters::AnnotationsType::Duration) From a5127539ebb0256704d2f6e981561adb735c819f Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 16 Sep 2019 15:59:35 +0300 Subject: [PATCH 05/12] Added unit tests of 'skip_waypoints' option to the Nearest/Route/Table services. --- unit_tests/library/nearest.cpp | 44 +++++++++++++++- unit_tests/library/route.cpp | 86 +++++++++++++++++++++++++++++++ unit_tests/library/table.cpp | 93 ++++++++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+), 1 deletion(-) diff --git a/unit_tests/library/nearest.cpp b/unit_tests/library/nearest.cpp index 9119c104283..899a35c8ea8 100644 --- a/unit_tests/library/nearest.cpp +++ b/unit_tests/library/nearest.cpp @@ -43,6 +43,27 @@ BOOST_AUTO_TEST_CASE(test_nearest_response) } } +BOOST_AUTO_TEST_CASE(test_nearest_response_skip_waypoints) +{ + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + + using namespace osrm; + + NearestParameters params; + params.skip_waypoints = true; + params.coordinates.push_back(get_dummy_location()); + + engine::api::ResultT result = json::Object(); + const auto rc = osrm.Nearest(params, result); + BOOST_REQUIRE(rc == Status::Ok); + + auto &json_result = result.get(); + const auto code = json_result.values.at("code").get().value; + BOOST_CHECK_EQUAL(code, "Ok"); + + BOOST_CHECK(json_result.values.find("waypoints") == json_result.values.end()); +} + BOOST_AUTO_TEST_CASE(test_nearest_response_no_coordinates) { auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); @@ -118,7 +139,7 @@ BOOST_AUTO_TEST_CASE(test_nearest_response_for_location_in_small_component) } } -BOOST_AUTO_TEST_CASE(test_nearest_fb_serilization) +BOOST_AUTO_TEST_CASE(test_nearest_fb_serialization) { auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); @@ -147,6 +168,27 @@ BOOST_AUTO_TEST_CASE(test_nearest_fb_serilization) } } +BOOST_AUTO_TEST_CASE(test_nearest_fb_serialization_skip_waypoints) +{ + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + + using namespace osrm; + + NearestParameters params; + params.skip_waypoints=true; + params.coordinates.push_back(get_dummy_location()); + + engine::api::ResultT result = flatbuffers::FlatBufferBuilder(); + const auto rc = osrm.Nearest(params, result); + BOOST_REQUIRE(rc == Status::Ok); + + auto &fb_result = result.get(); + auto fb = engine::api::fbresult::GetFBResult(fb_result.GetBufferPointer()); + BOOST_CHECK(!fb->error()); + + BOOST_CHECK(fb->waypoints() == nullptr); +} + BOOST_AUTO_TEST_CASE(test_nearest_fb_error) { auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); diff --git a/unit_tests/library/route.cpp b/unit_tests/library/route.cpp index b00c782be04..49187f00f47 100644 --- a/unit_tests/library/route.cpp +++ b/unit_tests/library/route.cpp @@ -270,6 +270,53 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates) } } +BOOST_AUTO_TEST_CASE(test_route_same_coordinates_no_waypoints) +{ + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + + using namespace osrm; + + RouteParameters params; + params.skip_waypoints = true; + params.steps = true; + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + + engine::api::ResultT result = json::Object(); + const auto rc = osrm.Route(params, result); + BOOST_CHECK(rc == Status::Ok); + + auto &json_result = result.get(); + const auto code = json_result.values.at("code").get().value; + BOOST_CHECK_EQUAL(code, "Ok"); + + BOOST_CHECK(json_result.values.find("waypoints") == json_result.values.end()); + + const auto &routes = json_result.values.at("routes").get().values; + BOOST_REQUIRE_GT(routes.size(), 0); + + for (const auto &route : routes) + { + const auto &route_object = route.get(); + + const auto distance = route_object.values.at("distance").get().value; + BOOST_CHECK_EQUAL(distance, 0); + + const auto duration = route_object.values.at("duration").get().value; + BOOST_CHECK_EQUAL(duration, 0); + + // geometries=polyline by default + const auto geometry = route_object.values.at("geometry").get().value; + BOOST_CHECK(!geometry.empty()); + + const auto &legs = route_object.values.at("legs").get().values; + BOOST_CHECK(!legs.empty()); + + //The rest of legs contents is verified by test_route_same_coordinates + } +} + BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component) { auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); @@ -575,4 +622,43 @@ BOOST_AUTO_TEST_CASE(test_route_serialize_fb) } } +BOOST_AUTO_TEST_CASE(test_route_serialize_fb_skip_waypoints) +{ + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + + using namespace osrm; + + RouteParameters params; + params.skip_waypoints = true; + params.steps = true; + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + + engine::api::ResultT result = flatbuffers::FlatBufferBuilder(); + const auto rc = osrm.Route(params, result); + BOOST_CHECK(rc == Status::Ok); + + auto &fb_result = result.get(); + auto fb = engine::api::fbresult::GetFBResult(fb_result.GetBufferPointer()); + BOOST_CHECK(!fb->error()); + + BOOST_CHECK(fb->waypoints() == nullptr); + + BOOST_CHECK(fb->routes() != nullptr); + const auto routes = fb->routes(); + BOOST_REQUIRE_GT(routes->size(), 0); + + for (const auto &route : *routes) + { + BOOST_CHECK_EQUAL(route->distance(), 0); + BOOST_CHECK_EQUAL(route->duration(), 0); + + const auto &legs = route->legs(); + BOOST_CHECK(legs->size() > 0); + + // Rest of the content is verified by test_route_serialize_fb + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/unit_tests/library/table.cpp b/unit_tests/library/table.cpp index 11186455845..33d57b0fb52 100644 --- a/unit_tests/library/table.cpp +++ b/unit_tests/library/table.cpp @@ -77,6 +77,57 @@ BOOST_AUTO_TEST_CASE(test_table_three_coords_one_source_one_dest_matrix) } } +BOOST_AUTO_TEST_CASE(test_table_three_coords_one_source_one_dest_matrix_no_waypoints) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + + TableParameters params; + params.skip_waypoints = true; + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + params.sources.push_back(0); + params.destinations.push_back(2); + params.annotations = TableParameters::AnnotationsType::All; + + engine::api::ResultT result = json::Object(); + + const auto rc = osrm.Table(params, result); + + auto &json_result = result.get(); + BOOST_CHECK(rc == Status::Ok || rc == Status::Error); + const auto code = json_result.values.at("code").get().value; + BOOST_CHECK_EQUAL(code, "Ok"); + + // check that returned durations error is expected size and proportions + // this test expects a 1x1 matrix + const auto &durations_array = json_result.values.at("durations").get().values; + BOOST_CHECK_EQUAL(durations_array.size(), params.sources.size()); + for (unsigned int i = 0; i < durations_array.size(); i++) + { + const auto durations_matrix = durations_array[i].get().values; + BOOST_CHECK_EQUAL(durations_matrix.size(), + params.sources.size() * params.destinations.size()); + } + + // check that returned distances error is expected size and proportions + // this test expects a 1x1 matrix + const auto &distances_array = json_result.values.at("distances").get().values; + BOOST_CHECK_EQUAL(distances_array.size(), params.sources.size()); + for (unsigned int i = 0; i < distances_array.size(); i++) + { + const auto distances_matrix = distances_array[i].get().values; + BOOST_CHECK_EQUAL(distances_matrix.size(), + params.sources.size() * params.destinations.size()); + } + + // waypoint arrays should be missing + BOOST_CHECK(json_result.values.find("destinations") == json_result.values.end()); + BOOST_CHECK(json_result.values.find("sources") == json_result.values.end()); +} + BOOST_AUTO_TEST_CASE(test_table_three_coords_one_source_matrix) { using namespace osrm; @@ -247,4 +298,46 @@ BOOST_AUTO_TEST_CASE(test_table_serialiaze_fb) } } +BOOST_AUTO_TEST_CASE(test_table_serialiaze_fb_no_waypoints) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + + TableParameters params; + params.skip_waypoints = true; + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + params.sources.push_back(0); + params.destinations.push_back(2); + params.annotations = TableParameters::AnnotationsType::All; + + engine::api::ResultT result = flatbuffers::FlatBufferBuilder(); + + const auto rc = osrm.Table(params, result); + + BOOST_CHECK(rc == Status::Ok || rc == Status::Error); + + auto &fb_result = result.get(); + auto fb = engine::api::fbresult::GetFBResult(fb_result.GetBufferPointer()); + BOOST_CHECK(!fb->error()); + BOOST_CHECK(fb->table() != nullptr); + + // check that returned durations error is expected size and proportions + // this test expects a 1x1 matrix + BOOST_CHECK(fb->table()->durations() != nullptr); + auto durations_array = fb->table()->durations(); + BOOST_CHECK_EQUAL(durations_array->size(), params.sources.size() * params.destinations.size()); + + // check that returned distances error is expected size and proportions + // this test expects a 1x1 matrix + BOOST_CHECK(fb->table()->distances() != nullptr); + auto distances_array = fb->table()->distances(); + BOOST_CHECK_EQUAL(distances_array->size(), params.sources.size() * params.destinations.size()); + + BOOST_CHECK(fb->table()->destinations() == nullptr); + BOOST_CHECK(fb->waypoints() == nullptr); +} + BOOST_AUTO_TEST_SUITE_END() From a9d4e28e383ed8ca667a1e1ac4ccd2aa12bff038 Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 16 Sep 2019 16:39:09 +0300 Subject: [PATCH 06/12] Added unit test for flatbuffers serialization of Match/Trip responses. --- unit_tests/library/match.cpp | 41 +++++++++++++++++++++++++++++++++ unit_tests/library/trip.cpp | 44 ++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/unit_tests/library/match.cpp b/unit_tests/library/match.cpp index c7c3b1eae7f..e510d998caf 100644 --- a/unit_tests/library/match.cpp +++ b/unit_tests/library/match.cpp @@ -118,4 +118,45 @@ BOOST_AUTO_TEST_CASE(test_match_split) } } +BOOST_AUTO_TEST_CASE(test_match_fb_serialization) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + + MatchParameters params; + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + + engine::api::ResultT result = flatbuffers::FlatBufferBuilder(); + + const auto rc = osrm.Match(params, result); + BOOST_CHECK(rc == Status::Ok); + + auto &fb_result = result.get(); + auto fb = engine::api::fbresult::GetFBResult(fb_result.GetBufferPointer()); + + BOOST_CHECK(!fb->error()); + + BOOST_CHECK(fb->waypoints() != nullptr); + const auto waypoints = fb->waypoints(); + BOOST_CHECK(waypoints->size() == params.coordinates.size()); + + BOOST_CHECK(fb->routes() != nullptr); + const auto matchings = fb->routes(); + const auto &number_of_matchings = matchings->size(); + + for (const auto &waypoint : *waypoints) + { + BOOST_CHECK(waypoint_check(waypoint)); + const auto matchings_index = waypoint->matchings_index(); + const auto waypoint_index = waypoint->waypoint_index(); + const auto &route_legs = matchings->operator[](matchings_index)->legs(); + + BOOST_CHECK_LT(waypoint_index, route_legs->size() + 1); + BOOST_CHECK_LT(matchings_index, number_of_matchings); + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/unit_tests/library/trip.cpp b/unit_tests/library/trip.cpp index bfe1108c508..b58dcac0a29 100644 --- a/unit_tests/library/trip.cpp +++ b/unit_tests/library/trip.cpp @@ -4,6 +4,7 @@ #include "coordinates.hpp" #include "fixture.hpp" +#include #include "osrm/trip_parameters.hpp" #include "osrm/coordinate.hpp" @@ -422,4 +423,47 @@ BOOST_AUTO_TEST_CASE(test_tfse_legal_parameters) CheckOk(osrm, params); } +BOOST_AUTO_TEST_CASE(test_roundtrip_response_fb_serialization) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + const auto locations = get_locations_in_small_component(); + + TripParameters params; + params.coordinates.push_back(locations.at(0)); + params.coordinates.push_back(locations.at(1)); + params.coordinates.push_back(locations.at(2)); + + engine::api::ResultT result = flatbuffers::FlatBufferBuilder(); + const auto rc = osrm.Trip(params, result); + BOOST_CHECK(rc == Status::Ok); + + auto &fb_result = result.get(); + auto fb = engine::api::fbresult::GetFBResult(fb_result.GetBufferPointer()); + + BOOST_CHECK(!fb->error()); + + BOOST_CHECK(fb->waypoints() != nullptr); + const auto waypoints = fb->waypoints(); + BOOST_CHECK(waypoints->size() == params.coordinates.size()); + + BOOST_CHECK(fb->routes() != nullptr); + const auto trips = fb->routes(); + BOOST_CHECK_EQUAL(trips->size(), 1); + + for (const auto &waypoint : *waypoints) + { + const auto longitude = waypoint->location()->longitude(); + const auto latitude = waypoint->location()->latitude(); + BOOST_CHECK(longitude >= -180. && longitude <= 180.); + BOOST_CHECK(latitude >= -90. && latitude <= 90.); + + const auto trip = waypoint->trips_index(); + const auto pos = waypoint->waypoint_index(); + BOOST_CHECK(trip < trips->size()); + BOOST_CHECK(pos < waypoints->size()); + } +} + BOOST_AUTO_TEST_SUITE_END() From fa5567e66997d3f33efa6ddac866833775c3ca23 Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 16 Sep 2019 17:07:45 +0300 Subject: [PATCH 07/12] Added unit tests for 'skip waypoints' on Trip/Match services --- unit_tests/library/match.cpp | 49 ++++++++++++++++++++++++++++++++++++ unit_tests/library/trip.cpp | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/unit_tests/library/match.cpp b/unit_tests/library/match.cpp index e510d998caf..cce5138cd7e 100644 --- a/unit_tests/library/match.cpp +++ b/unit_tests/library/match.cpp @@ -65,6 +65,30 @@ BOOST_AUTO_TEST_CASE(test_match) } } +BOOST_AUTO_TEST_CASE(test_match_skip_waypoints) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + + MatchParameters params; + params.skip_waypoints = true; + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + + engine::api::ResultT result = json::Object(); + + const auto rc = osrm.Match(params, result); + + auto &json_result = result.get(); + BOOST_CHECK(rc == Status::Ok || rc == Status::Error); + const auto code = json_result.values.at("code").get().value; + BOOST_CHECK_EQUAL(code, "Ok"); + + BOOST_CHECK(json_result.values.find("tracepoints") == json_result.values.end()); +} + BOOST_AUTO_TEST_CASE(test_match_split) { using namespace osrm; @@ -159,4 +183,29 @@ BOOST_AUTO_TEST_CASE(test_match_fb_serialization) } } +BOOST_AUTO_TEST_CASE(test_match_fb_serialization_skip_waypoints) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + + MatchParameters params; + params.skip_waypoints = true; + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + params.coordinates.push_back(get_dummy_location()); + + engine::api::ResultT result = flatbuffers::FlatBufferBuilder(); + + const auto rc = osrm.Match(params, result); + BOOST_CHECK(rc == Status::Ok); + + auto &fb_result = result.get(); + auto fb = engine::api::fbresult::GetFBResult(fb_result.GetBufferPointer()); + + BOOST_CHECK(!fb->error()); + + BOOST_CHECK(fb->waypoints() == nullptr); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/unit_tests/library/trip.cpp b/unit_tests/library/trip.cpp index b58dcac0a29..d519661ef76 100644 --- a/unit_tests/library/trip.cpp +++ b/unit_tests/library/trip.cpp @@ -58,6 +58,30 @@ BOOST_AUTO_TEST_CASE(test_roundtrip_response_for_locations_in_small_component) } } +BOOST_AUTO_TEST_CASE(test_roundtrip_response_for_locations_in_small_component_skip_waypoints) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + const auto locations = get_locations_in_small_component(); + + TripParameters params; + params.skip_waypoints = true; + params.coordinates.push_back(locations.at(0)); + params.coordinates.push_back(locations.at(1)); + params.coordinates.push_back(locations.at(2)); + + engine::api::ResultT result = json::Object(); + const auto rc = osrm.Trip(params, result); + BOOST_CHECK(rc == Status::Ok); + + auto &json_result = result.get(); + const auto code = json_result.values.at("code").get().value; + BOOST_CHECK_EQUAL(code, "Ok"); + + BOOST_CHECK(json_result.values.find("waypoints") == json_result.values.end()); +} + BOOST_AUTO_TEST_CASE(test_roundtrip_response_for_locations_in_big_component) { using namespace osrm; @@ -466,4 +490,29 @@ BOOST_AUTO_TEST_CASE(test_roundtrip_response_fb_serialization) } } +BOOST_AUTO_TEST_CASE(test_roundtrip_response_fb_serialization_skip_waypoints) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + const auto locations = get_locations_in_small_component(); + + TripParameters params; + params.skip_waypoints = true; + params.coordinates.push_back(locations.at(0)); + params.coordinates.push_back(locations.at(1)); + params.coordinates.push_back(locations.at(2)); + + engine::api::ResultT result = flatbuffers::FlatBufferBuilder(); + const auto rc = osrm.Trip(params, result); + BOOST_CHECK(rc == Status::Ok); + + auto &fb_result = result.get(); + auto fb = engine::api::fbresult::GetFBResult(fb_result.GetBufferPointer()); + + BOOST_CHECK(!fb->error()); + + BOOST_CHECK(fb->waypoints() == nullptr); +} + BOOST_AUTO_TEST_SUITE_END() From e97ec13064201799332eaf3d7501b9c9b45d6ded Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 16 Sep 2019 17:13:33 +0300 Subject: [PATCH 08/12] Formatted the sources --- include/engine/api/match_api.hpp | 3 +- include/engine/api/nearest_api.hpp | 32 +++++++++++-------- include/engine/api/route_api.hpp | 9 ++++-- include/engine/api/table_api.hpp | 24 +++++++++----- include/engine/api/trip_api.hpp | 3 +- .../server/api/base_parameters_grammar.hpp | 4 +-- unit_tests/library/nearest.cpp | 2 +- unit_tests/library/route.cpp | 2 +- unit_tests/library/trip.cpp | 2 +- 9 files changed, 49 insertions(+), 32 deletions(-) diff --git a/include/engine/api/match_api.hpp b/include/engine/api/match_api.hpp index 19db1ad3a0b..d005c3a321e 100644 --- a/include/engine/api/match_api.hpp +++ b/include/engine/api/match_api.hpp @@ -83,7 +83,8 @@ class MatchAPI final : public RouteAPI route.values["confidence"] = sub_matchings[index].confidence; routes.values.push_back(std::move(route)); } - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { response.values["tracepoints"] = MakeTracepoints(sub_matchings); } response.values["matchings"] = std::move(routes); diff --git a/include/engine/api/nearest_api.hpp b/include/engine/api/nearest_api.hpp index 7f2d519cace..6e0788ef427 100644 --- a/include/engine/api/nearest_api.hpp +++ b/include/engine/api/nearest_api.hpp @@ -55,24 +55,27 @@ class NearestAPI final : public BaseAPI data_version_string = fb_result.CreateString(data_timestamp); } - flatbuffers::Offset>> waypoints_vector; - if (!parameters.skip_waypoints) { + flatbuffers::Offset>> + waypoints_vector; + if (!parameters.skip_waypoints) + { std::vector> waypoints; waypoints.resize(phantom_nodes.front().size()); - std::transform(phantom_nodes.front().begin(), - phantom_nodes.front().end(), - waypoints.begin(), - [this, &fb_result](const PhantomNodeWithDistance &phantom_with_distance) { - auto &phantom_node = phantom_with_distance.phantom_node; + std::transform( + phantom_nodes.front().begin(), + phantom_nodes.front().end(), + waypoints.begin(), + [this, &fb_result](const PhantomNodeWithDistance &phantom_with_distance) { + auto &phantom_node = phantom_with_distance.phantom_node; - auto node_values = MakeNodes(phantom_node); - fbresult::Uint64Pair nodes{node_values.first, node_values.second}; + auto node_values = MakeNodes(phantom_node); + fbresult::Uint64Pair nodes{node_values.first, node_values.second}; - auto waypoint = MakeWaypoint(fb_result, phantom_node); - waypoint.add_nodes(&nodes); + auto waypoint = MakeWaypoint(fb_result, phantom_node); + waypoint.add_nodes(&nodes); - return waypoint.Finish(); - }); + return waypoint.Finish(); + }); waypoints_vector = fb_result.CreateVector(waypoints); } @@ -89,7 +92,8 @@ class NearestAPI final : public BaseAPI void MakeResponse(const std::vector> &phantom_nodes, util::json::Object &response) const { - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { util::json::Array waypoints; waypoints.values.resize(phantom_nodes.front().size()); std::transform(phantom_nodes.front().begin(), diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index ee1cd8d392b..8adac88efac 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -110,7 +110,8 @@ class RouteAPI : public BaseAPI route.target_traversed_in_reverse)); } - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { response.values["waypoints"] = BaseAPI::MakeWaypoints(all_start_end_points); } response.values["routes"] = std::move(jsRoutes); @@ -143,8 +144,10 @@ class RouteAPI : public BaseAPI } auto routes_vector = fb_result.CreateVector(routes); - flatbuffers::Offset>> waypoints_vector; - if (!parameters.skip_waypoints) { + flatbuffers::Offset>> + waypoints_vector; + if (!parameters.skip_waypoints) + { waypoints_vector = getWaypoints(); } diff --git a/include/engine/api/table_api.hpp b/include/engine/api/table_api.hpp index bdb9db7a967..4fe21b66583 100644 --- a/include/engine/api/table_api.hpp +++ b/include/engine/api/table_api.hpp @@ -84,14 +84,16 @@ class TableAPI final : public BaseAPI flatbuffers::Offset>> sources; if (parameters.sources.empty()) { - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { sources = MakeWaypoints(fb_result, phantoms); } number_of_sources = phantoms.size(); } else { - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { sources = MakeWaypoints(fb_result, phantoms, parameters.sources); } } @@ -100,14 +102,16 @@ class TableAPI final : public BaseAPI destinations; if (parameters.destinations.empty()) { - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { destinations = MakeWaypoints(fb_result, phantoms); } number_of_destinations = phantoms.size(); } else { - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { destinations = MakeWaypoints(fb_result, phantoms, parameters.destinations); } } @@ -171,28 +175,32 @@ class TableAPI final : public BaseAPI // symmetric case if (parameters.sources.empty()) { - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { response.values["sources"] = MakeWaypoints(phantoms); } number_of_sources = phantoms.size(); } else { - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { response.values["sources"] = MakeWaypoints(phantoms, parameters.sources); } } if (parameters.destinations.empty()) { - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { response.values["destinations"] = MakeWaypoints(phantoms); } number_of_destinations = phantoms.size(); } else { - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { response.values["destinations"] = MakeWaypoints(phantoms, parameters.destinations); } } diff --git a/include/engine/api/trip_api.hpp b/include/engine/api/trip_api.hpp index 1a28d301163..a38275f543c 100644 --- a/include/engine/api/trip_api.hpp +++ b/include/engine/api/trip_api.hpp @@ -81,7 +81,8 @@ class TripAPI final : public RouteAPI sub_routes[index].target_traversed_in_reverse); routes.values.push_back(std::move(route)); } - if (!parameters.skip_waypoints) { + if (!parameters.skip_waypoints) + { response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms); } response.values["trips"] = std::move(routes); diff --git a/include/server/api/base_parameters_grammar.hpp b/include/server/api/base_parameters_grammar.hpp index 0c579120211..31bc4a71752 100644 --- a/include/server/api/base_parameters_grammar.hpp +++ b/include/server/api/base_parameters_grammar.hpp @@ -153,8 +153,8 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar qi::bool_[ph::bind(&engine::api::BaseParameters::generate_hints, qi::_r1) = qi::_1]; skip_waypoints_rule = - qi::lit("skip_waypoints=") > - qi::bool_[ph::bind(&engine::api::BaseParameters::skip_waypoints, qi::_r1) = qi::_1]; + qi::lit("skip_waypoints=") > + qi::bool_[ph::bind(&engine::api::BaseParameters::skip_waypoints, qi::_r1) = qi::_1]; bearings_rule = qi::lit("bearings=") > diff --git a/unit_tests/library/nearest.cpp b/unit_tests/library/nearest.cpp index 899a35c8ea8..5f4568dc88d 100644 --- a/unit_tests/library/nearest.cpp +++ b/unit_tests/library/nearest.cpp @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(test_nearest_fb_serialization_skip_waypoints) using namespace osrm; NearestParameters params; - params.skip_waypoints=true; + params.skip_waypoints = true; params.coordinates.push_back(get_dummy_location()); engine::api::ResultT result = flatbuffers::FlatBufferBuilder(); diff --git a/unit_tests/library/route.cpp b/unit_tests/library/route.cpp index 49187f00f47..a2984530bae 100644 --- a/unit_tests/library/route.cpp +++ b/unit_tests/library/route.cpp @@ -313,7 +313,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_no_waypoints) const auto &legs = route_object.values.at("legs").get().values; BOOST_CHECK(!legs.empty()); - //The rest of legs contents is verified by test_route_same_coordinates + // The rest of legs contents is verified by test_route_same_coordinates } } diff --git a/unit_tests/library/trip.cpp b/unit_tests/library/trip.cpp index d519661ef76..e41e14aee6c 100644 --- a/unit_tests/library/trip.cpp +++ b/unit_tests/library/trip.cpp @@ -4,8 +4,8 @@ #include "coordinates.hpp" #include "fixture.hpp" -#include #include "osrm/trip_parameters.hpp" +#include #include "osrm/coordinate.hpp" #include "osrm/engine_config.hpp" From 6214f1655272df3e5bb5fe1a20d8d0a8226b76d8 Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 16 Sep 2019 17:26:57 +0300 Subject: [PATCH 09/12] Updated http API documentation with `skip_waypoints`. --- docs/http.md | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/docs/http.md b/docs/http.md index 4052f1eac75..346e6e2eca8 100644 --- a/docs/http.md +++ b/docs/http.md @@ -29,15 +29,16 @@ To pass parameters to each location some options support an array like encoding: **Request options** -| Option | Values | Description | -|----------------|--------------------------------------------------------|-------------------------------------------------------------------------------------------------------| -|bearings |`{bearing};{bearing}[;{bearing} ...]` |Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | -|radiuses |`{radius};{radius}[;{radius} ...]` |Limits the search to given radius in meters. | -|generate\_hints |`true` (default), `false` |Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. | -|hints |`{hint};{hint}[;{hint} ...]` |Hint from previous request to derive position in street network. | -|approaches |`{approach};{approach}[;{approach} ...]` |Keep waypoints on curb side. | -|exclude |`{class}[,{class}]` |Additive list of classes to avoid, order does not matter. | -|snapping |`default` (default), `any` |Default snapping avoids is_startpoint (see profile) edges, `any` will snap to any edge in the graph | +| Option | Values | Description | +|----------------|--------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|bearings |`{bearing};{bearing}[;{bearing} ...]` |Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | +|radiuses |`{radius};{radius}[;{radius} ...]` |Limits the search to given radius in meters. | +|generate\_hints |`true` (default), `false` |Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. | +|hints |`{hint};{hint}[;{hint} ...]` |Hint from previous request to derive position in street network. | +|approaches |`{approach};{approach}[;{approach} ...]` |Keep waypoints on curb side. | +|exclude |`{class}[,{class}]` |Additive list of classes to avoid, order does not matter. | +|snapping |`default` (default), `any` |Default snapping avoids is_startpoint (see profile) edges, `any` will snap to any edge in the graph | +|skip_waypoints |`true`, `false` (default) |Removes waypoints from the response. Waypoints are still calculated, but not serialized. Could be useful in case you are interested in some other part of response and do not want to transfer waste data. | Where the elements follow the following format: @@ -128,6 +129,9 @@ In addition to the [general options](#general-options) the following options are |------------|------------------------------|----------------------------------------------------| |number |`integer >= 1` (default `1`) |Number of nearest segments that should be returned. | +As `waypoints` is a single thing, returned byt that service, using it with option `skip_waypoints` set to `true` is quite useless, but still +possible. In that case only `code` field will be returned. + **Response** - `code` if the request was successful `Ok` otherwise see the service dependent and general status codes. @@ -207,8 +211,8 @@ In addition to the [general options](#general-options) the following options are |annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| -|continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. | -|waypoints | `{index};{index};{index}...` |Treats input coordinates indicated by given indices as waypoints in returned Match object. Default is to treat all input coordinates as waypoints. | +|continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. | +|waypoints | `{index};{index};{index}...` |Treats input coordinates indicated by given indices as waypoints in returned Match object. Default is to treat all input coordinates as waypoints. | \* Please note that even if alternative routes are requested, a result cannot be guaranteed. @@ -257,6 +261,8 @@ In addition to the [general options](#general-options) the following options are Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal** to number of input locations; +With `skip_waypoints` set to `true`, both `sources` and `destinations` arrays will be skipped. + **Example:** ``` @@ -967,7 +973,7 @@ Root object is the only object, available from a 'raw' `flatbuffers` buffer. It - `error`: `bool` Marks response as erroneous. Erroneus response should include `code` field set, all the other field may not present. - `code`: `Error` Error description object, only present, when `error` is `true` -- `waypoints`: `[Waypoint]` Array of `Waypoint` objects. Should present for every service call. Table service will put `sources` array here. +- `waypoints`: `[Waypoint]` Array of `Waypoint` objects. Should present for every service call, unless `skip_waypoints` is set to `true`. Table service will put `sources` array here. - `routes`: `[RouteObject]` Array of `RouteObject` objects. May be empty or absent. Should present for Route/Trip/Match services call. - `table`: `Table` Table object, may absent. Should be present in case of Table service call. @@ -1112,6 +1118,7 @@ Almost same as `json` Table object. The main difference is that 'sources' field used instead. All the other differences follow: - `durations`: `[float]` Flat representation of a durations matrix. Element at row;col can be adressed as [row * cols + col] -- `destinations`: `[float]` Flat representation of a destinations matrix. Element at row;col can be adressed as [row * cols + col] +- `distances`: `[float]` Flat representation of a destinations matrix. Element at row;col can be adressed as [row * cols + col] +- `destinations`: `[Waypoint]` Array of `Waypoint` objects. Will be `null` if `skip_waypoints` will be set to `true` - `rows`: `ushort` Number of rows in durations/destinations matrices. - `cols`: `ushort` Number of cols in durations/destinations matrices. From 50a1c8a08d2c3584132bac03b0acd0e311620d3e Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Tue, 17 Sep 2019 17:32:09 +0300 Subject: [PATCH 10/12] Added flatbuffers support to Table service cucumber tests --- features/step_definitions/distance_matrix.js | 85 ++++++++++++++------ features/testbot/duration_matrix.feature | 15 ++++ 2 files changed, 76 insertions(+), 24 deletions(-) diff --git a/features/step_definitions/distance_matrix.js b/features/step_definitions/distance_matrix.js index 594268d50fa..37de07a269d 100644 --- a/features/step_definitions/distance_matrix.js +++ b/features/step_definitions/distance_matrix.js @@ -1,27 +1,38 @@ var util = require('util'); +var flatbuffers = require('../support/flatbuffers').flatbuffers; +var FBResult = require('../support/fbresult_generated').osrm.engine.api.fbresult.FBResult; + module.exports = function () { const durationsRegex = new RegExp(/^I request a travel time matrix I should get$/); const distancesRegex = new RegExp(/^I request a travel distance matrix I should get$/); const estimatesRegex = new RegExp(/^I request a travel time matrix I should get estimates for$/); + const durationsRegexFb = new RegExp(/^I request a travel time matrix with flatbuffers I should get$/); + const distancesRegexFb = new RegExp(/^I request a travel distance matrix with flatbuffers I should get$/); const DURATIONS_NO_ROUTE = 2147483647; // MAX_INT const DISTANCES_NO_ROUTE = 3.40282e+38; // MAX_FLOAT - this.When(durationsRegex, function(table, callback) {tableParse.call(this, table, DURATIONS_NO_ROUTE, 'durations', callback);}.bind(this)); - this.When(distancesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'distances', callback);}.bind(this)); - this.When(estimatesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'fallback_speed_cells', callback);}.bind(this)); + const FORMAT_JSON = 'json'; + const FORMAT_FB = 'flatbuffers'; + + this.When(durationsRegex, function(table, callback) {tableParse.call(this, table, DURATIONS_NO_ROUTE, 'durations', FORMAT_JSON, callback);}.bind(this)); + this.When(distancesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'distances', FORMAT_JSON, callback);}.bind(this)); + this.When(estimatesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'fallback_speed_cells', FORMAT_JSON, callback);}.bind(this)); + this.When(durationsRegexFb, function(table, callback) {tableParse.call(this, table, DURATIONS_NO_ROUTE, 'durations', FORMAT_FB, callback);}.bind(this)); + this.When(distancesRegexFb, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'distances', FORMAT_FB, callback);}.bind(this)); }; const durationsParse = function(v) { return isNaN(parseInt(v)); }; const distancesParse = function(v) { return isNaN(parseFloat(v)); }; const estimatesParse = function(v) { return isNaN(parseFloat(v)); }; -function tableParse(table, noRoute, annotation, callback) { +function tableParse(table, noRoute, annotation, format, callback) { const parse = annotation == 'distances' ? distancesParse : (annotation == 'durations' ? durationsParse : estimatesParse); const params = this.queryParams; params.annotations = ['durations','fallback_speed_cells'].indexOf(annotation) !== -1 ? 'duration' : 'distance'; + params.output = format; var tableRows = table.raw(); @@ -62,27 +73,53 @@ function tableParse(table, noRoute, annotation, callback) { if (err) return callback(err); if (!response.body.length) return callback(new Error('Invalid response body')); - var json = JSON.parse(response.body); - - var result = {}; - if (annotation === 'fallback_speed_cells') { - result = table.raw().map(row => row.map(() => '')); - json[annotation].forEach(pair => { - result[pair[0]+1][pair[1]+1] = 'Y'; - }); - result = result.slice(1).map(row => { - var hashes = {}; - row.slice(1).forEach((v,i) => { - hashes[tableRows[0][i+1]] = v; + var result = []; + if (format === 'json') { + var json = JSON.parse(response.body); + + if (annotation === 'fallback_speed_cells') { + result = table.raw().map(row => row.map(() => '')); + json[annotation].forEach(pair => { + result[pair[0]+1][pair[1]+1] = 'Y'; }); - return hashes; - }); - } else { - result = json[annotation].map(row => { - var hashes = {}; - row.forEach((v, i) => { hashes[tableRows[0][i+1]] = parse(v) ? '' : v; }); - return hashes; - }); + result = result.slice(1).map(row => { + var hashes = {}; + row.slice(1).forEach((v,i) => { + hashes[tableRows[0][i+1]] = v; + }); + return hashes; + }); + } else { + result = json[annotation].map(row => { + var hashes = {}; + row.forEach((v, i) => { hashes[tableRows[0][i+1]] = parse(v) ? '' : v; }); + return hashes; + }); + } + } else { //flatbuffers + var body = response.body; + var bytes = new Uint8Array(body.length); + for (var indx = 0; indx < body.length; ++indx) { + bytes[indx] = body.charCodeAt(indx); + } + var buf = new flatbuffers.ByteBuffer(bytes); + var fb = FBResult.getRootAsFBResult(buf); + + var matrix; + if (annotation === 'durations') { + matrix = fb.table().durationsArray(); + } + if (annotation === 'distances') { + matrix = fb.table().distancesArray(); + } + var cols = fb.table().cols(); + var rows = fb.table().rows(); + for (let r = 0; r < rows; ++r) { + result[r]={}; + for(let c=0; c < cols; ++c) { + result[r][tableRows[0][c+1]] = matrix[r*cols + c]; + } + } } var testRow = (row, ri, cb) => { diff --git a/features/testbot/duration_matrix.feature b/features/testbot/duration_matrix.feature index dce1b177c08..94e0a64144c 100644 --- a/features/testbot/duration_matrix.feature +++ b/features/testbot/duration_matrix.feature @@ -21,6 +21,21 @@ Feature: Basic Duration Matrix | a | 0 | 10 | | b | 10 | 0 | + Scenario: Testbot - Travel time matrix of minimal network requested with flatbuffer format + Given the node map + """ + a b + """ + + And the ways + | nodes | + | ab | + + When I request a travel time matrix with flatbuffers I should get + | | a | b | + | a | 0 | 10 | + | b | 10 | 0 | + @ch Scenario: Testbot - Travel time matrix of minimal network with toll exclude Given the query options From a6097cdc013c5b344df9275b427946d6c4194283 Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Tue, 17 Sep 2019 17:56:27 +0300 Subject: [PATCH 11/12] Changelog updated --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f524becbfd1..85d75a3014f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - ADDED: new API parameter - `snapping=any|default` to allow snapping to previously unsnappable edges [#5361](https://github.com/Project-OSRM/osrm-backend/pull/5361) - ADDED: keepalive support to the osrm-routed HTTP server [#5518](https://github.com/Project-OSRM/osrm-backend/pull/5518) - ADDED: flatbuffers output format support [#5513](https://github.com/Project-OSRM/osrm-backend/pull/5513) + - ADDED: Global 'skip_waypoints' option [#5556](https://github.com/Project-OSRM/osrm-backend/pull/5556) - Routing: - CHANGED: allow routing past `barrier=arch` [#5352](https://github.com/Project-OSRM/osrm-backend/pull/5352) - CHANGED: default car weight was reduced to 2000 kg. [#5371](https://github.com/Project-OSRM/osrm-backend/pull/5371) From d25a5309424c64139fd8285f1e7718a92da283de Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Mon, 23 Sep 2019 11:38:33 +0300 Subject: [PATCH 12/12] Added cucumber test for skip_waypoint feature --- features/step_definitions/routing.js | 5 +++++ features/support/shared_steps.js | 7 +++++++ features/testbot/basic.feature | 23 ++++++++++++++++++++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/features/step_definitions/routing.js b/features/step_definitions/routing.js index c3e679aa5b3..136add5ef29 100644 --- a/features/step_definitions/routing.js +++ b/features/step_definitions/routing.js @@ -12,4 +12,9 @@ module.exports = function () { q.awaitAll(callback); }); + + this.Given(/^skip waypoints$/, (callback) => { + this.queryParams['skip_waypoints'] = true; + callback(); + }); }; diff --git a/features/support/shared_steps.js b/features/support/shared_steps.js index 20fc0cf71a2..0eeda27902c 100644 --- a/features/support/shared_steps.js +++ b/features/support/shared_steps.js @@ -155,6 +155,13 @@ module.exports = function () { if (headers.has('locations')){ got.locations = (locations || '').trim(); } + if (headers.has('waypoints_count')) { + if ('waypoints' in json) { + got.waypoints_count = json.waypoints.length; + } else{ + got.waypoints_count = 0; + } + } /* if (headers.has('approaches')){ got.approaches = (approaches || '').trim(); diff --git a/features/testbot/basic.feature b/features/testbot/basic.feature index 0041a133eb3..9224cd46911 100644 --- a/features/testbot/basic.feature +++ b/features/testbot/basic.feature @@ -17,9 +17,9 @@ Feature: Basic Routing | ab | When I route I should get - | from | to | route | data_version | - | a | b | ab,ab | | - | b | a | ab,ab | | + | from | to | route | data_version | waypoints_count | + | a | b | ab,ab | | 2 | + | b | a | ab,ab | | 2 | Scenario: Data_version test Given the node map @@ -38,6 +38,23 @@ Feature: Basic Routing | a | b | ab,ab | cucumber_data_version | | b | a | ab,ab | cucumber_data_version | + Scenario: Skip_waypoints test + Given the node map + """ + a b + """ + + And skip waypoints + + And the ways + | nodes | + | ab | + + When I route I should get + | from | to | route | waypoints_count | + | a | b | ab,ab | 0 | + | b | a | ab,ab | 0 | + Scenario: Routing in between two nodes of way Given the node map """