Include datasources for each segment in route annotation.
This commit is contained in:
parent
fb4834458e
commit
280b000f07
12
docs/http.md
12
docs/http.md
@ -414,11 +414,23 @@ With `steps=false` and `annotations=true`:
|
||||
"annotation": {
|
||||
"distance": [5,5,10,5,5],
|
||||
"duration": [15,15,40,15,15],
|
||||
"datasources": [1,0,0,0,1],
|
||||
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Annotation data
|
||||
|
||||
Several fields are available as annotations. They are:
|
||||
|
||||
| field | description |
|
||||
|-------------|---------------------------------------------------------------------------------------------------------|
|
||||
| distance | the distance, in metres, between each pair of coordinates |
|
||||
| duration | the duration between each pair of coordinates, in seconds |
|
||||
| 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` |
|
||||
| nodes | the OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates |
|
||||
|
||||
### RouteStep
|
||||
|
||||
A step consists of a maneuver such as a turn or merge, followed
|
||||
|
@ -152,15 +152,15 @@ module.exports = function () {
|
||||
};
|
||||
|
||||
this.annotationList = (instructions) => {
|
||||
function zip(list_1, list_2)
|
||||
function zip(list_1, list_2, list_3)
|
||||
{
|
||||
let pairs = [];
|
||||
let tuples = [];
|
||||
for (let i = 0; i < list_1.length; ++i) {
|
||||
pairs.push([list_1[i], list_2[i]]);
|
||||
tuples.push([list_1[i], list_2[i], list_3[i]]);
|
||||
}
|
||||
return pairs;
|
||||
return tuples;
|
||||
}
|
||||
return instructions.legs.map(l => {return zip(l.annotation.duration, l.annotation.distance).map(p => { return p.join(':'); }).join(','); }).join(',');
|
||||
return instructions.legs.map(l => {return zip(l.annotation.duration, l.annotation.distance, l.annotation.datasources).map(p => { return p.join(':'); }).join(','); }).join(',');
|
||||
};
|
||||
|
||||
this.OSMIDList = (instructions) => {
|
||||
|
@ -4,6 +4,7 @@ Feature: Basic Map Matching
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
Given a grid size of 10 meters
|
||||
Given the extract extra arguments "--generate-edge-lookup"
|
||||
|
||||
Scenario: Testbot - Map matching with outlier that has no candidate
|
||||
Given a grid size of 100 meters
|
||||
@ -118,10 +119,17 @@ Feature: Basic Map Matching
|
||||
| abcdegh | no |
|
||||
| ci | no |
|
||||
|
||||
And the speed file
|
||||
"""
|
||||
1,2,36
|
||||
"""
|
||||
|
||||
And the contract extra arguments "--segment-speed-file speeds.csv"
|
||||
|
||||
When I match I should get
|
||||
| trace | matchings | annotation |
|
||||
| abeh | abcedgh | 1:9.897633,0:0,1:10.008842,1:10.008842,1:10.008842,0:0,2:20.017685,1:10.008842 |
|
||||
| abci | abc,ci | 1:9.897633,0:0,1:10.008842,0:0.111209,1:10.010367 |
|
||||
| trace | matchings | annotation |
|
||||
| abeh | abcedgh | 1:9.897633:1,0:0:0,1:10.008842:0,1:10.008842:0,1:10.008842:0,0:0:0,2:20.017685:0,1:10.008842:0 |
|
||||
| abci | abc,ci | 1:9.897633:1,0:0:0,1:10.008842:0,0:0.111209:0,1:10.010367:0 |
|
||||
|
||||
# The following is the same as the above, but separated for readability (line length)
|
||||
When I match I should get
|
||||
|
@ -207,18 +207,21 @@ class RouteAPI : public BaseAPI
|
||||
util::json::Array durations;
|
||||
util::json::Array distances;
|
||||
util::json::Array nodes;
|
||||
util::json::Array datasources;
|
||||
auto &leg_geometry = leg_geometries[idx];
|
||||
|
||||
durations.values.reserve(leg_geometry.annotations.size());
|
||||
distances.values.reserve(leg_geometry.annotations.size());
|
||||
nodes.values.reserve(leg_geometry.osm_node_ids.size());
|
||||
datasources.values.reserve(leg_geometry.annotations.size());
|
||||
|
||||
std::for_each(
|
||||
leg_geometry.annotations.begin(),
|
||||
leg_geometry.annotations.end(),
|
||||
[this, &durations, &distances](const guidance::LegGeometry::Annotation &step) {
|
||||
[this, &durations, &distances, &datasources](const guidance::LegGeometry::Annotation &step) {
|
||||
durations.values.push_back(step.duration);
|
||||
distances.values.push_back(step.distance);
|
||||
datasources.values.push_back(step.datasource);
|
||||
});
|
||||
std::for_each(leg_geometry.osm_node_ids.begin(),
|
||||
leg_geometry.osm_node_ids.end(),
|
||||
@ -229,6 +232,7 @@ class RouteAPI : public BaseAPI
|
||||
annotation.values["distance"] = std::move(distances);
|
||||
annotation.values["duration"] = std::move(durations);
|
||||
annotation.values["nodes"] = std::move(nodes);
|
||||
annotation.values["datasources"] = std::move(datasources);
|
||||
annotations.push_back(std::move(annotation));
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
||||
geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(
|
||||
reverse_geometry[reverse_geometry.size() - source_node.fwd_segment_position - 1]));
|
||||
|
||||
std::vector<uint8_t> forward_datasource_vector;
|
||||
facade.GetUncompressedDatasources(source_node.forward_packed_geometry_id, forward_datasource_vector);
|
||||
|
||||
|
||||
auto cumulative_distance = 0.;
|
||||
auto current_distance = 0.;
|
||||
auto prev_coordinate = geometry.locations.front();
|
||||
@ -70,7 +74,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
||||
|
||||
prev_coordinate = coordinate;
|
||||
geometry.annotations.emplace_back(
|
||||
LegGeometry::Annotation{current_distance, path_point.duration_until_turn / 10.});
|
||||
LegGeometry::Annotation{current_distance, path_point.duration_until_turn / 10., path_point.datasource_id});
|
||||
geometry.locations.push_back(std::move(coordinate));
|
||||
geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(path_point.turn_via_node));
|
||||
}
|
||||
@ -79,8 +83,12 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
||||
cumulative_distance += current_distance;
|
||||
// segment leading to the target node
|
||||
geometry.segment_distances.push_back(cumulative_distance);
|
||||
|
||||
std::vector<DatasourceID> forward_datasources;
|
||||
facade.GetUncompressedDatasources(target_node.forward_packed_geometry_id, forward_datasources);
|
||||
|
||||
geometry.annotations.emplace_back(
|
||||
LegGeometry::Annotation{current_distance, target_node.forward_weight / 10.});
|
||||
LegGeometry::Annotation{current_distance, target_node.forward_weight / 10., forward_datasources[target_node.fwd_segment_position]});
|
||||
geometry.segment_offsets.push_back(geometry.locations.size());
|
||||
geometry.locations.push_back(target_node.location);
|
||||
|
||||
@ -91,6 +99,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
||||
geometry.osm_node_ids.push_back(
|
||||
facade.GetOSMNodeIDOfNode(forward_geometry[target_node.fwd_segment_position]));
|
||||
|
||||
|
||||
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
|
||||
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());
|
||||
BOOST_ASSERT(geometry.annotations.size() == geometry.locations.size() - 1);
|
||||
|
@ -39,6 +39,7 @@ struct LegGeometry
|
||||
{
|
||||
double distance;
|
||||
double duration;
|
||||
DatasourceID datasource;
|
||||
};
|
||||
std::vector<Annotation> annotations;
|
||||
|
||||
|
@ -33,6 +33,9 @@ struct PathData
|
||||
extractor::TravelMode travel_mode : 4;
|
||||
// entry class of the turn, indicating possibility of turns
|
||||
EntryClassID entry_classid;
|
||||
|
||||
// Source of the speed value on this road segment
|
||||
DatasourceID datasource_id;
|
||||
};
|
||||
|
||||
struct InternalRouteResult
|
||||
|
@ -294,16 +294,18 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
? phantom_node_pair.source_phantom.backward_travel_mode
|
||||
: facade->GetTravelModeForEdgeID(ed.id);
|
||||
|
||||
const auto geometry_index = facade->GetGeometryIndexForEdgeID(ed.id);
|
||||
std::vector<NodeID> id_vector;
|
||||
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id),
|
||||
id_vector);
|
||||
facade->GetUncompressedGeometry(geometry_index, id_vector);
|
||||
BOOST_ASSERT(id_vector.size() > 0);
|
||||
|
||||
std::vector<EdgeWeight> weight_vector;
|
||||
facade->GetUncompressedWeights(facade->GetGeometryIndexForEdgeID(ed.id),
|
||||
weight_vector);
|
||||
facade->GetUncompressedWeights(geometry_index, weight_vector);
|
||||
BOOST_ASSERT(weight_vector.size() > 0);
|
||||
|
||||
std::vector<DatasourceID> datasource_vector;
|
||||
facade->GetUncompressedDatasources(geometry_index, datasource_vector);
|
||||
|
||||
auto total_weight = std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
|
||||
|
||||
BOOST_ASSERT(weight_vector.size() == id_vector.size());
|
||||
@ -329,7 +331,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||
travel_mode,
|
||||
INVALID_ENTRY_CLASSID});
|
||||
INVALID_ENTRY_CLASSID,
|
||||
datasource_vector[i]});
|
||||
}
|
||||
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||
if (facade->hasLaneData(ed.id))
|
||||
@ -343,6 +346,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
std::size_t start_index = 0, end_index = 0;
|
||||
std::vector<unsigned> id_vector;
|
||||
std::vector<EdgeWeight> weight_vector;
|
||||
std::vector<DatasourceID> datasource_vector;
|
||||
const bool is_local_path = (phantom_node_pair.source_phantom.forward_packed_geometry_id ==
|
||||
phantom_node_pair.target_phantom.forward_packed_geometry_id) &&
|
||||
unpacked_path.empty();
|
||||
@ -355,6 +359,9 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
facade->GetUncompressedWeights(
|
||||
phantom_node_pair.target_phantom.reverse_packed_geometry_id, weight_vector);
|
||||
|
||||
facade->GetUncompressedDatasources(
|
||||
phantom_node_pair.target_phantom.reverse_packed_geometry_id, datasource_vector);
|
||||
|
||||
if (is_local_path)
|
||||
{
|
||||
start_index =
|
||||
@ -375,6 +382,9 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
|
||||
facade->GetUncompressedWeights(
|
||||
phantom_node_pair.target_phantom.forward_packed_geometry_id, weight_vector);
|
||||
|
||||
facade->GetUncompressedDatasources(
|
||||
phantom_node_pair.target_phantom.forward_packed_geometry_id, datasource_vector);
|
||||
}
|
||||
|
||||
// Given the following compressed geometry:
|
||||
@ -396,7 +406,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
|
||||
: phantom_node_pair.target_phantom.forward_travel_mode,
|
||||
INVALID_ENTRY_CLASSID});
|
||||
INVALID_ENTRY_CLASSID,
|
||||
datasource_vector[i]});
|
||||
}
|
||||
|
||||
if (unpacked_path.size() > 0)
|
||||
|
@ -83,6 +83,8 @@ static const NameID EMPTY_NAMEID = 0;
|
||||
static const unsigned INVALID_COMPONENTID = 0;
|
||||
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
|
||||
|
||||
using DatasourceID = std::uint8_t;
|
||||
|
||||
struct SegmentID
|
||||
{
|
||||
SegmentID(const NodeID id_, const bool enabled_) : id{id_}, enabled{enabled_}
|
||||
|
@ -335,7 +335,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str
|
||||
&used_weights](const detail::FixedLine &tile_line,
|
||||
const std::uint32_t speed_kmh,
|
||||
const std::size_t duration,
|
||||
const std::uint8_t datasource,
|
||||
const DatasourceID datasource,
|
||||
const std::size_t name,
|
||||
std::int32_t &start_x,
|
||||
std::int32_t &start_y) {
|
||||
|
@ -293,11 +293,12 @@ int Storage::Run()
|
||||
throw util::exception("Could not open " + config.datasource_indexes_path.string() +
|
||||
" for reading.");
|
||||
}
|
||||
std::size_t number_of_compressed_datasources = 0;
|
||||
std::uint64_t number_of_compressed_datasources = 0;
|
||||
if (geometry_datasource_input_stream)
|
||||
{
|
||||
geometry_datasource_input_stream.read(
|
||||
reinterpret_cast<char *>(&number_of_compressed_datasources), sizeof(std::size_t));
|
||||
reinterpret_cast<char *>(&number_of_compressed_datasources),
|
||||
sizeof(number_of_compressed_datasources));
|
||||
}
|
||||
shared_layout_ptr->SetBlockSize<uint8_t>(SharedDataLayout::DATASOURCES_LIST,
|
||||
number_of_compressed_datasources);
|
||||
|
Loading…
Reference in New Issue
Block a user