Skip to content

Commit ede0921

Browse files
committed
Fix map matching lane-width tolerance
1 parent f984023 commit ede0921

11 files changed

Lines changed: 131 additions & 28 deletions

File tree

‎features/testbot/matching.feature‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,26 @@ Feature: Basic Map Matching
159159
| trace | matchings |
160160
| afcde | abcde |
161161

162+
Scenario: Testbot - Map matching accounts for lane width
163+
Given a grid size of 4 meters
164+
Given the node map
165+
"""
166+
a b c d
167+
168+
169+
1 2 3 4
170+
e f g h
171+
"""
172+
173+
And the ways
174+
| nodes | oneway | lanes |
175+
| abcd | no | 8 |
176+
| efgh | no | |
177+
178+
When I match I should get
179+
| trace | matchings |
180+
| 1234 | abcd |
181+
162182
Scenario: Testbot - Map matching with oneways
163183
Given a grid size of 10 meters
164184
Given the node map

‎include/engine/datafacade/contiguous_internalmem_datafacade.hpp‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
431431
return edge_based_node_data.GetClassData(edge_based_node_id);
432432
}
433433

434+
std::uint8_t GetNumberOfLanes(const NodeID edge_based_node_id) const override final
435+
{
436+
return edge_based_node_data.GetNumberOfLanes(edge_based_node_id);
437+
}
438+
434439
bool ExcludeNode(const NodeID edge_based_node_id) const override final
435440
{
436441
return (edge_based_node_data.GetClassData(edge_based_node_id) & exclude_mask) > 0;

‎include/engine/datafacade/datafacade_base.hpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ class BaseDataFacade
114114

115115
virtual extractor::ClassData GetClassData(const NodeID edge_based_node_id) const = 0;
116116

117+
virtual std::uint8_t GetNumberOfLanes(const NodeID edge_based_node_id) const = 0;
118+
117119
virtual bool ExcludeNode(const NodeID edge_based_node_id) const = 0;
118120

119121
virtual std::vector<std::string> GetClasses(const extractor::ClassData class_data) const = 0;

‎include/engine/geospatial_query.hpp‎

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef GEOSPATIAL_QUERY_HPP
22
#define GEOSPATIAL_QUERY_HPP
33

4+
#include "extractor/intersection/constants.hpp"
45
#include "engine/approach.hpp"
56
#include "engine/bearing.hpp"
67
#include "engine/phantom_node.hpp"
@@ -17,6 +18,7 @@
1718
#include <algorithm>
1819
#include <cmath>
1920
#include <iterator>
21+
#include <limits>
2022
#include <vector>
2123

2224
namespace osrm::engine
@@ -57,7 +59,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
5759
{
5860
auto results = rtree.SearchInRange(
5961
input_coordinate,
60-
max_distance,
62+
max_distance + GetMaximumRoadHalfWidth(),
6163
[this, approach, &input_coordinate, &bearing_with_range, &use_all_edges, max_distance](
6264
const CandidateSegment &segment)
6365
{
@@ -495,11 +497,37 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
495497
wsg84_coordinate);
496498
}
497499

500+
static constexpr double GetMaximumRoadHalfWidth()
501+
{
502+
return 0.5 * std::numeric_limits<std::uint8_t>::max() *
503+
extractor::intersection::ASSUMED_LANE_WIDTH;
504+
}
505+
506+
double GetRoadHalfWidth(const CandidateSegment &segment) const
507+
{
508+
if (segment.data.forward_segment_id.enabled &&
509+
segment.data.forward_segment_id.id != SPECIAL_SEGMENTID)
510+
{
511+
return 0.5 * datafacade.GetNumberOfLanes(segment.data.forward_segment_id.id) *
512+
extractor::intersection::ASSUMED_LANE_WIDTH;
513+
}
514+
515+
if (segment.data.reverse_segment_id.enabled &&
516+
segment.data.reverse_segment_id.id != SPECIAL_SEGMENTID)
517+
{
518+
return 0.5 * datafacade.GetNumberOfLanes(segment.data.reverse_segment_id.id) *
519+
extractor::intersection::ASSUMED_LANE_WIDTH;
520+
}
521+
522+
return 0.;
523+
}
524+
498525
bool CheckSegmentDistance(const Coordinate input_coordinate,
499526
const CandidateSegment &segment,
500527
const double max_distance) const
501528
{
502-
return GetSegmentDistance(input_coordinate, segment) > max_distance;
529+
return GetSegmentDistance(input_coordinate, segment) >
530+
max_distance + GetRoadHalfWidth(segment);
503531
}
504532

505533
std::pair<bool, bool> CheckSegmentExclude(const CandidateSegment &segment) const

‎include/extractor/node_based_edge.hpp‎

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,29 +68,35 @@ struct NodeBasedEdgeAnnotation
6868
StringViewID string_view_id; // 32 4
6969
LaneDescriptionID lane_description_id; // 16 2
7070
ClassData classes; // 8 1
71+
std::uint8_t number_of_lanes; // 8 1
7172
TravelMode travel_mode : 4; // 4
7273
bool is_left_hand_driving : 1; // 1
7374

7475
bool CanCombineWith(const NodeBasedEdgeAnnotation &other) const
75-
{
76-
return (std::tie(string_view_id, classes, travel_mode, is_left_hand_driving) ==
77-
std::tie(other.string_view_id,
78-
other.classes,
79-
other.travel_mode,
80-
other.is_left_hand_driving));
81-
}
82-
83-
bool operator<(const NodeBasedEdgeAnnotation &other) const
8476
{
8577
return (
86-
std::tie(
87-
string_view_id, lane_description_id, classes, travel_mode, is_left_hand_driving) <
78+
std::tie(string_view_id, classes, number_of_lanes, travel_mode, is_left_hand_driving) ==
8879
std::tie(other.string_view_id,
89-
other.lane_description_id,
9080
other.classes,
81+
other.number_of_lanes,
9182
other.travel_mode,
9283
other.is_left_hand_driving));
9384
}
85+
86+
bool operator<(const NodeBasedEdgeAnnotation &other) const
87+
{
88+
return (std::tie(string_view_id,
89+
lane_description_id,
90+
classes,
91+
number_of_lanes,
92+
travel_mode,
93+
is_left_hand_driving) < std::tie(other.string_view_id,
94+
other.lane_description_id,
95+
other.classes,
96+
other.number_of_lanes,
97+
other.travel_mode,
98+
other.is_left_hand_driving));
99+
}
94100
};
95101

96102
struct NodeBasedEdge

‎include/extractor/node_data_container.hpp‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
8989
return annotation_data[nodes[node_id].annotation_id].classes;
9090
}
9191

