Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skipwaypoints #5556

Merged
merged 12 commits into from
Sep 26, 2019
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
33 changes: 20 additions & 13 deletions docs/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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:**

```
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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.
85 changes: 61 additions & 24 deletions features/step_definitions/distance_matrix.js
Original file line number Diff line number Diff line change
@@ -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();

Expand Down Expand Up @@ -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) => {
Expand Down
5 changes: 5 additions & 0 deletions features/step_definitions/routing.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ module.exports = function () {

q.awaitAll(callback);
});

this.Given(/^skip waypoints$/, (callback) => {
this.queryParams['skip_waypoints'] = true;
callback();
});
};
7 changes: 7 additions & 0 deletions features/support/shared_steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
23 changes: 20 additions & 3 deletions features/testbot/basic.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
"""
Expand Down
15 changes: 15 additions & 0 deletions features/testbot/duration_matrix.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions include/engine/api/base_parameters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<util::Coordinate> coordinates_ = {},
Expand Down
5 changes: 4 additions & 1 deletion include/engine/api/match_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ 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";
}
Expand Down
Loading