Skip to content

Commit

Permalink
When matching, ignore 'is_startpoint' propert, snap to any edge (#5297)
Browse files Browse the repository at this point in the history
Includes all edges in the rtree, but adds an `is_startpoint` flag to each.  Most plugin behaviour remains unchanged (non-startpoint edges aren't used as snapping candidates), but for map matching, we allow snapping to any edge.  This fixes map-matching across previously non-is_startpoint edges, like ferries, private service roads, and a few others.
  • Loading branch information
danpat committed Dec 14, 2018
1 parent 06e010b commit 81bc2f4
Show file tree
Hide file tree
Showing 19 changed files with 143 additions and 90 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
- Table:
- ADDED: new parameter `scale_factor` which will scale the cell `duration` values by this factor. [#5298](https://github.com/Project-OSRM/osrm-backend/pull/5298)
- FIXED: only trigger `scale_factor` code to scan matrix when necessary. [#5303](https://github.com/Project-OSRM/osrm-backend/pull/5303)
- Matching:
- CHANGED: matching will now consider edges marked with is_startpoint=false, allowing matching over ferries and other previously non-matchable edge types. [#5297](https://github.com/Project-OSRM/osrm-backend/pull/5297)

# 5.20.0
- Changes from 5.19.0:
Expand Down
1 change: 1 addition & 0 deletions docs/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ Vector tiles contain two layers:
| `weight ` | `integer` | how long this segment takes to traverse, in units (may differ from `duration` when artificial biasing is applied in the Lua profiles). ACTUAL ROUTING USES THIS VALUE. |
| `name` | `string` | the name of the road this segment belongs to |
| `rate` | `float` | the value of `length/weight` - analagous to `speed`, but using the `weight` value rather than `duration`, rounded to the nearest integer |
| `is_startpoint` | `boolean` | whether this segment can be used as a start/endpoint for routes |

`turns` layer:

Expand Down
9 changes: 9 additions & 0 deletions features/car/ferry.feature
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,12 @@ Feature: Car - Handle ferry routes
When I route I should get
| from | to | route | modes | time |
| c | d | bcde,bcde | ferry,ferry | 600s |

Given the query options
| geometries | geojson |
| overview | full |

# Note that matching *should* work across unsnappable ferries
When I match I should get
| trace | geometry | duration |
| abcdef| 1,1,1.000899,1,1.000899,1,1.002697,1,1.002697,1,1.003596,1,1.003596,1,1.005394,1,1.005394,1,1.006293,1 | 610.9 |
10 changes: 6 additions & 4 deletions include/engine/datafacade/contiguous_internalmem_datafacade.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,25 +312,27 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const Approach approach) const override final
const Approach approach,
const bool use_all_edges) const override final
{
BOOST_ASSERT(m_geospatial_query.get());

return m_geospatial_query->NearestPhantomNodesInRange(
input_coordinate, max_distance, approach);
input_coordinate, max_distance, approach, use_all_edges);
}

std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range,
const Approach approach) const override final
const Approach approach,
const bool use_all_edges) const override final
{
BOOST_ASSERT(m_geospatial_query.get());

return m_geospatial_query->NearestPhantomNodesInRange(
input_coordinate, max_distance, bearing, bearing_range, approach);
input_coordinate, max_distance, bearing, bearing_range, approach, use_all_edges);
}

std::vector<PhantomNodeWithDistance>
Expand Down
6 changes: 4 additions & 2 deletions include/engine/datafacade/datafacade_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,13 @@ class BaseDataFacade
const float max_distance,
const int bearing,
const int bearing_range,
const Approach approach) const = 0;
const Approach approach,
const bool use_all_edges) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const Approach approach) const = 0;
const Approach approach,
const bool use_all_edges) const = 0;

virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
Expand Down
24 changes: 16 additions & 8 deletions include/engine/geospatial_query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const double max_distance,
const Approach approach) const
const Approach approach,
const bool use_all_edges) const
{
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate](const CandidateSegment &segment) {
return boolPairAnd(boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)),
CheckApproach(input_coordinate, segment, approach));
[this, approach, &input_coordinate, use_all_edges](const CandidateSegment &segment) {
return boolPairAnd(
boolPairAnd(HasValidEdge(segment, use_all_edges), CheckSegmentExclude(segment)),
CheckApproach(input_coordinate, segment, approach));
},
[this, max_distance, input_coordinate](const std::size_t,
const CandidateSegment &segment) {
Expand All @@ -76,15 +78,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const double max_distance,
const int bearing,
const int bearing_range,
const Approach approach) const
const Approach approach,
const bool use_all_edges) const
{
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate, bearing, bearing_range](
[this, approach, &input_coordinate, bearing, bearing_range, use_all_edges](
const CandidateSegment &segment) {
auto use_direction =
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)));
boolPairAnd(HasValidEdge(segment, use_all_edges),
CheckSegmentExclude(segment)));
use_direction =
boolPairAnd(use_direction, CheckApproach(input_coordinate, segment, approach));
return use_direction;
Expand Down Expand Up @@ -628,7 +632,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
* which means that this edge is not currently traversible. If this is the case,
* then we shouldn't snap to this edge.
*/
std::pair<bool, bool> HasValidEdge(const CandidateSegment &segment) const
std::pair<bool, bool> HasValidEdge(const CandidateSegment &segment,
const bool use_all_edges = false) const
{

bool forward_edge_valid = false;
Expand All @@ -652,6 +657,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_edge_valid = data.reverse_segment_id.enabled;
}

