Skip to content
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

remove assertions that could be triggered by bad data #3469

Merged
merged 1 commit into from
Jan 7, 2017

Conversation

MoKob
Copy link

@MoKob MoKob commented Dec 19, 2016

Some of the assertions in various coordinate extraction steps are not correct. It's possible for valid OSM geometry to contain nodes that are at the same coordinate (either via users placing duplicate coordinates, or decimal rounding snapping nearby points to the same place). We are currently asserting that this can't happen, even though it can.

This PR disables those assertions.

In addition, because there is no definition of "bearing" between two identical points, the current behaviour is undefined. This PR also adds some tests that when we encounter this situation, we return 0 for the bearing. Although still incorrect, at least it's consistent and testable.

A full fix for this requires #3470 which is more complex, this PR is just to unblock the demo server updates. We will live with #3470 being a known issue for now.

Tasklist

  • review
  • adjust for comments

Requirements / Relations

Related to: #3470

@MoKob MoKob added the Review label Dec 19, 2016
Copy link
Member

@TheMarex TheMarex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main problem I see with just disabling the assertions is that right now we have a function that can fail. For functions like that the calling code needs to check if it was successful.

Even if you want to remove this failure handling in the future because you found a nicer way to deal with it, it needs to be there in the current iteration.

@MoKob
Copy link
Author

MoKob commented Dec 19, 2016

I don't really see what you imagine to be in here. There is nothing else that can be returned in that situation. As long as you have ways from a to b with loc(a) == loc(b) there is now way of finding a coordinate c on that way with loc(c) != loc(a). The coordinate will always be at the same location.
As long as the code provides these coordinates to the graph creation, graph creation will not be able to come up with a way around these.
But feel free to implement handling against pushing down these to the graph creation in the first place.

Edit: to be clear: failing here gives a random bearing value. A road without any bearing will introduce randomness in detection obvious turns/forks and introduce a random value in the intersection classification. As long as this broken data cannot be excluded, I don't see what else we can do. Especially not at this location.

Especially, given the input, the function returns the only valid coordinate. It does, in itself, not fail. It only does not report something that has any meaning, but that's the case the input data reflects. I don't see a reason the code should make cases more reasonable than the input suggests.

@daniel-j-h
Copy link
Member

Hrm yeah we really should filter those already in the extraction (thanks for opening #3470), maybe write out a warning and throw them away. Or even build a small tool for same coordinate detection. If this makes our life easier.

I don't think wrapping the result in an optional is semantically more correct here, it's just our graph is already broken to some degree.

@TheMarex
Copy link
Member

TheMarex commented Dec 20, 2016

@MoKob to illustrate what I mean by error handling I just pushed the change. I would really like to see this handled in the graph creation as well, but as of now we don't do that, hence we need the explicit handling.

The problem is handled at the call site, since the function doesn't know that the caller will put the result into a bearing calculation. Hence the lambda that checks if the returned coordinate is not the same as the start coordinate of the segment needed a rename, since in some cases it can be a valid result as you pointed out.

@MoKob
Copy link
Author

MoKob commented Dec 20, 2016

I have to disagree here. The problem is not handled at the call site. The only handling that is done is logging. The changes to setting bearing are void, since bearing is just as well defined to a single constant value for two identical coordinates. Looking at the math, it should even be zero.

If you actually want to handle it at the call site, we would have to both consider it correctly in roundabout handling (possibly disable roundabout intersections for these cases) and remove them from intersection_classification/turn_discovery. I am not clear on whether this could be done by simply removing the segment (unlikely given all strange modelling in OSM). Handling this case is a complex matter, right now we are only logging it (duplicated even, since the log at the roundabout handling is only called on intersections that the normal intersection generator also generates)

The only effective change done is renaming an assert that at some point will be possible to assert (and at that point would also be fine the way that it was). If you need to change this behaviour to fix the demo server, go ahead.

return coordinates.back();
}

// due to repeated coordinates / smaller offset errors we skip over the very first parts of the
// coordinate set to add a small level of fault tolerance
const constexpr double skipping_inaccuracies_distance = 2;

// fallback, mostly necessary for dead ends
if (intersection_node == to_node)
Copy link
Author

@MoKob MoKob Dec 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing this will actually negatively affect the turn discovery. It has nothing to do with the changes necessary and has a negative impact on discovery in traffic loops.
I have to say though that I don't remember at which location I had to add this fallback.

