Avoid inconsistencies when a route doubles back on itself
When a route doubles back on itself and the user visits the same coordinate a second time, the SDK gets confused, momentarily thinking the user is visiting that coordinate for the first time. There are several ways to reproduce this issue, for example:
- A Michigan left, superstreet, or other intersection with turn restrictions requires the user to re-approach a given intersection in order to make a left turn.
- A custom route, such as one that solves the route inspection problem, reaches a four-way intersection from two different approaches and leaves on two different outlets. mapbox/navigation-ios-examples#28 demonstrates such a route.
- A loop ramp in a cloverleaf interchange happens to end directly over or under the spot where it begins.
- A route traverses the upper deck of a double-decker bridge, then the lower deck.
- A route traverses a spiral bridge, such as in a parking garage.
Symptoms of this issue are:
- The maneuver arrow along the route line points in the wrong direction.
- During route simulation, the camera and puck jump or turn in the wrong direction.
- Prior to #1710, the puck would also jump even when not simulating the route.
The problem is that we’re passing a coordinate into Polyline.trimmed(from:distance:), which assumes the coordinate can only appear once in the polyline:
https://github.com/mapbox/mapbox-navigation-ios/blob/f7ba632b731e7d8f8ccbad77df3ea07510bab395/MapboxNavigation/NavigationMapView.swift#L592-L593 https://github.com/mapbox/mapbox-navigation-ios/blob/f7ba632b731e7d8f8ccbad77df3ea07510bab395/MapboxCoreNavigation/SimulatedLocationManager.swift#L157
The most robust fix is to rely on indices into the coordinate array rather than the coordinates themselves. This approach will likely be necessary as part of the navigation-native refactoring. But that could make it much more difficult to memoize the remaining portion of the route, as in #1728.
An alternative approach, which accommodates #1728, is to form polylines from the two nearest steps’ coordinates properties rather than Route.coordinates. In the event that there are more than two maneuvers in close proximity, we’ll have to expand outward from those two steps. It’ll look pretty similar to RouteLegProgress.nearbyCoordinates, but that computed property is too aggressive because it unconditionally adds both the previous and next steps’ coordinates to the result.
/cc @mapbox/navigation-ios @d-prukop
#1735 fixes the maneuver arrow, but not the similar simulated location issue pointed out above. SimulatedLocationManager makes assumptions about the uniqueness of coordinates in multiple places, and untangling those assumptions will be less straightforward. mapbox/turf-swift#67 adds a method that may help with that.
#1735 fixed enough of this issue that the rest can land in a future release as we find reproducible cases for the remaining theoretical concerns. Removing the milestone.
I'm encountering a rerouting/navigation issue in Mapbox Navigation SDK for iOS when the route contains waypoints that cause the path to double back on itself. Specifically:
The route includes a loop or overlap near the 4th waypoint. On the map, this results in a double polyline being drawn at the overlapping section. However, during active navigation (simulation mode), the navigation puck fails to follow the intended loop. Instead of turning to follow the correct polyline, the puck continues in a straight line, effectively skipping the turn or maneuver that loops back.