-
Notifications
You must be signed in to change notification settings - Fork 661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interpolation bug fix #2275
Interpolation bug fix #2275
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to propose a simpler alternative that uses the interpolation to move the window rather than an unordered map and extra looping.
diff --git a/src/meili/map_matcher.cc b/src/meili/map_matcher.cc
index 3924651a2..21ef43470 100644
--- a/src/meili/map_matcher.cc
+++ b/src/meili/map_matcher.cc
@@ -35,6 +35,7 @@ struct Interpolation {
float route_distance;
float route_time;
float edge_distance;
+ std::vector<EdgeSegment>::const_iterator segment;
float sortcost(const EmissionCostModel& emission_model,
const TransitionCostModel& transition_model,
@@ -61,6 +62,7 @@ inline MatchResult CreateMatchResult(const Measurement& measurement, const Inter
Interpolation InterpolateMeasurement(const MapMatcher& mapmatcher,
const Measurement& measurement,
std::vector<EdgeSegment>::const_iterator begin,
+ float begin_source_offset,
std::vector<EdgeSegment>::const_iterator end,
float match_measurement_distance,
float match_measurement_time) {
@@ -75,6 +77,8 @@ Interpolation InterpolateMeasurement(const MapMatcher& mapmatcher,
Interpolation best_interp;
for (auto segment = begin; segment != end; segment++) {
+ // TODO: skip if this edgeid is the same as the previous one we dont need to check it twice
+
const auto directededge = mapmatcher.graphreader().directededge(segment->edgeid, tile);
if (!directededge) {
continue;
@@ -96,6 +100,16 @@ Interpolation InterpolateMeasurement(const MapMatcher& mapmatcher,
offset = 1.f - offset;
}
+ // clip distance along to the match boundaries
+ if (segment == begin && offset < begin_source_offset) {
+ offset = begin_source_offset;
+ // TODO: update the snap to this offset along the edge (projected_point, sq_distance)
+ }
+ if (segment == end - 1 && offset > segment->target) {
+ offset = segment->target;
+ // TODO: update the snap to this offset along the edge (projected_point, sq_distance)
+ }
+
// Distance from the projected point to the segment begin, or
// segment begin if we walk reversely
const auto distance_to_segment_ends =
@@ -109,8 +123,8 @@ Interpolation InterpolateMeasurement(const MapMatcher& mapmatcher,
auto edge_percent = segment->target - segment->source;
auto route_time = mapmatcher.costing()->EdgeCost(directededge, tile).secs * edge_percent;
- Interpolation interp{projected_point, segment->edgeid, sq_distance,
- route_distance, route_time, offset};
+ Interpolation interp{projected_point, segment->edgeid, sq_distance, route_distance,
+ route_time, offset, segment};
const auto cost =
interp.sortcost(mapmatcher.emission_cost_model(), mapmatcher.transition_cost_model(),
@@ -153,13 +167,22 @@ std::vector<MatchResult> InterpolateMeasurements(const MapMatcher& mapmatcher,
mapmatcher.state_container().state(next_stateid));
// for each point that needs interpolated
+ std::vector<EdgeSegment>::const_iterator left_most_segment = route.begin();
+ float left_most_offset = route.begin()->source;
for (const auto& measurement : measurements) {
const auto& match_measurement = mapmatcher.state_container().measurement(stateid.time());
const auto match_measurement_distance = GreatCircleDistance(measurement, match_measurement);
const auto match_measurement_time = ClockDistance(measurement, match_measurement);
+
// interpolate this point along the route
- const auto& interp = InterpolateMeasurement(mapmatcher, measurement, route.begin(), route.end(),
- match_measurement_distance, match_measurement_time);
+ const auto interp =
+ InterpolateMeasurement(mapmatcher, measurement, left_most_segment, left_most_offset,
+ route.end(), match_measurement_distance, match_measurement_time);
+
+ // shift the point at which we are allowed to start interpolating from to the right
+ // so that its on the interpolation point this way the next interpolation happens after
+ left_most_segment = interp.segment;
+ left_most_offset = interp.edge_distance;
// if it was able to do the interpolation
if (interp.edgeid.Is_Valid()) {
src/meili/map_matcher.cc
Outdated
@@ -152,28 +169,39 @@ std::vector<MatchResult> InterpolateMeasurements(const MapMatcher& mapmatcher, | |||
std::vector<EdgeSegment> route = MergeRoute(mapmatcher.state_container().state(stateid), | |||
mapmatcher.state_container().state(next_stateid)); | |||
|
|||
if (route.empty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is this doing, what tests do we have to show that this is doing what its supposed to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, after the changes. Some existing unit test in the test matcher got broken if we do not have this protection.
src/meili/map_matcher.cc
Outdated
@@ -664,12 +697,15 @@ std::vector<MatchResults> MapMatcher::OfflineMatch(const std::vector<Measurement | |||
const auto& this_stateid = original_state_ids[time]; | |||
const auto& next_stateid = | |||
time + 1 < original_state_ids.size() ? original_state_ids[time + 1] : StateId(); | |||
|
|||
midgard::PointLL first_projection = results[time].lnglat; | |||
midgard::PointLL last_projection = results[time + 1].lnglat; | |||
const auto& interpolated_results = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this shouldnt be a reference and if you do the move iterator you need to remove const as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
excellent debugging once again!
* master: additional data processing options (#2285) Fix Uturn cases on not_thru edge connected to origin. (#2272) Interpolation bug fix (#2275) Update intersection classes in osrm response to not label all ramps as motorway (#2279) More stop impact changes (#2282) Fixed verbal multi-cue logic (#2270) Re-write test/astar.cc to use gurka graph creation helpers rather than hard-coding edge creation/IDs Add gurka test framework to ease creation of test cases with ascii-maps Add helper functions so that we can perform actions without serializing if desired - this is to support testing of intermediate results. Make protobuf cleanup after tile building optional (on by default) so that tests can repeatedly call mjolnir::build_tile_set Downgrade some log messages to warnings - they are non-fatal behaviours, no error is actually emitted by the code. Reduce concurrency of lint debug build so that it doesn't hit OOM problems on CI Exact Reachability (ie v3) (#2243)
Issue
This PR is targeting on the fix of interpolation bug. The previous logic has a flaw that, the interpolated locations are allowed to go beyond the boundaries of the actual matched point. See following example of interpolated point's (B) distance_along of the edge is smaller than matched point (A). Such behavior will lead to discontinuity for the serializer, the serializer thinks there is a discontinuity which is incorrect.
after the fix, the clip the distance_along of B to A's distance along.
Tasklist
Requirements / Relations
Link any requirements here. Other pull requests this PR is based on?