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                              |
 | 
			
		||||
            | 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