mapbox / mapbox-navigation-ios

Turn-by-turn navigation logic and UI in Swift on iOS
https://docs.mapbox.com/ios/navigation/
Other
860 stars 310 forks source link

Calibrate course based on heading changes #2340

Open 1ec5 opened 4 years ago

1ec5 commented 4 years ago

We currently use only the course from GPS location updates, ignoring the heading from the magnetometer, because the phone doesn’t necessarily face the same direction that the user is headed. For example, it could be sitting in a cupholder rotated to the side to face the driver, in which case the heading is constantly offset.

Unfortunately, the course is just as noisy as any other component in a GPS location update, typically noisier than headings. The map can end up rotating back and forth even as the user travels in a straight line, potentially wasting energy as the map performs unnecessary symbol placement (see mapbox/mapbox-gl-native#9031).

We should ignore changes in course that aren’t accompanied by changes in heading. The assumption is that any real change in course would require the phone to face a different direction, whether it’s in a car cupholder or in a pedestrian’s hand. (However, #2215 would switch to headings for walking directions, ignoring the course outright.)

RouteController currently passes the course to MBNavigator verbatim and never uses the heading:

https://github.com/mapbox/mapbox-navigation-ios/blob/05c1f9fe54a9a0aa16767537ded952d7c313d0d7/MapboxCoreNavigation/RouteController.swift#L190 https://github.com/mapbox/mapbox-navigation-ios/blob/05c1f9fe54a9a0aa16767537ded952d7c313d0d7/MapboxCoreNavigation/MBNavigator.swift#L10

LegacyRouteController only disqualifies a course if the device doesn’t support course readings at all (such as in an iPhone simulator). It doesn’t even use the heading for the so-called heading-based turn completion heuristic:

https://github.com/mapbox/mapbox-navigation-ios/blob/05c1f9fe54a9a0aa16767537ded952d7c313d0d7/MapboxCoreNavigation/LegacyRouteController.swift#L100-L107 https://github.com/mapbox/mapbox-navigation-ios/blob/05c1f9fe54a9a0aa16767537ded952d7c313d0d7/MapboxCoreNavigation/LegacyRouteController.swift#L457-L460 https://github.com/mapbox/mapbox-navigation-ios/blob/dc9f1e9be68b18ca4f57882c98e0a58e85461507/MapboxCoreNavigation/CLLocationDirection.swift#L16-L18

NavigationMapView uses the course verbatim and doesn’t use the heading for anything, though #2215 would switch to heading for walking directions:

https://github.com/mapbox/mapbox-navigation-ios/blob/05c1f9fe54a9a0aa16767537ded952d7c313d0d7/MapboxNavigation/NavigationMapView.swift#L344

/ref #2046 /cc @mapbox/navigation-ios @avi-c @d-prukop @mapbox/navnative

1ec5 commented 4 years ago

@Aurora-Boreal pointed out this paper, which is focused on Android APIs but could provide some insights on the right heuristics to use when using both course and heading.

a-kosak-mbx commented 4 years ago

We currently use only the course from GPS location updates, ignoring the heading from the magnetometer, because the phone doesn’t necessarily face the same direction that the user is headed.

We are currently working on algorithm that couples car and phone coordinate systems even if they are relatevely floating. If phone is in cupholder it's easy enough to translate magnetometer data into car coordinate systems and fuse it with gyroscopes for higher stability and reliablility.