92+
std::uint8_t GetNumberOfLanes(const NodeID node_id) const
93+
{
94+
return annotation_data[nodes[node_id].annotation_id].number_of_lanes;
95+
}
96+
9297
friend void serialization::read<Ownership>(storage::tar::FileReader &reader,
9398
const std::string &name,
9499
EdgeBasedNodeDataContainerImpl &ebn_data_container);

‎profiles/testbot.lua‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function process_way (profile, way, result)
5555
local maxspeed_forward = tonumber(way:get_value_by_key( "maxspeed:forward"))
5656
local maxspeed_backward = tonumber(way:get_value_by_key( "maxspeed:backward"))
5757
local junction = way:get_value_by_key("junction")
58+
local lanes = tonumber(way:get_value_by_key("lanes"))
5859

5960
if name then
6061
result.name = name
@@ -120,6 +121,10 @@ function process_way (profile, way, result)
120121
result.backward_classes["toll"] = true
121122
end
122123

124+
if lanes and lanes > 0 then
125+
result.road_classification.num_lanes = lanes
126+
end
127+
123128
if junction == 'roundabout' then
124129
result.roundabout = true
125130
end

‎src/engine/routing_algorithms/map_matching.cpp‎

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "engine/map_matching/matching_confidence.hpp"
77
#include "engine/map_matching/sub_matching.hpp"
88

9+
#include "extractor/intersection/constants.hpp"
10+
911
#include "util/coordinate_calculation.hpp"
1012
#include "util/for_each_pair.hpp"
1113