forward_edge_valid = forward_edge_valid && (data.is_startpoint || use_all_edges);
reverse_edge_valid = reverse_edge_valid && (data.is_startpoint || use_all_edges);

return std::make_pair(forward_edge_valid, reverse_edge_valid);
}

Expand Down
8 changes: 5 additions & 3 deletions include/engine/plugins/plugin_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ class BasePlugin
std::vector<std::vector<PhantomNodeWithDistance>>
GetPhantomNodesInRange(const datafacade::BaseDataFacade &facade,
const api::BaseParameters &parameters,
const std::vector<double> radiuses) const
const std::vector<double> radiuses,
bool use_all_edges = false) const
{
std::vector<std::vector<PhantomNodeWithDistance>> phantom_nodes(
parameters.coordinates.size());
Expand Down Expand Up @@ -171,12 +172,13 @@ class BasePlugin
radiuses[i],
parameters.bearings[i]->bearing,
parameters.bearings[i]->range,
approach);
approach,
use_all_edges);
}
else
{
phantom_nodes[i] = facade.NearestPhantomNodesInRange(
parameters.coordinates[i], radiuses[i], approach);
parameters.coordinates[i], radiuses[i], approach, use_all_edges);
}
}

Expand Down
5 changes: 0 additions & 5 deletions include/extractor/edge_based_graph_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ class EdgeBasedGraphFactory
// The following get access functions destroy the content in the factory
void GetEdgeBasedEdges(util::DeallocatingVector<EdgeBasedEdge> &edges);
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
void GetEdgeBasedNodeDurations(std::vector<EdgeWeight> &output_node_durations);
void GetEdgeBasedNodeDistances(std::vector<EdgeDistance> &output_node_distances);
Expand All @@ -112,10 +111,6 @@ class EdgeBasedGraphFactory
std::vector<ConditionalTurnPenalty>
IndexConditionals(std::vector<Conditional> &&conditionals) const;

//! maps index from m_edge_based_node_list to ture/false if the node is an entry point to the
//! graph
std::vector<bool> m_edge_based_node_is_startpoint;

//! node weights that indicate the length of the segment (node based) represented by the
//! edge-based node
std::vector<EdgeWeight> m_edge_based_node_weights;
Expand Down
12 changes: 8 additions & 4 deletions include/extractor/edge_based_node_segment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,20 @@ struct EdgeBasedNodeSegment
EdgeBasedNodeSegment()
: forward_segment_id{SPECIAL_SEGMENTID, false},
reverse_segment_id{SPECIAL_SEGMENTID, false}, u(SPECIAL_NODEID), v(SPECIAL_NODEID),
fwd_segment_position(std::numeric_limits<unsigned short>::max())
fwd_segment_position(std::numeric_limits<unsigned short>::max() >>
1), // >> 1 because we've only got 15 bits
is_startpoint(false)
{
}

explicit EdgeBasedNodeSegment(const SegmentID forward_segment_id_,
const SegmentID reverse_segment_id_,
NodeID u,
NodeID v,
unsigned short fwd_segment_position)
unsigned short fwd_segment_position,
bool is_startpoint_)
: forward_segment_id(forward_segment_id_), reverse_segment_id(reverse_segment_id_), u(u),
v(v), fwd_segment_position(fwd_segment_position)
v(v), fwd_segment_position(fwd_segment_position), is_startpoint(is_startpoint_)
{
BOOST_ASSERT(forward_segment_id.enabled || reverse_segment_id.enabled);
}
Expand All @@ -41,7 +44,8 @@ struct EdgeBasedNodeSegment
SegmentID reverse_segment_id; // edge-based graph node ID in reverse direction (v->u if exists)
NodeID u; // node-based graph node ID of the start node
NodeID v; // node-based graph node ID of the target node
unsigned short fwd_segment_position; // segment id in a compressed geometry
unsigned short fwd_segment_position : 15; // segment id in a compressed geometry
bool is_startpoint : 1;
};
}
}
Expand Down
2 changes: 0 additions & 2 deletions include/extractor/extractor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ class Extractor
// output data
EdgeBasedNodeDataContainer &edge_based_nodes_container,
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
std::vector<EdgeDuration> &edge_based_node_durations,
std::vector<EdgeDistance> &edge_based_node_distances,
Expand All @@ -97,7 +96,6 @@ class Extractor
const std::vector<EdgeBasedNodeSegment> &input_node_segments,
EdgeBasedNodeDataContainer &nodes_container) const;
void BuildRTree(std::vector<EdgeBasedNodeSegment> edge_based_node_segments,
std::vector<bool> node_is_startpoint,
const std::vector<util::Coordinate> &coordinates);
std::shared_ptr<RestrictionMap> LoadRestrictionMap();

