Open IAntolK opened 4 years ago
Hello, @IAntolK! Let's see if I got it correct: during turn-by-turn navigation on a real bike ride, navigation map view starts in a landscape mode and everything works correct, but after some time, it switches to portrait mode and User Puck does not point to correct heading anymore?
If it is so, I have few questions to help identify the issue:
Yes, you got it. If device is oriented to landscape left, user puck points up and camera is set to point in user direction. After some time (device orientation is landscape left all the time), map rotates for 90 degrees to the left. User puck and camera stil point up. It happens while riding a bike in straight direction with relatively contant speed (30-40 km/h). I think the problem is that mapbox desn't update heading calculation when device orientation changes. Because, when device orientation is changed from portrait to landscape, it still calculates heading like in portrait mode - top of the device points to north. I think, after some time, during the ride, it updates heading calculation based on current orientation (landscape) but I don't know why because status bar orientation and device orientation don't change.
https://www.dropbox.com/s/eqcgai8drouegoz/RPReplay_Final1592487517.mov?dl=0
This is example with followWithHeading
user tracking mode set.
Bug is definitely in the framework. I've run this example https://docs.mapbox.com/ios/navigation/examples/advanced/ with only one change mapView?.userTrackingMode = .followWithHeading
and succeed to reproduce the bug.
Steps to reproduce:
follow
to followWithHeading
Link to video: https://www.dropbox.com/s/iexn06qegvkkcfh/FFTW9970.mov?dl=0.
@Udumft any updates on this one? This is a blocker for our project for almost 2 months now. :(
The team will be investigating this issue and we'll report back as soon as we know more.
First implementation was with
userTrackingMode
set tofollowWithHeading
. Second one was withuserTrackingMode
set to follow and I was changing map view direction to fit currentCLLocationManager
heading. The last one was withuserTrackingMode
set to follow and I was changing camera to point currentCLLocationManager
heading.
Each of these implementations sets the map SDK’s MGLMapView.userTrackingMode
property. During turn-by-turn navigation, NavigationMapView uses its own puck and camera implementation in order to more accurately track the user’s direction of motion. This behavior is controlled by the tracksUserCourse
property. Setting userTrackingMode
overrides this behavior with the less sophisticated map SDK behavior. #1741 would clean up the relationship between MGLMapView and NavigationMapView in this regard.
Heading is affected by the heading orientation. The map SDK normally does account for heading orientation, but it could be that the navigation SDK’s customizations prevent the map SDK’s heading orientation correction from taking effect. The navigation SDK doesn’t currently use heading in any capacity, so it isn’t setting CLLocationManager.headingOrientation
. But if you’re feeding the location manager’s heading into the map, then you’ll probably need to set that property. We can use this issue to track setting the property out of the box, since it couldn’t hurt to set it even if we aren’t using it yet.
As the name implies, tracksUserCourse
is specifically designed to track CLLocation.course
rather than CLHeading. This design is ideal for driving and may also be suitable for biking. However, if you prefer to track heading instead of course, that would be good feedback for #2215, which does that for walking. (That PR still has a to-do item about accounting for heading orientation changes.)
Thanks for the answer, but I don't understand what can we do to solve the problem. We are not using NavigationMapView, just MGLMapView, drawing a route, showing navigation directions, and tracking user location (see https://www.dropbox.com/s/eqcgai8drouegoz/RPReplay_Final1592487517.mov?dl=0). Are you suggesting, if we want to track heading, to set tracking mode to none and update camera manually? We've tried that but the same problem occurred.
Are there any code examples of how we can implement custom design, as on the attached video, using NavigationViewController or NavigationMapView?
We are not using NavigationMapView, just MGLMapView, drawing a route, showing navigation directions, and tracking user location
Ah, I was under the assumption that it was simply a heavily customized NavigationMapView (which is in turn a heavily customized subclass of MGLMapView). It sounds like this issue doesn’t involve the navigation SDK at all (even if your application uses the MapboxDirections framework). The mapbox-gl-native-ios repository may be a better place to report the issue to get some attention on it.
Are there any code examples of how we can implement custom design, as on the attached video, using NavigationViewController or NavigationMapView?
It should be feasible to implement a custom design like that with NavigationMapView. As it is merely a subclass of MGLMapView, it should behave almost identically if you were to replace MGLMapView with NavigationMapView. NavigationMapView comes with additional conveniences for common navigation-related customizations, like displaying a route line. In principle, NavigationViewController is also designed for your use case; however, it unfortunately isn’t optimized for landscape orientation (#1139), so you’d probably still have to continue to implement your own view controller for now.
I am using custom mapbox turn-by-turn navigation in our bike app. Navigation should work in landscape mode and camera should follow user with heading. Everything works fine when I'm testing the navigation in office by simulating location changes, but the problem occurs when I put the device on bike and start to ride. After few hundred meters map view changes orientation to portrait and, because device is in landscape/faceUp mode, user heading indicator shows wrong direction. I've tried with few approaches but result was the same. First implementation was with
userTrackingMode
set tofollowWithHeading
. Second one was withuserTrackingMode
set to follow and I was changing map view direction to fit currentCLLocationManager
heading. The last one was withuserTrackingMode
set to follow and I was changing camera to point currentCLLocationManager
heading.The last approach code example MGLMapView initialization:
mapNavigationView.styleURL = mapStyle.url mapNavigationView.delegate = self mapNavigationView.showsUserLocation = true mapNavigationView.userTrackingMode = .follow mapNavigationView.compassView.isHidden = true mapNavigationView.attributionButton.isHidden = true mapNavigationView.logoView.isHidden = true mapNavigationView.direction = 0
output .heading .asDriverIgnoringErrors() .drive(onNext: { [unowned self] in guard self.isUserNavigating else { return } var heading: CLLocationDirection switch UIApplication.shared.statusBarOrientation { case .landscapeLeft: heading = $0 - 90 case .landscapeRight: heading = $0 + 90 default: heading = $0 } self.zoomToUser(withHeading: heading) }) .disposed(by: disposeBag)
func zoomToUser( fromDistance: CLLocationDistance = Constants.Map.distance, withPitch pitch: CGFloat = Constants.Map.pitch, withAltitude altitude: CLLocationDistance = Constants.Map.altitude, withHeading heading: CLLocationDirection = Constants.Map.heading ) { guard let center = mapNavigationView.userLocation?.coordinate else { return } let camera = MGLMapCamera(lookingAtCenter: center, acrossDistance: fromDistance, pitch: pitch, heading: heading) camera.altitude = altitude mapNavigationView.fly(to: camera, completionHandler: nil) }
I thought that device orientation changes was the cause of the problem, but it occurs when device is in landscape/faceUp mode all the time too.