@danpat
Copy link
Member

danpat commented Dec 21, 2016

I agree with @MoKob, the assertions need to go. They're faulty as-is - we're asserting an invalid proposition that ignores the possibility of zero-length edges. Although the data is stupid, it is valid in OSM, we shouldn't crash hard when we come across it. Printing a warning would be reasonable if we can't work around it.

There is all kinds of junk data in OSM - duplicated ways with identical node coordinates are very common, as are duplicated nodes (iD at one point had a bug that made it easy to add many nodes at the same spot). We have to figure out a way to live with this data.

@MoKob Do you think you could sketch out a few cucumberjs scenarios for this ugliness? I suspect there are some situations we can probably resolve and some that are just going to result in garbage results - it'd be great to catalogue these so we understand what junk we can handle and what we can't.

If we can systematically identify totally unusable geometry, we can produce a report and the OSM community and/or the Mapbox data team can help clean up the bad stuff.

@MoKob
Copy link
Author

MoKob commented Dec 21, 2016

@danpat that would be part of #3470. Here we kind of don't have any possibilities other than disabling the assertion, for now. At some point we would want to re-introduce it, since when we handle the case before, we should never get into the bad situation here...

@daniel-j-h daniel-j-h added this to the 5.5.3 milestone Jan 2, 2017
@danpat danpat force-pushed the fix/remove-assert-valid-coordinates branch from e6567e2 to ae1cd7d Compare January 3, 2017 18:54
@danpat danpat force-pushed the fix/remove-assert-valid-coordinates branch from ae1cd7d to fe7569a Compare January 4, 2017 07:22
@danpat
Copy link
Member

danpat commented Jan 4, 2017

@MoKob @daniel-j-h I've tidied up and squashed this PR. Can you please sanity check that I didn't break anything during the rebase?

I've added a test case to verify that we always return 0. as a bearing for identical coordinates. The bearing is still invalid, but at least it's a known value we might recognize if someone notices the problem in a route.

If everything looks correct, lets get this merged into master and unblock the demo server. @daniel-j-h feel free to hit the merge button, or I can do it during my day tomorrow.

@danpat danpat dismissed TheMarex’s stale review January 4, 2017 07:34

I've tidied up the checks. Full fix should be done with #3470.

@MoKob MoKob force-pushed the fix/remove-assert-valid-coordinates branch 2 times, most recently from 5ce51bf to 799d180 Compare January 4, 2017 07:50
// Here we can't check for validity, due to possible dead-ends with repeated coordinates
// BOOST_ASSERT(is_valid_result(coordinates.back()));
// TODO: possibly re-enable with https://github.com/Project-OSRM/osrm-backend/issues/3470
// BOOST_ASSERT(not_same_as_start(result));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is .back() always safe here or do we have to assert for !empty?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we have at least the intersection node, we cannot have less than one coordinate

Copy link
Member

@daniel-j-h daniel-j-h left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clearly ticket the TODOs and the reasoning behind them in #3470 or even make a separate ticket. I can see us forgetting about them, as it is always the case with TODOs / FIXMEs.

@MoKob
Copy link
Author

MoKob commented Jan 4, 2017

I've added tasks to the todos to #3470.

@daniel-j-h
Copy link
Member

Running a staging demo server with this - let's wait till we know for sure it runs through this time.

@danpat
Copy link
Member

danpat commented Jan 5, 2017

So close, but not quite. @daniel-j-h the staging server just asserted the following:

[assert] /mnt/ebs/osrm/2017-01-04-161647/src/extractor/guidance/sliproad_handler.cpp:309
in: virtual osrm::extractor::guidance::Intersection osrm::extractor::guidance::SliproadHandler::operator()(NodeID, EdgeID, osrm::extractor::guidance::Intersection) const: coords.size() >= 2
terminate called without an active exception

I'm out of time to dig into this deeper today :-(

@MoKob
Copy link
Author

MoKob commented Jan 5, 2017

I've had a look. Simply was another case of these duplicated coordinates. Since the coordinate extractor filters these duplicates for easy handling as a precondition, we can end up seeing only one coordinate in the result.

The sliproad handler assumed to have at least two. I've checked all instances of the coordinate_extractor used in the handlers and found this to be the only occurrence where it happened.

