Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions Sources/MapboxCoreNavigation/CoreConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public extension Notification.Name {
/**
Posted when `RouteController` receives a user location update representing movement along the expected route.

The user info dictionary contains the keys `RouteController.NotificationUserInfoKey.routeProgressKey`, `RouteController.NotificationUserInfoKey.locationKey`, and `RouteController.NotificationUserInfoKey.rawLocationKey`.
The user info dictionary contains the keys `RouteController.NotificationUserInfoKey.routeProgressKey`, `RouteController.NotificationUserInfoKey.locationKey`, and `RouteController.NotificationUserInfoKey.rawLocationKey`, and `RouteController.NotificationUserInfoKey.headingKey`.

- seealso: `passiveLocationManagerDidUpdate`
*/
Expand All @@ -174,14 +174,14 @@ public extension Notification.Name {
/**
Posted after the user diverges from the expected route, just before `RouteController` attempts to calculate a new route.

The user info dictionary contains the key `RouteController.NotificationUserInfoKey.locationKey`.
The user info dictionary contains the keys `RouteController.NotificationUserInfoKey.locationKey` and `RouteController.NotificationUserInfoKey.headingKey`.
*/
static let routeControllerWillReroute: Notification.Name = .init(rawValue: "RouteControllerWillReroute")

/**
Posted when `RouteController` obtains a new route in response to the user diverging from a previous route.

The user info dictionary contains the keys `RouteController.NotificationUserInfoKey.locationKey` and `RouteController.NotificationUserInfoKey.isProactiveKey`.
The user info dictionary contains the keys `RouteController.NotificationUserInfoKey.locationKey`, `RouteController.NotificationUserInfoKey.isProactiveKey`, and `RouteController.NotificationUserInfoKey.headingKey`.
*/
static let routeControllerDidReroute: Notification.Name = .init(rawValue: "RouteControllerDidReroute")

Expand Down Expand Up @@ -274,6 +274,16 @@ extension RouteController {
*/
public static let rawLocationKey: NotificationUserInfoKey = .init(rawValue: "rawLocation")

/**
A key in the user info dictionary of a `Notification.Name.routeControllerProgressDidChange` notification. The corresponding value is a `CLHeading` object representing the current user heading.
*/
public static let headingKey: NotificationUserInfoKey = .init(rawValue: "heading")

/**
A key in the user info dictionary of a `Notification.Name.routeControllerProgressDidChange` notification. The corresponding value is a `CLHeading` object representing the current raw user heading.
*/
public static let rawHeadingKey: NotificationUserInfoKey = .init(rawValue: "rawHeading")

/**
A key in the user info dictionary of a `Notification.Name.currentRoadNameDidChange` notification. The corresponding value is a `NSString` object representing the current road name.
*/
Expand Down
23 changes: 17 additions & 6 deletions Sources/MapboxCoreNavigation/RouteController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ open class RouteController: NSObject {
*/
public weak var delegate: RouterDelegate?

var heading: CLHeading?
/**
The route controller’s heading.
*/
public var heading: CLHeading?
var isFirstLocation: Bool = true

/**
Expand Down Expand Up @@ -220,6 +223,10 @@ open class RouteController: NSObject {
}
}

public func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
heading = newHeading
}

/**
Asynchronously updates NavNative navigator with the new `RouteProgress`.

Expand Down Expand Up @@ -464,11 +471,15 @@ open class RouteController: NSObject {
delegate?.router(self, didUpdate: progress, with: location, rawLocation: rawLocation)

//Fire the notification (for now)
NotificationCenter.default.post(name: .routeControllerProgressDidChange, object: self, userInfo: [
NotificationUserInfoKey.routeProgressKey: progress,
NotificationUserInfoKey.locationKey: location, //guaranteed value
NotificationUserInfoKey.rawLocationKey: rawLocation, //raw
])

var userInfo: [RouteController.NotificationUserInfoKey: Any] = [
.routeProgressKey: progress,
.locationKey: location, // guaranteed value
.rawLocationKey: rawLocation, // raw
]
userInfo[.headingKey] = heading

NotificationCenter.default.post(name: .routeControllerProgressDidChange, object: self, userInfo: userInfo)
}

private func announcePassage(of spokenInstructionPoint: SpokenInstruction, routeProgress: RouteProgress) {
Expand Down
10 changes: 6 additions & 4 deletions Sources/MapboxCoreNavigation/RouteProgress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ open class RouteProgress: Codable {
self.calculateLegsCongestion()
}

func reroutingOptions(with current: CLLocation) -> RouteOptions {
func reroutingOptions(from location: CLLocation) -> RouteOptions {
let oldOptions = routeOptions
let user = Waypoint(coordinate: current.coordinate)
let user = Waypoint(coordinate: location.coordinate)

if (current.course >= 0) {
user.heading = current.course
// A pedestrian can turn on a dime; there's no problem with a route that starts out by turning the pedestrian around.
let transportType = currentLegProgress.currentStep.transportType
if transportType != .walking && location.course >= 0 {
user.heading = location.course
user.headingAccuracy = RouteProgress.reroutingAccuracy
}
let newWaypoints = [user] + remainingWaypointsForCalculatingRoute()
Expand Down
23 changes: 16 additions & 7 deletions Sources/MapboxCoreNavigation/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ public protocol Router: CLLocationManagerDelegate {
*/
var rawLocation: CLLocation? { get }

/**
The most recently received user heading, if any.
*/
public var heading: CLHeading? { get }

/**
If true, the `RouteController` attempts to calculate a more optimal route for the user on an interval defined by `RouteControllerProactiveReroutingInterval`. If `refreshesRoute` is enabled too, reroute attempt will be fired after route refreshing.
*/
Expand Down Expand Up @@ -329,7 +334,7 @@ extension InternalRouter where Self: Router {
*/
func calculateRoutes(from origin: CLLocation, along progress: RouteProgress, completion: @escaping IndexedRouteCompletionHandler) {
routeTask?.cancel()
let options = progress.reroutingOptions(with: origin)
let options = progress.reroutingOptions(from: origin)

lastRerouteLocation = origin

Expand All @@ -350,16 +355,20 @@ extension InternalRouter where Self: Router {

func announceImpendingReroute(at location: CLLocation) {
delegate?.router(self, willRerouteFrom: location)
NotificationCenter.default.post(name: .routeControllerWillReroute, object: self, userInfo: [
RouteController.NotificationUserInfoKey.locationKey: location,
])

var userInfo: [RouteController.NotificationUserInfoKey: Any] = [
.locationKey: location,
]
userInfo[.headingKey] = heading

NotificationCenter.default.post(name: .routeControllerWillReroute, object: self, userInfo: userInfo)
}

func announce(reroute newRoute: Route, at location: CLLocation?, proactive: Bool) {
var userInfo = [RouteController.NotificationUserInfoKey: Any]()
if let location = location {
userInfo[.locationKey] = location
}
// to do: WAS IT OKAY TO REMOVE THIS IF LET?
userInfo[.locationKey] = location
userInfo[.headingKey] = heading
userInfo[.isProactiveKey] = proactive
NotificationCenter.default.post(name: .routeControllerDidReroute, object: self, userInfo: userInfo)
delegate?.router(self, didRerouteAlong: routeProgress.route, at: location, proactive: proactive)
Expand Down
17 changes: 14 additions & 3 deletions Sources/MapboxNavigation/NavigationMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -663,9 +663,10 @@ open class NavigationMapView: UIView {
Updates `UserLocationStyle` to provided location.

- parameter location: Location, where `UserLocationStyle` should be shown.
- parameter heading: Optional heading, which allows camera to move using heading instead of bearing for walking directions.
- parameter animated: Property, which determines whether `UserLocationStyle` transition to new location will be animated.
*/
public func moveUserLocation(to location: CLLocation, animated: Bool = false) {
public func moveUserLocation(to location: CLLocation, with heading: CLHeading? = nil, animated: Bool = false) {
guard CLLocationCoordinate2DIsValid(location.coordinate) else { return }

mostRecentUserCourseViewLocation = location
Expand All @@ -676,11 +677,11 @@ open class NavigationMapView: UIView {
}

if case let .courseView(view) = userLocationStyle {
move(view, to: location, animated: animated)
move(view, to: location, with: heading, animated: animated)
}
}

func move(_ userCourseView: UserCourseView, to location: CLLocation, animated: Bool = false) {
func move(_ userCourseView: UserCourseView, to location: CLLocation, with heading: CLHeading? = nil, animated: Bool = false) {
// While animating to overview mode, don't animate the puck.
let duration: TimeInterval = animated && navigationCamera.state != .transitionToOverview ? 1 : 0
UIView.animate(withDuration: duration, delay: 0, options: [.curveLinear]) { [weak self] in
Expand All @@ -690,6 +691,16 @@ open class NavigationMapView: UIView {
}

let cameraOptions = CameraOptions(cameraState: mapView.cameraState)

if let heading = heading {
userCourseView.update(location: location,
pitch: cameraOptions.pitch!,
direction: heading.trueHeading,
animated: animated,
navigationCameraState: navigationCamera.state)
return
}

userCourseView.update(location: location,
pitch: cameraOptions.pitch!,
direction: cameraOptions.bearing!,
Expand Down
4 changes: 3 additions & 1 deletion Sources/MapboxNavigation/NavigationViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,9 @@ extension NavigationViewController: NavigationServiceDelegate {

let movePuckToCurrentLocation = !(userArrivedAtWaypoint && snapsUserLocationAnnotationToRoute && preventRerouting)
if movePuckToCurrentLocation {
navigationMapView?.moveUserLocation(to: location, animated: true)
let isWalking = progress.currentLegProgress.currentStep.transportType == .walking
let heading = isWalking ? navigationService.locationManager.heading : nil
navigationMapView?.moveUserLocation(to: location, with: heading, animated: true)
}

attemptToHighlightBuildings(progress, navigationMapView: navigationMapView)
Expand Down