# Route generation

> **Note (legacy): A newer version of the Navigation SDK is available**
> 
> This page uses v1.6.2 of the Mapbox Navigation SDK. A newer version of the SDK is available. Learn about the latest version, v2.22.2, in the [Navigation SDK documentation](https://docs.mapbox.com/android/navigation/v2/guides/turn-by-turn-navigation/route-generation/).

 Navigation UI SDK

This guide does not describe any specific options in the Navigation UI SDK, but the concepts described in this guide are important to understand if you are using the Navigation UI SDK. You will need to provide either a valid `DirectionsRoute` object or both an origin and destination `Point` object to the `NavigationView`. If you provide both, only the `DirectionsRoute` will be used.

For details on default and custom route *styling* using the Navigation UI, see [Map and application design](https://docs.mapbox.com/android/legacy/navigation/guides/styles/).

## Request a route

The Navigation SDK uses routes generated by the [Mapbox Directions API](https://docs.mapbox.com/api/navigation/#directions). After you've created [a `MapboxNavigation` object](https://docs.mapbox.com/android/legacy/navigation/guides/install/#create-a-mapboxnavigation-object), you can use its `requestRoutes()` method to request routes from the Mapbox Directions API.

The method accepts a built `RouteOptions` object. The `RouteOptions` class has convenient methods for setting the various route parameters available in the [Directions API documentation](https://docs.mapbox.com/api/navigation/#directions). To set default route options, use [`defaultNavigationOptionsBuilder`](https://docs.mapbox.com/android/navigation/v2/api/1.6.2/libnavigation-core/-core/com.mapbox.navigation.core/-mapbox-navigation/-companion/default-navigation-options-builder.html) when creating your `MapboxNavigation` object.

You can use the `RouteOptions.builder` class to create a `RouteOptions` class as you create a new route request. There are many methods that can be used to customize your request, three of which are required:

-   `accessToken()`
-   `coordinates()`
    -   `origin`: [a `Point` object](https://docs.mapbox.com/android/java/guides/geojson/#geometries)
    -   `destination`: [a `Point` object](https://docs.mapbox.com/android/java/guides/geojson/#geometries)

```kotlin
mapboxNavigation.requestRoutes(
	RouteOptions.builder()
		.accessToken(MAPBOX_TOKEN)
		.coordinates(listOf(originPoint, destinationPoint))
		.build()
)
```

The `origin` and `destination` `Point` coordinates need to be in a single list of `Point`s. The `origin` should be the first `Point` in the list and the `destination` should be the last `Point`. If there are any other `Point`s in the list between the `origin` and `destination`, these `Point`s are considered [waypoints](#include-waypoint-stops).

## Route request status

The `mapboxNavigation.requestRoutes()` method's only required parameter is the built `RouteOptions` object. An optional second parameter is a `RoutesRequestCallback` interface object. The Navigation SDK's `RoutesRequestCallback` interface provides methods, which inform you about the status of a route request.

```kotlin
private val routesReqCallback = object : RoutesRequestCallback {

	override fun onRoutesReady(routes: List<DirectionsRoute>) {

	}

	override fun onRoutesRequestFailure(throwable: Throwable, routeOptions: RouteOptions) {

	}

	override fun onRoutesRequestCanceled(routeOptions: RouteOptions {

	}
}
```

Add the `RoutesRequestCallback` object to the `mapboxNavigation.requestRoutes()` method:

```kotlin
mapboxNavigation.requestRoutes(
	RouteOptions.builder()
		.accessToken(MAPBOX_TOKEN)
		.coordinates(listOf(originPoint, destinationPoint))
		.geometries(RouteUrl.GEOMETRY_POLYLINE6)
		.profile(RouteUrl.PROFILE_DRIVING)
		.build(),

		routesReqCallback
)
```

> **Note: Trip session state**
> 
> Calling `requestRoutes()` affects the `TripSessionState`. If you call `startTripSession()` without calling `requestRoutes()`, you'll be in ["Free Drive" state](https://docs.mapbox.com/android/legacy/navigation/guides/free-drive/). If you call `requestRoutes()` after `startTripSession()`, you'll be in "Active Guidance" state.

## Include waypoint stops

If your navigation experience involves several stops along the way to the final destination, you can add up to 25 coordinates (including the origin and destination) to the `RouteOptions` builder. The coordinates are treated as stops between the origin and destination [`Points`](https://docs.mapbox.com/android/java/guides/geojson/#geometries) (in the order that you add them — the first waypoint `Point` is the first stop along the route):

```kotlin
mapboxNavigation.requestRoutes(
	RouteOptions.builder()

		.accessToken(MAPBOX_TOKEN)

		.coordinates(listOf(originPoint, firstWaypoint, secondWaypoint, thirdWaypoint, destinationPoint))

		.geometries(RouteUrl.GEOMETRY_POLYLINE6)
		.profile(RouteUrl.PROFILE_DRIVING)
		.build()
)
```

## Changed routes

Use the Navigation SDK's `RouteObserver` interface if you want to know when the routes list has changed.

```kotlin
private val routeObserver = object : RouteObserver {
	override fun onRoutesChanged(routes: List<DirectionsRoute>) {

	}
}
```

Register the `RouteObserver` interface with [your already-instantiated `MapboxNavigation` object](https://docs.mapbox.com/android/legacy/navigation/guides/install/#create-a-mapboxnavigation-object).

```kotlin
mapboxNavigation.registerRouteObserver(routeObserver)
```

Don't forget to unregister the `RouteObserver` interface:

```kotlin
override fun onStop() {
	super.onStop()
	mapView.onStop()
	mapboxNavigation.unregisterRoutesObserver(routeProgressObserver)
}
```

## Request a route in a specific direction

The Navigation SDK can make a Directions API request that takes into account the direction the device is facing. The returned route will be ideal for the device's particular *bearing*.

**Device location**: In the adjacent diagram, the blue dot with white stroke is the device location.

**Bearing**: The bearing tells you the direction that a device is facing. It is an angle clockwise from true north between 0 and 359. For example, if the device is facing north, the bearing will be 0°, and if the device is facing due east, the bearing will be 90°. In the adjacent diagram, the pink arrow is the direction that the device is facing (which is due west or 270°).

**Tolerance**: Tolerance is the range of degrees by which a route can deviate from the bearing angle and still be recommended. The semi-transparent blue area illustrates tolerance. In this example tolerance is 90° (45° in either direction from the bearing angle).

The `RouteOptions.builder()`'s `bearingsList()` method is a list of a `double` lists. The first `double` value in a single list, the bearing, should be an angle clockwise from true north between 0 and 355. The second value in a single list, the tolerance, should be the range of degrees by which the angle can deviate (recommended value is 45 or 90).

If the `bearingsList()` method is used, the list of `double` pairs must be the same length as the list of `Point`s passed through the `coordinates()` method. But, you can skip a coordinate and show its position in the `double` list with the null value.

```kotlin
mapboxNavigation.requestRoutes(
	RouteOptions.builder()
		.accessToken(MAPBOX_TOKEN)
		.coordinates(listOf(originPoint, destinationPoint))
		.profile(RouteUrl.PROFILE_DRIVING)

		.bearingsList(listOf(listOf(bearing, tolerance)))

		.build()
)
```

Request a route including the bearing value from the device's last known `Location` object:

```kotlin
mapboxMap.locationComponent.lastKnownLocation?.let { location ->

	val lastKnownBearing = location.bearing
	val tolerance = 90

	mapboxNavigation.requestRoutes(
	RouteOptions.builder()
		.accessToken(MAPBOX_TOKEN)
		.coordinates(listOf(originPoint, destinationPoint))
		.profile(RouteUrl.PROFILE_DRIVING)

		.bearingsList(listOf(listOf(lastKnownBearing, tolerance))

		.build()
	)
}
```

## Specify a side of the road to approach

You can state from which side of the road to approach a waypoint by adding `approaches` to the `RouteOptions` builder. There are three options found in the `DirectionsCriteria` class:

-   `"unrestricted"` (default): the route can approach waypoints from either side of the road. Use `DirectionsCriteria.APPROACH_UNRESTRICTED`.
-   `"curb"`: return the route in a way that, upon arrival, the waypoint is located on the side corresponding to the `driving_side` of the region where the route is situated. Use `DirectionsCriteria.APPROACH_CURB`.
-   `null`: if no option is specified, it is translated internally to `""`, which has the same result as setting an approach to `"unrestricted"`. Use `null`.

If provided, the list of approaches must be the same length as the list of coordinates (including the `origin` and the `destination`) and in that particular order (`origin`, waypoints, `destination`).

If a re-route occurs and `approaches` were used to fetch the first `DirectionsRoute`, the new route fetched will take the same `approaches` criteria into account.

```kotlin
mapboxNavigation.requestRoutes(
	RouteOptions.builder()
		.accessToken(MAPBOX_TOKEN)
		.coordinates(listOf(originPoint, firstWaypoint, secondWaypoint, thirdWaypoint, destinationPoint))
		.profile(RouteUrl.PROFILE_DRIVING)

		.approachesList(listOf(DirectionsCriteria.APPROACH_UNRESTRICTED,
		DirectionsCriteria.APPROACH_UNRESTRICTED, DirectionsCriteria.APPROACH_CURB, null, DirectionsCriteria.APPROACH_CURB))

		.build()
)
```

## More about route generation

Read more about route generation in the [Localization](https://docs.mapbox.com/android/legacy/navigation/guides/localization/) guide, which walks through how to customize the language and units of measurement returned for both text and voice instructions or use the language preferences set on the device.