diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e2ab425945..83fa22dfd38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ -# UNRELEASED +# 5.21.0 + - Changes from 5.20.0: + - Table: + - ADDED: new parameter `scale_factor` which will scale the cell `duration` values by this factor. + +# 5.20.0 - Changes from 5.19.0: - Table: - CHANGED: switch to pre-calculated distances for table responses for large speedup and 10% memory increase. [#5251](https://github.com/Project-OSRM/osrm-backend/pull/5251) diff --git a/docs/http.md b/docs/http.md index e2bcd0141d7..3c12f9fcca0 100644 --- a/docs/http.md +++ b/docs/http.md @@ -238,6 +238,7 @@ In addition to the [general options](#general-options) the following options are |annotations |`duration` (default), `distance`, or `duration,distance`|Return the requested table or tables in response. Note that computing the `distances` table is currently only implemented for CH. If `annotations=distance` or `annotations=duration,distance` is requested when running a MLD router, a `NotImplemented` error will be returned. | |fallback_speed|`double > 0`|If no route found between a source/destination pair, calculate the as-the-crow-flies distance, then use this speed to estimate duration.| |fallback_coordinate|`input` (default), or `snapped`| When using a `fallback_speed`, use the user-supplied coordinate (`input`), or the snapped location (`snapped`) for calculating distances.| +|scale_factor|`double > 0`| Multiply the table `duration` values by this number. Default is 1.0.| Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal** to number of input locations; diff --git a/docs/nodejs/api.md b/docs/nodejs/api.md index 1f9765e0828..b2312ed2dd1 100644 --- a/docs/nodejs/api.md +++ b/docs/nodejs/api.md @@ -131,6 +131,7 @@ tables. Optionally returns distance table. - `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`. - `options.fallback_speed` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Replace `null` responses in result with as-the-crow-flies estimates based on `fallback_speed`. Value is in metres/second. - `options.fallback_coordinate` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Either `input` (default) or `snapped`. If using a `fallback_speed`, use either the user-supplied coordinate (`input`), or the snapped coordinate (`snapped`) for calculating the as-the-crow-flies diestance between two points. + - `options.scale_factor` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Multiply the table duration values in the table by this number for more controlled input into a route optimization solver. - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** **Examples** diff --git a/features/testbot/duration_matrix.feature b/features/testbot/duration_matrix.feature index 629a9f3f92c..929fc90372b 100644 --- a/features/testbot/duration_matrix.feature +++ b/features/testbot/duration_matrix.feature @@ -580,4 +580,48 @@ Feature: Basic Duration Matrix | a | 0 | 30 | 18 | 24 | | b | 30 | 0 | 12 | 18 | | f | 18 | 12 | 0 | 30 | - | 1 | 24 | 18 | 30 | 0 | \ No newline at end of file + | 1 | 24 | 18 | 30 | 0 | + + Scenario: Testbot - Test fallback speeds and scale factor + Given a grid size of 300 meters + Given the extract extra arguments "--small-component-size 4" + Given the query options + | scale_factor | 2 | + | fallback_speed | 5 | + | fallback_coordinate | snapped | + + Given the node map + """ + a b f h 1 + d e g i + """ + + And the ways + | nodes | + | abeda | + | fhigf | + + When I request a travel time matrix I should get + | | a | b | f | 1 | + | a | 0 | 60 | 36 | 48 | + | b | 60 | 0 | 24 | 36 | + | f | 36 | 24 | 0 | 60 | + | 1 | 48 | 36 | 60 | 0 | + + Scenario: Testbot - Travel time matrix of minimal network with scale factor + Given the query options + | scale_factor | 2 | + + Given the node map + """ + a b + """ + + And the ways + | nodes | + | ab | + + When I request a travel time matrix I should get + | | a | b | + | a | 0 | 20 | + | b | 20 | 0 | \ No newline at end of file diff --git a/include/engine/api/table_parameters.hpp b/include/engine/api/table_parameters.hpp index 1bf05ff6e0e..1b4e924a1c4 100644 --- a/include/engine/api/table_parameters.hpp +++ b/include/engine/api/table_parameters.hpp @@ -79,6 +79,8 @@ struct TableParameters : public BaseParameters AnnotationsType annotations = AnnotationsType::Duration; + double scale_factor = 1; + TableParameters() = default; template TableParameters(std::vector sources_, @@ -105,10 +107,13 @@ struct TableParameters : public BaseParameters const AnnotationsType annotations_, double fallback_speed_, FallbackCoordinateType fallback_coordinate_type_, + double scale_factor_, Args... args_) : BaseParameters{std::forward(args_)...}, sources{std::move(sources_)}, destinations{std::move(destinations_)}, fallback_speed{fallback_speed_}, - fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_} + fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_}, + scale_factor{scale_factor_} + { } @@ -135,6 +140,9 @@ struct TableParameters : public BaseParameters if (fallback_speed < 0) return false; + if (scale_factor < 1) + return false; + return true; } }; diff --git a/include/nodejs/node_osrm_support.hpp b/include/nodejs/node_osrm_support.hpp index ba4aba6ceab..11179fc99c3 100644 --- a/include/nodejs/node_osrm_support.hpp +++ b/include/nodejs/node_osrm_support.hpp @@ -1229,6 +1229,24 @@ argumentsToTableParameter(const Nan::FunctionCallbackInfo &args, } } + if (obj->Has(Nan::New("scale_factor").ToLocalChecked())) + { + auto scale_factor = obj->Get(Nan::New("scale_factor").ToLocalChecked()); + + if (!scale_factor->IsNumber()) + { + Nan::ThrowError("scale_factor must be a number"); + return table_parameters_ptr(); + } + else if (scale_factor->NumberValue() < 1) + { + Nan::ThrowError("scale_factor must be > 1"); + return table_parameters_ptr(); + } + + params->scale_factor = static_cast(scale_factor->NumberValue()); + } + return params; } diff --git a/include/server/api/table_parameter_grammar.hpp b/include/server/api/table_parameter_grammar.hpp index 8b6d0ace69a..dc1a073f97a 100644 --- a/include/server/api/table_parameter_grammar.hpp +++ b/include/server/api/table_parameter_grammar.hpp @@ -56,16 +56,20 @@ struct TableParametersGrammar : public BaseParametersGrammar - -('?' > (table_rule(qi::_r1) | base_rule(qi::_r1) | fallback_speed_rule(qi::_r1) | - (qi::lit("fallback_coordinate=") > - fallback_coordinate_type - [ph::bind(&engine::api::TableParameters::fallback_coordinate_type, - qi::_r1) = qi::_1])) % - '&'); + root_rule = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") > + -('?' > (table_rule(qi::_r1) | base_rule(qi::_r1) | scale_factor_rule(qi::_r1) | + fallback_speed_rule(qi::_r1) | + (qi::lit("fallback_coordinate=") > + fallback_coordinate_type + [ph::bind(&engine::api::TableParameters::fallback_coordinate_type, + qi::_r1) = qi::_1])) % + '&'); } TableParametersGrammar(qi::rule &root_rule_) : BaseGrammar(root_rule_) @@ -94,6 +98,7 @@ struct TableParametersGrammar : public BaseParametersGrammar sources_rule; qi::rule destinations_rule; qi::rule fallback_speed_rule; + qi::rule scale_factor_rule; qi::rule size_t_; qi::symbols annotations; qi::rule annotations_list; diff --git a/src/engine/plugins/table.cpp b/src/engine/plugins/table.cpp index 50e41d75b8e..2cf6c76c120 100644 --- a/src/engine/plugins/table.cpp +++ b/src/engine/plugins/table.cpp @@ -96,7 +96,7 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, } // Scan table for null results - if any exist, replace with distance estimates - if (params.fallback_speed > 0) + if (params.fallback_speed > 0 || params.scale_factor > 1.0) { for (std::size_t row = 0; row < num_sources; row++) { @@ -104,7 +104,8 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, { const auto &table_index = row * num_destinations + column; BOOST_ASSERT(table_index < result_tables_pair.first.size()); - if (result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION) + if (params.fallback_speed > 0 && + result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION) { const auto &source = snapped_phantoms[params.sources.empty() ? row : params.sources[row]]; @@ -127,6 +128,9 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, result_tables_pair.second[table_index] = distance_estimate; } } + if (params.scale_factor > 1.0 && result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION){ + result_tables_pair.first[table_index] = result_tables_pair.first[table_index] * (double)params.scale_factor; + } } } } diff --git a/src/server/service/table_service.cpp b/src/server/service/table_service.cpp index 374ea22022c..4694aaf6fb3 100644 --- a/src/server/service/table_service.cpp +++ b/src/server/service/table_service.cpp @@ -61,6 +61,11 @@ std::string getWrongOptionHelp(const engine::api::TableParameters ¶meters) help = "fallback_speed must be > 0"; } + if (parameters.scale_factor < 1) + { + help = "scale_factor must be > 1"; + } + return help; } } // anon. ns diff --git a/test/nodejs/table.js b/test/nodejs/table.js index e8142e6bcc0..13bf99b47d8 100644 --- a/test/nodejs/table.js +++ b/test/nodejs/table.js @@ -260,5 +260,19 @@ tables.forEach(function(annotation) { }); }); + test('table: ' + annotation + ' table in Monaco with scale factor', function(assert) { + assert.plan(1); + var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'}); + var options = { + coordinates: two_test_coordinates, + annotations: [annotation.slice(0,-1)], + scale_factor: 2 + }; + osrm.table(options, function(err, response) { + console.log(response[annotation]); + assert.equal(response[annotation].length, 2); + }); + }); + });