@MoKob MoKob force-pushed the fix/remove-assert-valid-coordinates branch from 89a9414 to c8c2dc9 Compare January 5, 2017 08:52
@daniel-j-h
Copy link
Member

Starting the toolchain on the staging demo server anew.

@MoKob MoKob force-pushed the fix/remove-assert-valid-coordinates branch from c8c2dc9 to 562e506 Compare January 5, 2017 12:22
@danpat
Copy link
Member

danpat commented Jan 6, 2017

[assert] /mnt/ebs/osrm/2017-01-05-121703/src/extractor/guidance/coordinate_extractor.cpp:166
in: osrm::util::Coordinate osrm::extractor::guidance::CoordinateExtractor::ExtractRepresentativeCoordinate(NodeID, EdgeID, bool, NodeID, uint8_t, std::vector<osrm::util::Coordinate>) const: not_same_as_start(result)
terminate called without an active exception

Getting closer, we're now on a different assert (about 85-90% of the way through Generating edge-expanded edges).

@daniel-j-h
Copy link
Member

Starting another toolchain run - maybe this time. cc @danpat

@MoKob
Copy link
Author

MoKob commented Jan 6, 2017

from the on first glance unrelated change, the tile size check failed. @danpat do you have any further insight into why this happens/if that adjustment would be fine?

Is there a way we can check tile sizes other than exact sizes which may change when the file is updated (e.g. since we need new features) or can be affected by changes like these?
I am thinking of some appropriate range to make sure than the tile size does not explode, but we don't have to adjust on changes like the turn angles I just edited.

@danpat
Copy link
Member

danpat commented Jan 7, 2017

@MoKob If some of the turn angles changed, then it's likely that the varint packing in the PBF vector tile ended up with a different number of bytes.

Changes to angles in the tiles should only vary the size by a couple of bytes, so adding a +/- of a small amount is probably fine.

Some of the tile tests verify that the expected turn values are in place, like here:

https://github.com/Project-OSRM/osrm-backend/blob/master/unit_tests/library/tile.cpp#L332-L334

maybe we should drop the size check now that the platform-dependent differences in tile size problems have been corrected.

If it's fixed for now, I'm inclined to leave it alone though - if it happens again, let's adjust the tile tests.

When two consecutive nodes have identical coordinates, there is no valid
bearing.  For now, make equal nodes have bearing 0.

Full fix still needs to be done via #3470.
@danpat danpat force-pushed the fix/remove-assert-valid-coordinates branch from 2f07193 to a8e515f Compare January 7, 2017 00:25
@danpat danpat merged commit 15c8fd3 into master Jan 7, 2017
TheMarex pushed a commit that referenced this pull request Jan 11, 2017
When two consecutive nodes have identical coordinates, there is no valid
bearing.  For now, make equal nodes have bearing 0.

Full fix still needs to be done via #3470.
@MoKob MoKob deleted the fix/remove-assert-valid-coordinates branch January 12, 2017 08:31
raymond0 added a commit to raymond0/osrm-backend that referenced this pull request Feb 24, 2017
Merge commit '54ab5373cf9b883f1d791182f218c33a2b5bd22b' into develop-ultimaterides-buildmain-integration

* commit '54ab5373cf9b883f1d791182f218c33a2b5bd22b': (23 commits)
  Fix tests - backported changes need old namespace.
  Update changelog and version for 5.5.4
  fix emitting invalid turn types, now surfacing due to changes in obvious detection
  Changelog Item for Project-OSRM#3561
  Added missing backward_speed for cycleways
  cherry-pick Project-OSRM#3555
  Fix possible division by zero by clamping latitude to 85.05°
  Adjusted number of `nodes` in `annotation`, resolves Project-OSRM#3515
  Update version and CHANGELOG for 5.5.3.
  Backport NumLanesToTheRight/NumLanesToTheLeft to support 6ea9f9f
  fix coordinate assertion for walking profile with steps
  Remove assertions that could be triggered by bad data. (Project-OSRM#3469)
  Make a hard reset of named barrier mutexes on signal
  Fix copying vector on std::sort comparator (Project-OSRM#3504)
  Consider number of lanes to cross, resolves Project-OSRM#3025.
  Make Travis buildit.
  Update changelog and version.
  Revert "Smarter search radius formula for map matching"
  Revert "Fix capture"
  Revert "Hardcode search radius parameters"
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants