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": {
|
"annotation": {
|
||||||
"distance": [5,5,10,5,5],
|
"distance": [5,5,10,5,5],
|
||||||
"duration": [15,15,40,15,15],
|
"duration": [15,15,40,15,15],
|
||||||
|
"datasources": [1,0,0,0,1],
|
||||||
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802]
|
"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
|
### RouteStep
|
||||||
|
|
||||||
A step consists of a maneuver such as a turn or merge, followed
|
A step consists of a maneuver such as a turn or merge, followed
|
||||||
|
@ -152,15 +152,15 @@ module.exports = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.annotationList = (instructions) => {
|
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) {
|
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) => {
|
this.OSMIDList = (instructions) => {
|
||||||
|
@ -4,6 +4,7 @@ Feature: Basic Map Matching
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
Given a grid size of 10 meters
|
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
|
Scenario: Testbot - Map matching with outlier that has no candidate
|
||||||
Given a grid size of 100 meters
|
Given a grid size of 100 meters
|
||||||
@ -118,10 +119,17 @@ Feature: Basic Map Matching
|
|||||||
| abcdegh | no |
|
| abcdegh | no |
|
||||||
| ci | 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
|
When I match I should get
|
||||||
| trace | matchings | annotation |
|
| 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 |
|
| 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,0:0,1:10.008842,0:0.111209,1:10.010367 |
|
| 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)
|
# The following is the same as the above, but separated for readability (line length)
|
||||||
When I match I should get
|
When I match I should get
|
||||||
|
@ -207,18 +207,21 @@ class RouteAPI : public BaseAPI
|
|||||||
util::json::Array durations;
|
util::json::Array durations;
|
||||||
util::json::Array distances;
|
util::json::Array distances;
|
||||||
util::json::Array nodes;
|
util::json::Array nodes;
|
||||||
|
util::json::Array datasources;
|
||||||
auto &leg_geometry = leg_geometries[idx];
|
auto &leg_geometry = leg_geometries[idx];
|
||||||
|
|
||||||
durations.values.reserve(leg_geometry.annotations.size());
|
durations.values.reserve(leg_geometry.annotations.size());
|
||||||
distances.values.reserve(leg_geometry.annotations.size());
|
distances.values.reserve(leg_geometry.annotations.size());
|
||||||
nodes.values.reserve(leg_geometry.osm_node_ids.size());
|
nodes.values.reserve(leg_geometry.osm_node_ids.size());
|
||||||
|
datasources.values.reserve(leg_geometry.annotations.size());
|
||||||
|
|
||||||
std::for_each(
|
std::for_each(
|
||||||
leg_geometry.annotations.begin(),
|
leg_geometry.annotations.begin(),
|
||||||
leg_geometry.annotations.end(),
|
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);
|
durations.values.push_back(step.duration);
|
||||||
distances.values.push_back(step.distance);
|
distances.values.push_back(step.distance);
|
||||||
|
datasources.values.push_back(step.datasource);
|
||||||
});
|
});
|
||||||
std::for_each(leg_geometry.osm_node_ids.begin(),
|
std::for_each(leg_geometry.osm_node_ids.begin(),
|
||||||
leg_geometry.osm_node_ids.end(),
|
leg_geometry.osm_node_ids.end(),
|
||||||
@ -229,6 +232,7 @@ class RouteAPI : public BaseAPI
|
|||||||
annotation.values["distance"] = std::move(distances);
|
annotation.values["distance"] = std::move(distances);
|
||||||
annotation.values["duration"] = std::move(durations);
|
annotation.values["duration"] = std::move(durations);
|
||||||
annotation.values["nodes"] = std::move(nodes);
|
annotation.values["nodes"] = std::move(nodes);
|
||||||
|
annotation.values["datasources"] = std::move(datasources);
|
||||||
annotations.push_back(std::move(annotation));
|
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(
|
geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(
|
||||||
reverse_geometry[reverse_geometry.size() - source_node.fwd_segment_position - 1]));
|
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 cumulative_distance = 0.;
|
||||||
auto current_distance = 0.;
|
auto current_distance = 0.;
|
||||||
auto prev_coordinate = geometry.locations.front();
|
auto prev_coordinate = geometry.locations.front();
|
||||||
@ -70,7 +74,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|||||||
|
|
||||||
prev_coordinate = coordinate;
|
prev_coordinate = coordinate;
|
||||||
geometry.annotations.emplace_back(
|
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.locations.push_back(std::move(coordinate));
|
||||||
geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(path_point.turn_via_node));
|
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;
|
cumulative_distance += current_distance;
|
||||||
// segment leading to the target node
|
// segment leading to the target node
|
||||||
geometry.segment_distances.push_back(cumulative_distance);
|
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(
|
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.segment_offsets.push_back(geometry.locations.size());
|
||||||
geometry.locations.push_back(target_node.location);
|
geometry.locations.push_back(target_node.location);
|
||||||
|
|
||||||
@ -91,6 +99,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|||||||
geometry.osm_node_ids.push_back(
|
geometry.osm_node_ids.push_back(
|
||||||
facade.GetOSMNodeIDOfNode(forward_geometry[target_node.fwd_segment_position]));
|
facade.GetOSMNodeIDOfNode(forward_geometry[target_node.fwd_segment_position]));
|
||||||
|
|
||||||
|
|
||||||
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
|
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
|
||||||
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());
|
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());
|
||||||
BOOST_ASSERT(geometry.annotations.size() == geometry.locations.size() - 1);
|
BOOST_ASSERT(geometry.annotations.size() == geometry.locations.size() - 1);
|
||||||
|
@ -39,6 +39,7 @@ struct LegGeometry
|
|||||||
{
|
{
|
||||||
double distance;
|
double distance;
|
||||||
double duration;
|
double duration;
|
||||||
|
DatasourceID datasource;
|
||||||
};
|
};
|
||||||
std::vector<Annotation> annotations;
|
std::vector<Annotation> annotations;
|
||||||
|
|
||||||
|
@ -33,6 +33,9 @@ struct PathData
|
|||||||
extractor::TravelMode travel_mode : 4;
|
extractor::TravelMode travel_mode : 4;
|
||||||
// entry class of the turn, indicating possibility of turns
|
// entry class of the turn, indicating possibility of turns
|
||||||
EntryClassID entry_classid;
|
EntryClassID entry_classid;
|
||||||
|
|
||||||
|
// Source of the speed value on this road segment
|
||||||
|
DatasourceID datasource_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InternalRouteResult
|
struct InternalRouteResult
|
||||||
|
@ -294,16 +294,18 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
? phantom_node_pair.source_phantom.backward_travel_mode
|
? phantom_node_pair.source_phantom.backward_travel_mode
|
||||||
: facade->GetTravelModeForEdgeID(ed.id);
|
: facade->GetTravelModeForEdgeID(ed.id);
|
||||||
|
|
||||||
|
const auto geometry_index = facade->GetGeometryIndexForEdgeID(ed.id);
|
||||||
std::vector<NodeID> id_vector;
|
std::vector<NodeID> id_vector;
|
||||||
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id),
|
facade->GetUncompressedGeometry(geometry_index, id_vector);
|
||||||
id_vector);
|
|
||||||
BOOST_ASSERT(id_vector.size() > 0);
|
BOOST_ASSERT(id_vector.size() > 0);
|
||||||
|
|
||||||
std::vector<EdgeWeight> weight_vector;
|
std::vector<EdgeWeight> weight_vector;
|
||||||
facade->GetUncompressedWeights(facade->GetGeometryIndexForEdgeID(ed.id),
|
facade->GetUncompressedWeights(geometry_index, weight_vector);
|
||||||
weight_vector);
|
|
||||||
BOOST_ASSERT(weight_vector.size() > 0);
|
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);
|
auto total_weight = std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
|
||||||
|
|
||||||
BOOST_ASSERT(weight_vector.size() == id_vector.size());
|
BOOST_ASSERT(weight_vector.size() == id_vector.size());
|
||||||
@ -329,7 +331,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||||
travel_mode,
|
travel_mode,
|
||||||
INVALID_ENTRY_CLASSID});
|
INVALID_ENTRY_CLASSID,
|
||||||
|
datasource_vector[i]});
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(unpacked_path.size() > 0);
|
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||||
if (facade->hasLaneData(ed.id))
|
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::size_t start_index = 0, end_index = 0;
|
||||||
std::vector<unsigned> id_vector;
|
std::vector<unsigned> id_vector;
|
||||||
std::vector<EdgeWeight> weight_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 ==
|
const bool is_local_path = (phantom_node_pair.source_phantom.forward_packed_geometry_id ==
|
||||||
phantom_node_pair.target_phantom.forward_packed_geometry_id) &&
|
phantom_node_pair.target_phantom.forward_packed_geometry_id) &&
|
||||||
unpacked_path.empty();
|
unpacked_path.empty();
|
||||||
@ -355,6 +359,9 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
facade->GetUncompressedWeights(
|
facade->GetUncompressedWeights(
|
||||||
phantom_node_pair.target_phantom.reverse_packed_geometry_id, weight_vector);
|
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)
|
if (is_local_path)
|
||||||
{
|
{
|
||||||
start_index =
|
start_index =
|
||||||
@ -375,6 +382,9 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
|
|
||||||
facade->GetUncompressedWeights(
|
facade->GetUncompressedWeights(
|
||||||
phantom_node_pair.target_phantom.forward_packed_geometry_id, weight_vector);
|
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:
|
// Given the following compressed geometry:
|
||||||
@ -396,7 +406,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||||
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
|
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
|
||||||
: phantom_node_pair.target_phantom.forward_travel_mode,
|
: phantom_node_pair.target_phantom.forward_travel_mode,
|
||||||
INVALID_ENTRY_CLASSID});
|
INVALID_ENTRY_CLASSID,
|
||||||
|
datasource_vector[i]});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unpacked_path.size() > 0)
|
if (unpacked_path.size() > 0)
|
||||||
|
@ -83,6 +83,8 @@ static const NameID EMPTY_NAMEID = 0;
|
|||||||
static const unsigned INVALID_COMPONENTID = 0;
|
static const unsigned INVALID_COMPONENTID = 0;
|
||||||
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
|
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
|
||||||
|
|
||||||
|
using DatasourceID = std::uint8_t;
|
||||||
|
|
||||||
struct SegmentID
|
struct SegmentID
|
||||||
{
|
{
|
||||||
SegmentID(const NodeID id_, const bool enabled_) : id{id_}, enabled{enabled_}
|
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,
|
&used_weights](const detail::FixedLine &tile_line,
|
||||||
const std::uint32_t speed_kmh,
|
const std::uint32_t speed_kmh,
|
||||||
const std::size_t duration,
|
const std::size_t duration,
|
||||||
const std::uint8_t datasource,
|
const DatasourceID datasource,
|
||||||
const std::size_t name,
|
const std::size_t name,
|
||||||
std::int32_t &start_x,
|
std::int32_t &start_x,
|
||||||
std::int32_t &start_y) {
|
std::int32_t &start_y) {
|
||||||
|
@ -293,11 +293,12 @@ int Storage::Run()
|
|||||||
throw util::exception("Could not open " + config.datasource_indexes_path.string() +
|
throw util::exception("Could not open " + config.datasource_indexes_path.string() +
|
||||||
" for reading.");
|
" for reading.");
|
||||||
}
|
}
|
||||||
std::size_t number_of_compressed_datasources = 0;
|
std::uint64_t number_of_compressed_datasources = 0;
|
||||||
if (geometry_datasource_input_stream)
|
if (geometry_datasource_input_stream)
|
||||||
{
|
{
|
||||||
geometry_datasource_input_stream.read(
|
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,
|
shared_layout_ptr->SetBlockSize<uint8_t>(SharedDataLayout::DATASOURCES_LIST,
|
||||||
number_of_compressed_datasources);
|
number_of_compressed_datasources);
|
||||||
|
Loading…
Reference in New Issue
Block a user