Skip to content

Update the mapSDK puck in NavigationMapView with location course for bearing #3123

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

Merged
merged 7 commits into from
Jul 2, 2021

Conversation

ShanMa1991
Copy link
Contributor

@ShanMa1991 ShanMa1991 commented Jun 28, 2021

Description

This pr is to fix #3105, to remove the manually puck heading update code in navigationMapView.moveUserLocation(to:animated:) introduced in #2968

Implementation

Use the simulatesLocation to switch between the course and heading as the puck bearing source, instead of manually stop and update the puck layer.

Create a SimulatedLocationManger based NavigationLocationProvider to provide location update during simulated session.

Add the RouteOverlayController as the location consumer for the mapView, to receive the location update.

Use the renderFrameFinished to check the location change under simulation, and push location update to allow the vanishing route line synced with puck.

Stop the location update from the CarPlay before navigation session starts, to avoid the background navigator trigger.

Screenshots or Gifs

puckUpdate

@ShanMa1991 ShanMa1991 added op-ex Refactoring, Tech Debt or any other operational excellence work. UI Work related to visual components, Android Auto, Camera, 3D, voice, etc. labels Jun 28, 2021
@ShanMa1991 ShanMa1991 added this to the v2.0.0 (GA) milestone Jun 28, 2021
@ShanMa1991 ShanMa1991 self-assigned this Jun 28, 2021
@ShanMa1991
Copy link
Contributor Author

According to the log below, the sequence when we call func presentAndRemoveNavigationMapView(_:completion:) in ViewController is as:

1. navigator starts, providing route progress
2. Two location updates source exist, one from the still existing navigationMapView with the `passiveLocationManager`, one from the navigator
3. the `present(navigationViewController, animated: true)` is called, the navigationMapView is later removed from the superView and set to nil, only one location update source exists.

So when we try to start the navigation, the navigator starts before the navigationMapView is removed. It caused rerouting behavior under simulation.

@ShanMa1991 ShanMa1991 force-pushed the shan/puck-course-bearing-3105 branch from 1afc1ae to e2e795d Compare June 29, 2021 21:23
@ShanMa1991 ShanMa1991 changed the base branch from release-v2.0 to main June 30, 2021 19:50
@ShanMa1991 ShanMa1991 force-pushed the shan/puck-course-bearing-3105 branch from e2e795d to 9285ff3 Compare June 30, 2021 19:51
@ShanMa1991 ShanMa1991 marked this pull request as ready for review June 30, 2021 23:44
@ShanMa1991 ShanMa1991 requested review from 1ec5, MaximAlien and a team June 30, 2021 23:44
Copy link
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

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

There’s one part of the PR that I’m unclear about – probably just an awkward situation that needs comments – but otherwise it’s good to go once that’s resolved.

@@ -262,6 +271,7 @@ open class NavigationMapView: UIView {
self.mapView.location.options.puckType = .puck3D(configuration)
}
}
mapView.location.options.puckBearingSource = simulatesLocation ? .course : .heading
Copy link
Contributor

Choose a reason for hiding this comment

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

This would reuse the property’s didSet for consistency:

Suggested change
mapView.location.options.puckBearingSource = simulatesLocation ? .course : .heading
simulatesLocation = true

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestion, I'll improve this part.

Comment on lines 175 to 184
var simulatesLocation: Bool = true {
didSet {
if simulatesLocation {
mapView.location.options.puckBearingSource = .course

} else {
mapView.location.options.puckBearingSource = .heading
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a comment explaining the logic in this property and its didSet? At a glance, I get the impression that the puck would be rotated based on the course during simulation (as in SimulatedLocationManager or ReplayLocationManager) but rotated based on the heading during actual navigation. Intuitively, I’d expect the puck to be rotated based on the course when it’s available, only falling back to heading otherwise.

Is the discrepancy because of tunnel simulation? I suppose in a deep tunnel, there may be no course because there’s no GPS location update, but there would likely be a heading because the magnetometer would still function normally.

(#1942 tracks rotating the camera (and puck) based on heading while walking, regardless of the location manager.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So right now, the simulatesLocation dose two thing:

  1. To decide the puck bearing source. During simulated navigation, we use the course for puck bearing because we have no heading data. When the simulated navigation ends, the turn-by-turn navigation is using CLHeading( maybe we should set the puck bearing from course as default when the navigator starts? ).
  2. When set up mapView, to keep the route line synced with location puck. if we're using the default userCourseView, the route line in navigation is listening to mapView location update while the userCourseView is using animation through route controller update. We should keep them synced by sending location update. If we're using map puck, in simulated navigation, the location update is should be triggered and sent to the map by frame.
    https://github.com/mapbox/mapbox-navigation-ios/blob/1b7ebf366baf7773d967c0805a8659b51a840c77/Sources/MapboxNavigation/NavigationMapView.swift#L340-L350

So I think the best way to implement the heading/course, and the simulated location update is to split the simulatesLocation into two properties. One is public to control the puck bearing source, which could adjust to tunnel check or walking situation and used by customer on their purposes. One is to control the location update from the location manager, decide whether should we manually sending location update to the location consumers.

@@ -262,6 +262,7 @@ open class NavigationMapView: UIView {
self.mapView.location.options.puckType = .puck3D(configuration)
}
}
mapView.location.options.puckBearingSource = .course
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right now the map puck bearing source defaults to the location course, while the simulatesLocation is only used to notify the navigationMapView that we're using simulated location provider, and keep the puck synced with vanishing route line synced with user location layer.

@ShanMa1991 ShanMa1991 force-pushed the shan/puck-course-bearing-3105 branch from 8a6c9b3 to 9e8edb3 Compare July 2, 2021 15:59
@ShanMa1991 ShanMa1991 merged commit 97f962d into main Jul 2, 2021
@ShanMa1991 ShanMa1991 deleted the shan/puck-course-bearing-3105 branch July 2, 2021 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
op-ex Refactoring, Tech Debt or any other operational excellence work. UI Work related to visual components, Android Auto, Camera, 3D, voice, etc.
Projects
None yet
2 participants