Return datasource names along with datasource annotation (#4973)
* Add new `datasource_names` annotation that returns the string version of the `datasources` annotation
This commit is contained in:
parent
8a63ad9b4b
commit
b5a4ffed96
@ -23,6 +23,8 @@
|
||||
- ADDED: Add documentation about OSM node ids in nearest service response [#4436](https://github.com/Project-OSRM/osrm-backend/pull/4436)
|
||||
- Performance
|
||||
- FIXED: Speed up response time when lots of legs exist and geojson is used with `steps=true` [#4936](https://github.com/Project-OSRM/osrm-backend/pull/4936)
|
||||
- Misc:
|
||||
- ADDED: expose name for datasource annotations as metadata [#4973](https://github.com/Project-OSRM/osrm-backend/pull/4973)
|
||||
|
||||
# 5.16.0
|
||||
- Changes from 5.15.2:
|
||||
|
@ -547,6 +547,7 @@ With `steps=false` and `annotations=true`:
|
||||
"distance": [5,5,10,5,5],
|
||||
"duration": [15,15,40,15,15],
|
||||
"datasources": [1,0,0,0,1],
|
||||
"metadata": { "datasource_names": ["traffic","lua profile","lua profile","lua profile","traffic"] },
|
||||
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
|
||||
"speed": [0.3, 0.3, 0.3, 0.3, 0.3]
|
||||
}
|
||||
@ -561,10 +562,12 @@ Annotation of the whole route leg with fine-grained information about each segme
|
||||
|
||||
- `distance`: The distance, in metres, between each pair of coordinates
|
||||
- `duration`: The duration between each pair of coordinates, in seconds. Does not include the duration of any turns.
|
||||
- `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract`
|
||||
- `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract` or `osrm-customize`. String-like names are in the `metadata.datasource_names` array.
|
||||
- `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates
|
||||
- `weight`: The weights between each pair of coordinates. Does not include any turn costs.
|
||||
- `speed`: Convenience field, calculation of `distance / duration` rounded to one decimal place
|
||||
- `metadata`: Metadata related to other annotations
|
||||
- `datasource_names`: The names of the datasources used for the speed between each pair of coordinates. `lua profile` is the default profile, other values arethe filenames supplied via `--segment-speed-file` to `osrm-contract` or `osrm-customize`
|
||||
|
||||
#### Example
|
||||
|
||||
@ -573,6 +576,7 @@ Annotation of the whole route leg with fine-grained information about each segme
|
||||
"distance": [5,5,10,5,5],
|
||||
"duration": [15,15,40,15,15],
|
||||
"datasources": [1,0,0,0,1],
|
||||
"metadata": { "datasource_names": ["traffic","lua profile","lua profile","lua profile","traffic"] },
|
||||
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
|
||||
"weight": [15,15,40,15,15]
|
||||
}
|
||||
|
@ -199,14 +199,26 @@ module.exports = function () {
|
||||
|
||||
var merged = {};
|
||||
instructions.legs.map(l => {
|
||||
Object.keys(l.annotation).forEach(a => {
|
||||
Object.keys(l.annotation).filter(a => !a.match(/metadata/)).forEach(a => {
|
||||
if (!merged[a]) merged[a] = [];
|
||||
merged[a].push(l.annotation[a].join(':'));
|
||||
});
|
||||
if (l.annotation.metadata) {
|
||||
merged.metadata = {};
|
||||
Object.keys(l.annotation.metadata).forEach(a => {
|
||||
if (!merged.metadata[a]) merged.metadata[a] = [];
|
||||
merged.metadata[a].push(l.annotation.metadata[a].join(':'));
|
||||
});
|
||||
}
|
||||
});
|
||||
Object.keys(merged).map(a => {
|
||||
Object.keys(merged).filter(k => !k.match(/metadata/)).map(a => {
|
||||
merged[a] = merged[a].join(',');
|
||||
});
|
||||
if (merged.metadata) {
|
||||
Object.keys(merged.metadata).map(a => {
|
||||
merged.metadata[a] = merged.metadata[a].join(',');
|
||||
});
|
||||
}
|
||||
return merged;
|
||||
};
|
||||
|
||||
|
@ -158,7 +158,8 @@ module.exports = function () {
|
||||
// if header matches 'a:*', parse out the values for *
|
||||
// and return in that header
|
||||
headers.forEach((k) => {
|
||||
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
|
||||
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed' ];
|
||||
let metadata_whitelist = [ 'datasource_names' ];
|
||||
if (k.match(/^a:/)) {
|
||||
let a_type = k.slice(2);
|
||||
if (whitelist.indexOf(a_type) == -1)
|
||||
@ -166,6 +167,13 @@ module.exports = function () {
|
||||
if (annotation && !annotation[a_type])
|
||||
return cb(new Error('Annotation not found in response', a_type));
|
||||
got[k] = annotation && annotation[a_type] || '';
|
||||
} else if (k.match(/^am:/)) {
|
||||
let a_type = k.slice(3);
|
||||
if (metadata_whitelist.indexOf(a_type) == -1)
|
||||
return cb(new Error('Unrecognized annotation field', a_type));
|
||||
if (annotation && (!annotation.metadata || !annotation.metadata[a_type]))
|
||||
return cb(new Error('Annotation not found in response', a_type));
|
||||
got[k] = (annotation && annotation.metadata && annotation.metadata[a_type]) || '';
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -60,6 +60,39 @@ Feature: Annotations
|
||||
| a | i | abcdefghi,abcdefghi | 1:0:1:0:1:0:0:0 | 50:10:50:10:50:10:10:10 |
|
||||
| i | a | abcdefghi,abcdefghi | 0:1:0:0:0:0:0:1 | 10:50:10:10:10:10:10:50 |
|
||||
|
||||
Scenario: datasource name annotations
|
||||
Given the profile "testbot"
|
||||
|
||||
And the node map
|
||||
"""
|
||||
a b c
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abc |
|
||||
|
||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||
|
||||
And the speed file
|
||||
"""
|
||||
1,2,180,1
|
||||
2,1,180,1
|
||||
"""
|
||||
|
||||
And the query options
|
||||
| annotations | datasources |
|
||||
|
||||
# Note - the source names here are specific to how the tests are constructed,
|
||||
# so if this test is moved around (changes line number) or support code
|
||||
# changes how the filenames are generated, this test will need to be updated
|
||||
When I route I should get
|
||||
| from | to | route | am:datasource_names |
|
||||
| a | c | abc,abc | lua profile:63_datasource_name_annotations_speeds |
|
||||
| c | a | abc,abc | lua profile:63_datasource_name_annotations_speeds |
|
||||
|
||||
|
||||
Scenario: Speed annotations should handle zero segments
|
||||
Given the profile "testbot"
|
||||
|
||||
|
@ -324,6 +324,23 @@ class RouteAPI : public BaseAPI
|
||||
}
|
||||
annotation.values["nodes"] = std::move(nodes);
|
||||
}
|
||||
// Add any supporting metadata, if needed
|
||||
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
|
||||
{
|
||||
const auto MAX_DATASOURCE_ID = 255u;
|
||||
util::json::Object metadata;
|
||||
util::json::Array datasource_names;
|
||||
for (auto i = 0u; i < MAX_DATASOURCE_ID; i++)
|
||||
{
|
||||
const auto name = facade.GetDatasourceName(i);
|
||||
// Length of 0 indicates the first empty name, so we can stop here
|
||||
if (name.size() == 0)
|
||||
break;
|
||||
datasource_names.values.push_back(std::string(facade.GetDatasourceName(i)));
|
||||
}
|
||||
metadata.values["datasource_names"] = datasource_names;
|
||||
annotation.values["metadata"] = metadata;
|
||||
}
|
||||
|
||||
annotations.push_back(std::move(annotation));
|
||||
}
|
||||
|
@ -453,7 +453,7 @@ BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property)
|
||||
.values["annotation"]
|
||||
.get<json::Object>()
|
||||
.values;
|
||||
BOOST_CHECK_EQUAL(annotations.size(), 5);
|
||||
BOOST_CHECK_EQUAL(annotations.size(), 6);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue
Block a user