Expand Down
3 changes: 2 additions & 1 deletion src/engine/plugins/match.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
});
}

auto candidates_lists = GetPhantomNodesInRange(facade, tidied.parameters, search_radiuses);
auto candidates_lists =
GetPhantomNodesInRange(facade, tidied.parameters, search_radiuses, true);

filterCandidates(tidied.parameters.coordinates, candidates_lists);
if (std::all_of(candidates_lists.begin(),
Expand Down
13 changes: 12 additions & 1 deletion src/engine/plugins/tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ struct SpeedLayer : public vtzero::layer_builder
vtzero::index_value key_duration;
vtzero::index_value key_name;
vtzero::index_value key_rate;
vtzero::index_value key_is_startpoint;

SpeedLayer(vtzero::tile_builder &tile)
: layer_builder(tile, "speeds"), uint_index(*this), double_index(*this),
Expand All @@ -302,7 +303,8 @@ struct SpeedLayer : public vtzero::layer_builder
key_datasource(add_key_without_dup_check("datasource")),
key_weight(add_key_without_dup_check("weight")),
key_duration(add_key_without_dup_check("duration")),
key_name(add_key_without_dup_check("name")), key_rate(add_key_without_dup_check("rate"))
key_name(add_key_without_dup_check("name")), key_rate(add_key_without_dup_check("rate")),
key_is_startpoint(add_key_without_dup_check("is_startpoint"))
{
}

Expand Down Expand Up @@ -349,6 +351,11 @@ class SpeedLayerFeatureBuilder : public vtzero::linestring_feature_builder

void set_rate(double value) { add_property(m_layer.key_rate, m_layer.double_index(value)); }

void set_is_startpoint(bool value)
{
add_property(m_layer.key_is_startpoint, m_layer.bool_index(value));
}

}; // class SpeedLayerFeatureBuilder

struct TurnsLayer : public vtzero::layer_builder
Expand Down Expand Up @@ -485,6 +492,8 @@ void encodeVectorTile(const DataFacadeBase &facade,
const auto reverse_datasource_idx = reverse_datasource_range(
reverse_datasource_range.size() - edge.fwd_segment_position - 1);

const auto is_startpoint = edge.is_startpoint;

const auto component_id = facade.GetComponentID(edge.forward_segment_id.id);
const auto name_id = facade.GetNameIndex(edge.forward_segment_id.id);
auto name = facade.GetNameForID(name_id);
Expand Down Expand Up @@ -516,6 +525,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
fbuilder.set_duration(forward_duration / 10.0);
fbuilder.set_name(name);
fbuilder.set_rate(forward_rate / 10.0);
fbuilder.set_is_startpoint(is_startpoint);

fbuilder.commit();
}
Expand Down Expand Up @@ -549,6 +559,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
fbuilder.set_duration(reverse_duration / 10.0);
fbuilder.set_name(name);
fbuilder.set_rate(reverse_rate / 10.0);
fbuilder.set_is_startpoint(is_startpoint);

fbuilder.commit();
}
Expand Down
12 changes: 2 additions & 10 deletions src/extractor/edge_based_graph_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,6 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSe
swap(nodes, m_edge_based_node_segments);
}

void EdgeBasedGraphFactory::GetStartPointMarkers(std::vector<bool> &node_is_startpoint)
{
using std::swap; // Koenig swap
swap(m_edge_based_node_is_startpoint, node_is_startpoint);
}

void EdgeBasedGraphFactory::GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights)
{
using std::swap; // Koenig swap
Expand Down Expand Up @@ -229,10 +223,9 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
edge_id_to_segment_id(nbe_to_ebn_mapping[edge_id_2]),
current_edge_source_coordinate_id,
current_edge_target_coordinate_id,
i);
i,
forward_data.flags.startpoint || reverse_data.flags.startpoint);

m_edge_based_node_is_startpoint.push_back(forward_data.flags.startpoint ||
reverse_data.flags.startpoint);
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
}

Expand Down Expand Up @@ -427,7 +420,6 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
}
}

BOOST_ASSERT(m_edge_based_node_segments.size() == m_edge_based_node_is_startpoint.size());
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_weights.size());
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_durations.size());
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_distances.size());
Expand Down
Loading

0 comments on commit 81bc2f4

Please sign in to comment.