Skip to main content

Route generation

The routes used in the Navigation SDK are generated by the Mapbox Directions API. When you install the Navigation SDK, it also includes Mapbox Directions for Swift, which provides a convenient way to access the Mapbox Directions API in iOS applications.

To generate a route, you'll create a new Route object using RoutingProvider with its default implementation MapboxRoutingProvider. In most cases, you'll also use the NavigationRouteOptions class (a subclass of Mapbox Directions for Swift's RouteOptions class) to set a few options. You can specify any of the same options you could using the RouteOptions class found in Mapbox Directions for Swift, but the defaults in NavigationRouteOptions are better suited to how the Navigation SDK uses the resulting route.

Below are examples of how you can use specific options to generate routes for a few scenarios.

Request a route in a specific direction

With the Navigation SDK, you can consider the direction a user’s device is facing and request a route starting in a specific direction. To receive a route in a specific direction (for example, the direction a user is traveling or the direction a device is facing), pass in the user’s location heading value. This property corresponds to the angles in the bearings query parameter in the Mapbox Directions and Map Matching APIs.

Waypoint: In the adjacent diagram, the blue dot with white stroke is the device location. Imagine this is the first (origin) Waypoint in a Directions API request.

Heading: The Waypoint.heading can be used to influence the direction in which a route leg should begin. The heading value is the angle clockwise from true north between 0 and 359. For example, when the heading value is 0, the heading direction is due north. In the adjacent diagram, the pink arrow is the direction that the device is the heading (which is due west or 270°). Read about Waypoint.heading in more detail.

Heading accuracy: The Waypoint.headingAccuracy is the range of degrees by which a route can deviate from the Waypoint.heading angle and still be recommended. The semi-transparent blue area illustrates headingAccuracy. In this example headingAccuracy is 90° (45° in either direction from the heading angle). Read about Waypoint.headingAccuracy in more detail.

Default heading

The system sets the default value for heading to −1°, meaning it will not take the heading into account when calculating a route.

Consider the direction a device is facing

To request a route that starts in the direction that the device is facing, set Waypoint.heading to use CLHeading.trueHeading. This may be appropriate when requesting a route with the user's location as the origin before the user has started moving or for walking directions.

You can also set a Waypoint.headingAccuracy to specify the range of degrees by which a route can deviate from the Waypoint.heading angle. Though Waypoint.headingAccuracy and CLHeading.headingAccuracy have similar names, it is not appropriate to pass in the current CLHeading.headingAccuracy. CLHeading.headingAccuracy tends to result in too-strict route requests.

This can also be applied to any waypoint including the origin and any stops along the route.

if let latestLocation = navigationMapView.mapView.location.latestLocation,
let heading = latestLocation.heading {
let location = latestLocation.internalLocation
let userWaypoint = Waypoint(location: location)
userWaypoint.heading = heading.trueHeading
userWaypoint.headingAccuracy = 90.0
}

Consider the direction a user is already traveling

If you need to request a route that's continuing along the path that the user is traveling, set the Waypoint.heading to use CLLocation.course. This may be appropriate for driving directions. Consider that the phone may be in a center cup holder, facing the driver rather than the rear-view mirror, as the car moves in a forward direction. You can also set a custom Waypoint.headingAccuracy.

This can be applied to any waypoint including the origin, stops along the route, and the destination.

if let location = navigationMapView.mapView.location.latestLocation?.internalLocation {
let userWaypoint = Waypoint(location: location)
userWaypoint.heading = location.course
userWaypoint.headingAccuracy = 90.0
}

Specify a side of the road to approach

By default, routes generated will approach waypoints on either side of road. You can override the default by setting Waypoint.allowsArrivingOnOppositeSide to false. This will require that the route has the driver approach the waypoint on the same side of the road the waypoint is on. allowsArrivingOnOppositeSide corresponds to the approaches query parameter in the Mapbox Directions and Map Matching APIs.

if let location = navigationMapView.mapView.location.latestLocation?.internalLocation {
let userWaypoint = Waypoint(location: location)
userWaypoint.allowsArrivingOnOppositeSide = false
}

Include multiple stops

To request a route, create a property with a MapboxRoutingProvider instance:

let routeProvider = MapboxRoutingProvider()

The Mapbox Directions API requires at least two waypoints to generate a route. If your route involves several pick-up and drop-off points, you can add up to 25 coordinates (including the origin and destination) using the driving profile or three coordinates using the driving-traffic profile. These coordinates are treated as stops between the origin and destination in the order that you add them — the first waypoint is the origin and the second waypoint is the first stop:

let routeOptions = NavigationRouteOptions(waypoints: [
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 37.77766, longitude: -122.43199)),
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 37.77609, longitude: -122.43292)),
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 37.77536, longitude: -122.43494)),
])

routeProvider.calculateRoutes(options: routeOptions) { [weak self] result in
switch result {
case .failure(let error):
print(error.localizedDescription)
case .success(let response):
guard let route = response.routes?.first, let strongSelf = self else {
return
}

let navigationService = MapboxNavigationService(
indexedRouteResponse: indexedRouteResponse,
credentials: NavigationSettings.shared.directions.credentials,
simulating: .always
)
let navigationOptions = NavigationOptions(navigationService: navigationService)
let navigationViewController = NavigationViewController(for: indexedRouteResponse, navigationOptions: navigationOptions)
navigationViewController.delegate = strongSelf

strongSelf.present(navigationViewController, animated: true, completion: nil)
}
}

Silent waypoints

The Waypoint.separatesLegs property determines if a waypoint will be treated as a stop between legs or influence the route without specifically mentioning it in maneuver instructions.

By default Waypoint.separatesLegs is equal to true meaning the waypoint will appear in the resulting routes as a waypoint separating two legs, along with corresponding guidance instructions.

If you want to make sure that the route you request passes through the waypoint without specifically mentioning it, set Waypoint.separatesLegs equal to false.

Optimized routes

If you want to generate a route that will arrive at the waypoints in the fastest order (not necessarily in a specific order), see the Optimization API documentation.

Route generation in offline mode

MapboxRoutingProvider can be configured by Source to load online only, offline only, and online with fallback to offline routes. By default, the hybrid code is used.

let routeProvider = MapboxRoutingProvider(.offline)

More about route generation

  • Localization: Customize the language and units of measurement returned for both text and voice instructions or use the language preferences set on the device.
  • Free-drive navigation: Accurately display the user’s location outside of turn-by-turn navigation.
Was this page helpful?