Skip to content

Commit

Permalink
Merge pull request #2114 from mapbox/maxspeedAnnotations
Browse files Browse the repository at this point in the history
Add speed limit data returned by MapboxDirections.swift to the RouteProgress object
  • Loading branch information
1ec5 authored Dec 27, 2019
2 parents 77862f6 + 2a31257 commit 43825d8
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* Since pure Swift protocols cannot have optional methods, various delegate protocols now provide default no-op implementations for all their methods and conform to the `UnimplementedLogging` protocol, which can inform you at runtime when a delegate method is called but has not been implemented. Messages are sent through Apple Unified Logging and can be disabled globally through [Unifed Logging](https://developer.apple.com/documentation/os/logging#2878594), or by overriding the delegate function with a no-op implementation. ([#2230](https://github.com/mapbox/mapbox-navigation-ios/pull/2230))
* Renamed `RouteProgress.nearbyCoordinates` to `RouteProgress.nearbyShape`. ([#2275](https://github.com/mapbox/mapbox-navigation-ios/pull/2275))
* Removed `RouteLegProgress.nearbyCoordinates`. ([#2275](https://github.com/mapbox/mapbox-navigation-ios/pull/2275))
* Added the `RouteLegProgress.currentSpeedLimit` property. ([#2114](https://github.com/mapbox/mapbox-navigation-ios/pull/2114))

## v0.38.1

Expand Down
2 changes: 1 addition & 1 deletion Cartfile.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ github "CedarBDD/Cedar" "v1.0"
github "Quick/Nimble" "v8.0.4"
github "Quick/Quick" "v2.2.0"
github "ceeK/Solar" "2.1.0"
github "mapbox/MapboxDirections.swift" "472cbced199ef2d9c5c2fa49a21e8f6b249e9bf8"
github "mapbox/MapboxDirections.swift" "93a790ab18168c61a99f72b94e984b00e5bc7476"
github "mapbox/MapboxGeocoder.swift" "v0.10.2"
github "mapbox/mapbox-events-ios" "v0.9.5"
github "mapbox/mapbox-speech-swift" "v0.1.1"
Expand Down
9 changes: 8 additions & 1 deletion MapboxCoreNavigation/NavigationRouteOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ open class NavigationRouteOptions: RouteOptions {
shapeFormat = .polyline6
includesSteps = true
routeShapeResolution = .full
attributeOptions = [.congestionLevel, .expectedTravelTime]
if profileIdentifier == .walking {
attributeOptions = [.congestionLevel, .expectedTravelTime]
} else {
attributeOptions = [.congestionLevel, .expectedTravelTime, .maximumSpeedLimit]
}
includesSpokenInstructions = true
locale = Locale.nationalizedCurrent
distanceMeasurementSystem = Locale.current.usesMetricSystem ? .metric : .imperial
Expand Down Expand Up @@ -75,6 +79,9 @@ open class NavigationMatchOptions: MatchOptions {
routeShapeResolution = .full
shapeFormat = .polyline6
attributeOptions = [.congestionLevel, .expectedTravelTime]
if profileIdentifier == .automobile || profileIdentifier == .automobileAvoidingTraffic {
attributeOptions.insert(.maximumSpeedLimit)
}
includesSpokenInstructions = true
locale = Locale.nationalizedCurrent
distanceMeasurementSystem = Locale.current.usesMetricSystem ? .metric : .imperial
Expand Down
21 changes: 21 additions & 0 deletions MapboxCoreNavigation/RouteProgress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,27 @@ open class RouteLegProgress: NSObject {
return accumulatedCoordinates <= userCoordinateIndex
})
}

/**
Returns the SpeedLimit for the current position along the route. Returns SpeedLimit.invalid if the speed limit is unknown or missing.
The maximum speed may be an advisory speed limit for segments where legal limits are not posted, such as highway entrance and exit ramps. If the speed limit along a particular segment is unknown, it is set to `nil`. If the speed is unregulated along the segment, such as on the German _Autobahn_ system, it is represented by a measurement whose value is `Double.infinity`.
Speed limit data is available in [a number of countries and territories worldwide](https://docs.mapbox.com/help/how-mapbox-works/directions/).
*/
public var currentSpeedLimit: Measurement<UnitSpeed>? {
let distanceTraveled = currentStepProgress.distanceTraveled
guard let index = currentStep.shape?.indexedCoordinateFromStart(distance: distanceTraveled)?.index else {
return nil
}
let range = leg.segmentRangesByStep[stepIndex]
let speedLimit = leg.segmentMaximumSpeedLimits?[range][index]
if let speedUnit = currentStep.speedLimitUnit {
return speedLimit?.converted(to: speedUnit)
} else {
return speedLimit
}
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion MapboxCoreNavigationTests/OptionsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class OptionsTests: XCTestCase {
XCTAssertEqual(options.profileIdentifier, .automobileAvoidingTraffic)
XCTAssertEqual(options.routeShapeResolution, .full)
XCTAssertEqual(options.shapeFormat, .polyline6)
XCTAssertEqual(options.attributeOptions, [.congestionLevel, .expectedTravelTime])
XCTAssertEqual(options.attributeOptions, [.congestionLevel, .expectedTravelTime, .maximumSpeedLimit])
XCTAssertTrue(options.includesVisualInstructions)
XCTAssertTrue(options.includesSpokenInstructions)
}
Expand Down
63 changes: 61 additions & 2 deletions MapboxCoreNavigationTests/RouteProgressTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class RouteProgressTests: XCTestCase {
XCTAssertEqual(waypoints.1.map { $0.coordinate }, [coordinates.last!])
}

func routeLegProgress(options: RouteOptions, routeCoordinates: [CLLocationCoordinate2D]) -> RouteLegProgress {
func routeLeg(options: RouteOptions, routeCoordinates: [CLLocationCoordinate2D]) -> RouteLeg {
let source = options.waypoints.first!
let destination = options.waypoints.last!
options.shapeFormat = .polyline
Expand All @@ -97,7 +97,11 @@ class RouteProgressTests: XCTestCase {
RouteStep(transportType: .automobile, maneuverLocation: destination.coordinate, maneuverType: .arrive, maneuverDirection: nil, instructions: "", initialHeading: nil, finalHeading: nil, drivingSide: .right, exitCodes: nil, exitNames: nil, phoneticExitNames: nil, distance: 0, expectedTravelTime: 0, names: nil, phoneticNames: nil, codes: nil, destinationCodes: nil, destinations: nil, intersections: nil, instructionsSpokenAlongStep: nil, instructionsDisplayedAlongStep: nil),
]
steps[0].shape = LineString(routeCoordinates)
let leg = RouteLeg(steps: steps, name: "", distance: 0, expectedTravelTime: 0, profileIdentifier: .automobile)
return RouteLeg(steps: steps, name: "", distance: 0, expectedTravelTime: 0, profileIdentifier: .automobile)
}

func routeLegProgress(options: RouteOptions, routeCoordinates: [CLLocationCoordinate2D]) -> RouteLegProgress {
let leg = routeLeg(options: options, routeCoordinates: routeCoordinates)
return RouteLegProgress(leg: leg)
}

Expand Down Expand Up @@ -212,4 +216,59 @@ class RouteProgressTests: XCTestCase {
XCTAssertEqual(remainingWaypoints.count, 0,
"At the last via point after backtracking, nothing should remain")
}

func testSpeedLimits() {
let coordinates = [
CLLocationCoordinate2D(latitude: 0, longitude: 0),
CLLocationCoordinate2D(latitude: 2, longitude: 3),
CLLocationCoordinate2D(latitude: 4, longitude: 6),
CLLocationCoordinate2D(latitude: 6, longitude: 9),
CLLocationCoordinate2D(latitude: 8, longitude: 12),
CLLocationCoordinate2D(latitude: 10, longitude: 15),
CLLocationCoordinate2D(latitude: 12, longitude: 18),
]
let lineString = LineString(coordinates)

let options = RouteOptions(coordinates: [coordinates.first!, coordinates.last!])
let leg = routeLeg(options: options, routeCoordinates: coordinates)
leg.segmentMaximumSpeedLimits = [
.init(value: 10, unit: .kilometersPerHour),
.init(value: 20, unit: .milesPerHour),
nil,
.init(value: 40, unit: .milesPerHour),
.init(value: 50, unit: .kilometersPerHour),
.init(value: .infinity, unit: .kilometersPerHour),
]
let legProgress = RouteLegProgress(leg: leg)

XCTAssertEqual(legProgress.distanceTraveled, 0)
XCTAssertEqual(legProgress.currentSpeedLimit, Measurement(value: 10, unit: UnitSpeed.kilometersPerHour))
legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[1]) / 2.0
XCTAssertEqual(legProgress.currentSpeedLimit, Measurement(value: 10, unit: UnitSpeed.kilometersPerHour))

legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[1])
XCTAssertEqual(legProgress.currentSpeedLimit, Measurement(value: 20, unit: UnitSpeed.milesPerHour))
legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[1]) + lineString.distance(from: coordinates[1], to: coordinates[2]) / 2.0
XCTAssertEqual(legProgress.currentSpeedLimit, Measurement(value: 20, unit: UnitSpeed.milesPerHour))

legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[2])
XCTAssertNil(legProgress.currentSpeedLimit)
legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[2]) + lineString.distance(from: coordinates[2], to: coordinates[3]) / 2.0
XCTAssertNil(legProgress.currentSpeedLimit)

legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[3])
XCTAssertEqual(legProgress.currentSpeedLimit, Measurement(value: 40, unit: UnitSpeed.milesPerHour))
legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[3]) + lineString.distance(from: coordinates[3], to: coordinates[4]) / 2.0
XCTAssertEqual(legProgress.currentSpeedLimit, Measurement(value: 40, unit: UnitSpeed.milesPerHour))

legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[4])
XCTAssertEqual(legProgress.currentSpeedLimit, Measurement(value: 50, unit: UnitSpeed.kilometersPerHour))
legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[4]) + lineString.distance(from: coordinates[4], to: coordinates[5]) / 2.0
XCTAssertEqual(legProgress.currentSpeedLimit, Measurement(value: 50, unit: UnitSpeed.kilometersPerHour))

legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[5])
XCTAssertTrue(legProgress.currentSpeedLimit?.value.isInfinite ?? false)
legProgress.currentStepProgress.distanceTraveled = lineString.distance(to: coordinates[5]) + (lineString.distance() - lineString.distance(to: coordinates[5])) / 2.0
XCTAssertTrue(legProgress.currentSpeedLimit?.value.isInfinite ?? false)
}
}

0 comments on commit 43825d8

Please sign in to comment.