Skip to content
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

### Other changes

* This release includes a possible fix for spurious rerouting when passing an intermediate waypoint. ([#1869](https://github.com/mapbox/mapbox-navigation-ios/pull/1869))
Copy link
Contributor

Choose a reason for hiding this comment

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

This is still fixed, but via this PR rather than #1869.

* The `NavigationSettings.shared` property is now accessible in Objective-C code as `MBNavigationSettings.sharedSettings`. ([#1882](https://github.com/mapbox/mapbox-navigation-ios/pull/1882))
* Adding property `RouteController.nearbyCoordinates`, which offers similar behavior to `RouteLegProgress.nearbyCoordinates`, which the addition of step lookahead/lookbehind in multi-leg routes. ([#1883](https://github.com/mapbox/mapbox-navigation-ios/pull/1883))

## v0.25.0 (November 22, 2018)

Expand Down
2 changes: 1 addition & 1 deletion MapboxCoreNavigation/CLLocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ extension CLLocation {

// If the upcoming maneuver a sharp turn, only look at the current step for snapping.
// Otherwise, we may get false positives from nearby step coordinates
if let upcomingStep = legProgress.upComingStep,
if let upcomingStep = legProgress.upcomingStep,
let initialHeading = upcomingStep.initialHeading,
let finalHeading = upcomingStep.finalHeading {

Expand Down
8 changes: 4 additions & 4 deletions MapboxCoreNavigation/EventDetails.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,10 @@ extension RouteLegProgress: Encodable {

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(upComingStep?.instructions, forKey: .upcomingInstruction)
try container.encodeIfPresent(upComingStep?.maneuverType.description, forKey: .upcomingType)
try container.encodeIfPresent(upComingStep?.maneuverDirection.description, forKey: .upcomingModifier)
try container.encodeIfPresent(upComingStep?.names?.joined(separator: ";"), forKey: .upcomingName)
try container.encodeIfPresent(upcomingStep?.instructions, forKey: .upcomingInstruction)
try container.encodeIfPresent(upcomingStep?.maneuverType.description, forKey: .upcomingType)
try container.encodeIfPresent(upcomingStep?.maneuverDirection.description, forKey: .upcomingModifier)
try container.encodeIfPresent(upcomingStep?.names?.joined(separator: ";"), forKey: .upcomingName)
try container.encodeIfPresent(currentStep.instructions, forKey: .previousInstruction)
try container.encode(currentStep.maneuverType.description, forKey: .previousType)
try container.encode(currentStep.maneuverDirection.description, forKey: .previousModifier)
Expand Down
18 changes: 6 additions & 12 deletions MapboxCoreNavigation/RouteController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,8 @@ open class RouteController: NSObject, Router {
Monitors the user's course to see if it is consistantly moving away from what we expect the course to be at a given point.
*/
func userCourseIsOnRoute(_ location: CLLocation) -> Bool {
// if we have yet to travel along the current leg, don't check for heading conformance
guard routeProgress.currentLegProgress.distanceTraveled > 0 else {
movementsAwayFromRoute = 0
return true
}

let nearByCoordinates = routeProgress.currentLegProgress.nearbyCoordinates
guard let calculatedCourseForLocationOnStep = location.interpolatedCourse(along: nearByCoordinates) else { return true }
let nearbyCoordinates = routeProgress.nearbyCoordinates
guard let calculatedCourseForLocationOnStep = location.interpolatedCourse(along: nearbyCoordinates) else { return true }

let maxUpdatesAwayFromRouteGivenAccuracy = Int(location.horizontalAccuracy / Double(RouteControllerIncorrectCourseMultiplier))

Expand Down Expand Up @@ -421,7 +415,7 @@ extension RouteController: CLLocationManagerDelegate {
}

func checkForFasterRoute(from location: CLLocation) {
guard let currentUpcomingManeuver = routeProgress.currentLegProgress.upComingStep else {
guard let currentUpcomingManeuver = routeProgress.currentLegProgress.upcomingStep else {
return
}

Expand Down Expand Up @@ -539,7 +533,7 @@ extension RouteController: CLLocationManagerDelegate {
let currentStepProgress = routeProgress.currentLegProgress.currentStepProgress

// The intersections array does not include the upcoming maneuver intersection.
if let upcomingStep = routeProgress.currentLegProgress.upComingStep, let upcomingIntersection = upcomingStep.intersections, let firstUpcomingIntersection = upcomingIntersection.first {
if let upcomingStep = routeProgress.currentLegProgress.upcomingStep, let upcomingIntersection = upcomingStep.intersections, let firstUpcomingIntersection = upcomingIntersection.first {
intersections += [firstUpcomingIntersection]
}

Expand All @@ -563,7 +557,7 @@ extension RouteController: CLLocationManagerDelegate {

// Bearings need to normalized so when the `finalHeading` is 359 and the user heading is 1,
// we count this as within the `RouteControllerMaximumAllowedDegreeOffsetForTurnCompletion`
if let upcomingStep = routeProgress.currentLegProgress.upComingStep, let finalHeading = upcomingStep.finalHeading, let initialHeading = upcomingStep.initialHeading {
if let upcomingStep = routeProgress.currentLegProgress.upcomingStep, let finalHeading = upcomingStep.finalHeading, let initialHeading = upcomingStep.initialHeading {
let initialHeadingNormalized = initialHeading.wrap(min: 0, max: 360)
let finalHeadingNormalized = finalHeading.wrap(min: 0, max: 360)
let userHeadingNormalized = location.course.wrap(min: 0, max: 360)
Expand All @@ -582,7 +576,7 @@ extension RouteController: CLLocationManagerDelegate {
}
}

let step = routeProgress.currentLegProgress.upComingStep?.maneuverLocation ?? routeProgress.currentLegProgress.currentStep.maneuverLocation
let step = routeProgress.currentLegProgress.upcomingStep?.maneuverLocation ?? routeProgress.currentLegProgress.currentStep.maneuverLocation
let userAbsoluteDistance = step.distance(to: location.coordinate)
let lastKnownUserAbsoluteDistance = routeProgress.currentLegProgress.currentStepProgress.userDistanceToManeuverLocation

Expand Down
43 changes: 42 additions & 1 deletion MapboxCoreNavigation/RouteProgress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,42 @@ open class RouteProgress: NSObject {
*/
@objc public var currentLegProgress: RouteLegProgress

@objc public var nearbyCoordinates: [CLLocationCoordinate2D] {

var coords: [CLLocationCoordinate2D] = []

//If we're on the first step of a leg, add coords from previous leg.
if let firstStep = currentLegProgress.leg.steps.first,
currentLegProgress.currentStep == firstStep,
legIndex > 0 {

let lastLeg = route.legs[legIndex - 1]

if let lastStep = lastLeg.steps.last,
let priorCoords = lastStep.coordinates {
coords += priorCoords
}
}

//Add nearby coordinates from current step.
coords += currentLegProgress.nearbyCoordinates

//If we're on the last step of a leg, add coordinates from the next leg.
if let lastStep = currentLegProgress.leg.steps.last,
currentLegProgress.currentStep == lastStep,
legIndex < (route.legs.count - 1) {

let nextLeg = route.legs[legIndex + 1]

if let nextStep = nextLeg.steps.first,
let upcomingCoords = nextStep.coordinates {
coords += upcomingCoords
}
}

return coords
}

/**
Tuple containing a `CongestionLevel` and a corresponding `TimeInterval` representing the expected travel time for this segment.
*/
Expand Down Expand Up @@ -321,7 +357,12 @@ open class RouteLegProgress: NSObject {

If there is no `upcomingStep`, nil is returned.
*/
@available(*, deprecated, renamed: "upcomingStep")
@objc public var upComingStep: RouteStep? {
return upcomingStep
}

@objc public var upcomingStep: RouteStep? {
guard stepIndex + 1 < leg.steps.endIndex else {
return nil
}
Expand Down Expand Up @@ -369,7 +410,7 @@ open class RouteLegProgress: NSObject {
*/
@objc public var nearbyCoordinates: [CLLocationCoordinate2D] {
let priorCoords = priorStep?.coordinates ?? []
let upcomingCoords = upComingStep?.coordinates ?? []
let upcomingCoords = upcomingStep?.coordinates ?? []
let currentCoords = currentStep.coordinates ?? []
let nearby = priorCoords + currentCoords + upcomingCoords
assert(!nearby.isEmpty, "Step must have coordinates")
Expand Down
2 changes: 1 addition & 1 deletion MapboxCoreNavigationTests/LocationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class LocationTests: XCTestCase {

var setup: (progress: RouteProgress, firstLocation: CLLocation) {
let progress = RouteProgress(route: route)
let firstCoord = progress.currentLegProgress.nearbyCoordinates.first!
let firstCoord = progress.nearbyCoordinates.first!
let firstLocation = CLLocation(latitude: firstCoord.latitude, longitude: firstCoord.longitude)

return (progress, firstLocation)
Expand Down
16 changes: 8 additions & 8 deletions MapboxCoreNavigationTests/NavigationServiceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class NavigationServiceTests: XCTestCase {

let legProgress: RouteLegProgress = navigationService.router.routeProgress.currentLegProgress

let firstCoord = legProgress.nearbyCoordinates.first!
let firstCoord = navigationService.router.routeProgress.nearbyCoordinates.first!
let firstLocation = CLLocation(coordinate: firstCoord, altitude: 5, horizontalAccuracy: 10, verticalAccuracy: 5, course: 20, speed: 4, timestamp: Date())

let remainingStepCount = legProgress.remainingSteps.count
Expand Down Expand Up @@ -124,7 +124,7 @@ class NavigationServiceTests: XCTestCase {
navigation.locationManager!(navigation.locationManager, didUpdateLocations: [firstLocation])
XCTAssertEqual(navigation.router.location!.coordinate, firstLocation.coordinate, "Check snapped location is working")

let firstCoordinateOnUpcomingStep = navigation.router.routeProgress.currentLegProgress.upComingStep!.coordinates!.first!
let firstCoordinateOnUpcomingStep = navigation.router.routeProgress.currentLegProgress.upcomingStep!.coordinates!.first!
let firstLocationOnNextStepWithNoSpeed = CLLocation(coordinate: firstCoordinateOnUpcomingStep, altitude: 0, horizontalAccuracy: 10, verticalAccuracy: 10, course: 10, speed: 0, timestamp: Date())

navigation.locationManager!(navigation.locationManager, didUpdateLocations: [firstLocationOnNextStepWithNoSpeed])
Expand All @@ -144,9 +144,9 @@ class NavigationServiceTests: XCTestCase {
navigation.locationManager!(navigation.locationManager, didUpdateLocations: [firstLocation])
XCTAssertEqual(navigation.router.location!.coordinate, firstLocation.coordinate, "Check snapped location is working")

let firstCoordinateOnUpcomingStep = navigation.router.routeProgress.currentLegProgress.upComingStep!.coordinates!.first!
let firstCoordinateOnUpcomingStep = navigation.router.routeProgress.currentLegProgress.upcomingStep!.coordinates!.first!

let finalHeading = navigation.router.routeProgress.currentLegProgress.upComingStep!.finalHeading!
let finalHeading = navigation.router.routeProgress.currentLegProgress.upcomingStep!.finalHeading!
let firstLocationOnNextStepWithDifferentCourse = CLLocation(coordinate: firstCoordinateOnUpcomingStep, altitude: 0, horizontalAccuracy: 30, verticalAccuracy: 10, course: -finalHeading, speed: 5, timestamp: Date())

navigation.locationManager!(navigation.locationManager, didUpdateLocations: [firstLocationOnNextStepWithDifferentCourse])
Expand All @@ -163,7 +163,7 @@ class NavigationServiceTests: XCTestCase {
navigation.locationManager!(navigation.locationManager, didUpdateLocations: [firstLocation])
XCTAssertEqual(navigation.router.location!.coordinate, firstLocation.coordinate, "Check snapped location is working")

let futureCoord = Polyline(navigation.router.routeProgress.currentLegProgress.nearbyCoordinates).coordinateFromStart(distance: 100)!
let futureCoord = Polyline(navigation.router.routeProgress.nearbyCoordinates).coordinateFromStart(distance: 100)!
let futureInaccurateLocation = CLLocation(coordinate: futureCoord, altitude: 0, horizontalAccuracy: 1, verticalAccuracy: 200, course: 0, speed: 5, timestamp: Date())

navigation.locationManager!(navigation.locationManager, didUpdateLocations: [futureInaccurateLocation])
Expand All @@ -181,9 +181,9 @@ class NavigationServiceTests: XCTestCase {
route.accessToken = "foo"
let navigation = MapboxNavigationService(route: route, directions: directions)
let router = navigation.router!
let firstCoord = router.routeProgress.currentLegProgress.nearbyCoordinates.first!
let firstCoord = router.routeProgress.nearbyCoordinates.first!
let firstLocation = CLLocation(latitude: firstCoord.latitude, longitude: firstCoord.longitude)
let coordNearStart = Polyline(router.routeProgress.currentLegProgress.nearbyCoordinates).coordinateFromStart(distance: 10)!
let coordNearStart = Polyline(router.routeProgress.nearbyCoordinates).coordinateFromStart(distance: 10)!

navigation.locationManager(navigation.locationManager, didUpdateLocations: [firstLocation])

Expand All @@ -196,7 +196,7 @@ class NavigationServiceTests: XCTestCase {

// The course should not be the interpolated course, rather the raw course.
XCTAssertEqual(directionToStart, router.location!.course, "The course should be the raw course and not an interpolated course")
XCTAssertFalse(facingTowardsStartLocation.shouldSnap(toRouteWith: facingTowardsStartLocation.interpolatedCourse(along: router.routeProgress.currentLegProgress.nearbyCoordinates)!, distanceToFirstCoordinateOnLeg: facingTowardsStartLocation.distance(from: firstLocation)), "Should not snap")
XCTAssertFalse(facingTowardsStartLocation.shouldSnap(toRouteWith: facingTowardsStartLocation.interpolatedCourse(along: router.routeProgress.nearbyCoordinates)!, distanceToFirstCoordinateOnLeg: facingTowardsStartLocation.distance(from: firstLocation)), "Should not snap")
}

//TODO: Broken by PortableRoutecontroller & MBNavigator -- needs team discussion.
Expand Down
2 changes: 1 addition & 1 deletion MapboxCoreNavigationTests/RouteProgressTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class RouteProgressTests: XCTestCase {
XCTAssertEqual(routeProgress.currentLegProgress.fractionTraveled, 0)
XCTAssertEqual(routeProgress.currentLegProgress.stepIndex, 0)
XCTAssertEqual(routeProgress.currentLegProgress.followOnStep?.description, "Turn left onto Gough Street")
XCTAssertEqual(routeProgress.currentLegProgress.upComingStep?.description, "Turn right onto Sacramento Street")
XCTAssertEqual(routeProgress.currentLegProgress.upcomingStep?.description, "Turn right onto Sacramento Street")
}

func testRouteStepProgress() {
Expand Down
2 changes: 1 addition & 1 deletion MapboxNavigation/CarPlayNavigationViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ public class CarPlayNavigationViewController: UIViewController {
tertiaryManeuver.attributedInstructionVariants = [attributedTertiary]
}

if let upcomingStep = navService.routeProgress.currentLegProgress.upComingStep {
if let upcomingStep = navService.routeProgress.currentLegProgress.upcomingStep {
let distance = distanceFormatter.measurement(of: upcomingStep.distance)
tertiaryManeuver.initialTravelEstimates = CPTravelEstimates(distanceRemaining: distance, timeRemaining: upcomingStep.expectedTravelTime)
}
Expand Down
2 changes: 1 addition & 1 deletion MapboxNavigation/NavigationMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate {

if UIDevice.current.isPluggedIn {
preferredFramesPerSecond = FrameIntervalOptions.pluggedInFramesPerSecond
} else if let upcomingStep = routeProgress.currentLegProgress.upComingStep,
} else if let upcomingStep = routeProgress.currentLegProgress.upcomingStep,
upcomingStep.maneuverDirection == .straightAhead || upcomingStep.maneuverDirection == .slightLeft || upcomingStep.maneuverDirection == .slightRight {
preferredFramesPerSecond = shouldPositionCourseViewFrameByFrame ? FrameIntervalOptions.defaultFramesPerSecond : minimumFramesPerSecond
} else if durationUntilNextManeuver > FrameIntervalOptions.durationUntilNextManeuver &&
Expand Down
6 changes: 3 additions & 3 deletions MapboxNavigation/RouteMapViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ class RouteMapViewController: UIViewController {
let defaultAltitude = mapView.defaultAltitude
let isLongRoad = routeProgress.distanceRemaining >= mapView.longManeuverDistance
let currentStep = routeProgress.currentLegProgress.currentStep
let upComingStep = routeProgress.currentLegProgress.upComingStep
let upComingStep = routeProgress.currentLegProgress.upcomingStep

//If the user is at the last turn maneuver, the map should zoom in to the default altitude.
let currentInstruction = routeProgress.currentLegProgress.currentStepProgress.currentSpokenInstruction
Expand Down Expand Up @@ -935,7 +935,7 @@ extension RouteMapViewController: NavigationViewDelegate {
guard let stepIndex = leg.steps.index(of: step) else { return }

let legProgress = RouteLegProgress(leg: leg, stepIndex: stepIndex)
guard let upcomingStep = legProgress.upComingStep else { return }
guard let upcomingStep = legProgress.upcomingStep else { return }
addPreviewInstructions(step: legProgress.currentStep, maneuverStep: upcomingStep, distance: instructionsBannerView.distance)

mapView.enableFrameByFrameCourseViewTracking(for: 1)
Expand Down Expand Up @@ -973,7 +973,7 @@ extension RouteMapViewController: StepsViewControllerDelegate {

let legProgress = RouteLegProgress(leg: router.route.legs[legIndex], stepIndex: stepIndex)
let step = legProgress.currentStep
guard let upcomingStep = legProgress.upComingStep else { return }
guard let upcomingStep = legProgress.upcomingStep else { return }

currentPreviewInstructionBannerStepIndex = router.routeProgress.remainingSteps.index(of: step)

Expand Down
2 changes: 1 addition & 1 deletion MapboxNavigation/RouteVoiceController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extension SpokenInstruction {
@available(iOS 10.0, *)
func attributedText(for legProgress: RouteLegProgress) -> NSAttributedString {
let attributedText = NSMutableAttributedString(string: text)
if let step = legProgress.upComingStep,
if let step = legProgress.upcomingStep,
let name = step.names?.first,
let phoneticName = step.phoneticNames?.first {
let nameRange = attributedText.mutableString.range(of: name)
Expand Down
2 changes: 1 addition & 1 deletion MapboxNavigationTests/NavigationViewControllerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class NavigationViewControllerTests: XCTestCase {

let navigationService = navigationViewController.navigationService!
let router = navigationService.router!
let firstCoord = router.routeProgress.currentLegProgress.nearbyCoordinates.first!
let firstCoord = router.routeProgress.nearbyCoordinates.first!
let firstLocation = location(at: firstCoord)

var poi = [CLLocation]()
Expand Down
2 changes: 1 addition & 1 deletion MapboxNavigationTests/StepsViewControllerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class StepsViewControllerTests: XCTestCase {

let stepsViewController = StepsViewController(routeProgress: routeController.routeProgress)

let firstCoord = routeController.routeProgress.currentLegProgress.nearbyCoordinates.first!
let firstCoord = routeController.routeProgress.nearbyCoordinates.first!
let firstLocation = CLLocation(coordinate: firstCoord, altitude: 5, horizontalAccuracy: 10, verticalAccuracy: 5, course: 20, speed: 4, timestamp: Date())

let lastCoord = routeController.routeProgress.currentLegProgress.remainingSteps.last!.coordinates!.first!
Expand Down