@@ -61,6 +63,20 @@ inline void initializeHeap<mld::Algorithm>(SearchEngineData<mld::Algorithm> &eng
6163
engine_working_data.InitializeOrClearMapMatchingThreadLocalStorage(nodes_number,
6264
border_nodes_number);
6365
}
66+
67+
template <typename Algorithm>
68+
double getDistanceOutsideRoadSurface(const DataFacade<Algorithm> &facade,
69+
const PhantomNodeWithDistance &candidate)
70+
{
71+
const auto &phantom = candidate.phantom_node;
72+
const auto number_of_lanes = phantom.forward_segment_id.enabled
73+
? facade.GetNumberOfLanes(phantom.forward_segment_id.id)
74+
: facade.GetNumberOfLanes(phantom.reverse_segment_id.id);
75+
const double road_half_width =
76+
0.5 * number_of_lanes * extractor::intersection::ASSUMED_LANE_WIDTH;
77+
78+
return std::max(0., candidate.distance - road_half_width);
79+
}
6480
} // namespace
6581

6682
template <typename Algorithm>
@@ -106,7 +122,10 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
106122
candidates_list[t].end(),
107123
emission_log_probabilities[t].begin(),
108124
[&](const PhantomNodeWithDistance &candidate)
109-
{ return default_emission_log_probability(candidate.distance); });
125+
{
126+
return default_emission_log_probability(
127+
getDistanceOutsideRoadSurface(facade, candidate));
128+
});
110129
}
111130
}
112131
else
@@ -121,16 +140,22 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
121140
std::transform(candidates_list[t].begin(),
122141
candidates_list[t].end(),
123142
emission_log_probabilities[t].begin(),
124-
[&emission_log_probability](const PhantomNodeWithDistance &candidate)
125-
{ return emission_log_probability(candidate.distance); });
143+
[&](const PhantomNodeWithDistance &candidate)
144+
{
145+
return emission_log_probability(
146+
getDistanceOutsideRoadSurface(facade, candidate));
147+
});
126148
}
127149
else
128150
{
129151
std::transform(candidates_list[t].begin(),
130152
candidates_list[t].end(),
131153
emission_log_probabilities[t].begin(),
132154
[&](const PhantomNodeWithDistance &candidate)
133-
{ return default_emission_log_probability(candidate.distance); });
155+
{
156+
return default_emission_log_probability(
157+
getDistanceOutsideRoadSurface(facade, candidate));
158+
});
134159
}
135160
}
136161
}

‎src/extractor/extractor_callbacks.cpp‎

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -400,11 +400,13 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
400400
if (in_forward_direction)
401401
{ // add (forward) segments or (forward,backward) for non-split edges in backward direction
402402
const auto annotation_data_id = external_memory.all_edges_annotation_data_list.size();
403-
external_memory.all_edges_annotation_data_list.push_back({forward_name_id,
404-
turn_lane_id_forward,
405-
forward_classes,
406-
parsed_way.forward_travel_mode,
407-
parsed_way.is_left_hand_driving});
403+
external_memory.all_edges_annotation_data_list.push_back(
404+
{forward_name_id,
405+
turn_lane_id_forward,
406+
forward_classes,
407+
road_classification.GetNumberOfLanes(),
408+
parsed_way.forward_travel_mode,
409+
parsed_way.is_left_hand_driving});
408410
util::for_each_pair(nodes,
409411
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node)
410412
{
@@ -435,11 +437,13 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
435437
if (in_backward_direction && (!in_forward_direction || split_edge))
436438
{ // add (backward) segments for split edges or not in forward direction
437439
const auto annotation_data_id = external_memory.all_edges_annotation_data_list.size();
438-
external_memory.all_edges_annotation_data_list.push_back({backward_name_id,
439-
turn_lane_id_backward,
440-
backward_classes,
441-
parsed_way.backward_travel_mode,
442-
parsed_way.is_left_hand_driving});
440+
external_memory.all_edges_annotation_data_list.push_back(
441+
{backward_name_id,
442+
turn_lane_id_backward,
443+
backward_classes,
444+
road_classification.GetNumberOfLanes(),
445+
parsed_way.backward_travel_mode,
446+
parsed_way.is_left_hand_driving});
443447
util::for_each_pair(nodes,
444448
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node)
445449
{

‎unit_tests/engine/offline_facade.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
319319
}
320320

321321
osrm::extractor::ClassData GetClassData(const NodeID /*id*/) const override { return 0; }
322+
std::uint8_t GetNumberOfLanes(const NodeID /*id*/) const override { return 0; }
322323
std::vector<std::string> GetClasses(const extractor::ClassData /*class_data*/) const override
323324
{
324325
return {};

0 commit comments

Comments
 (0)