OffRoadTomTomNavigationFactory
Off-road navigation is designed for areas without roads, such as rural or wilderness areas or where traditional road navigation systems are inaccurate. You can enable off-road navigation using routes imported from GPS Exchange Format (GPX) files.
To create a default off-road TomTomNavigation, use the OffRoadTomTomNavigationFactory class:
val configuration = Configuration(
context = context,
locationProvider = customLocationProvider
)
val tomTomNavigation = OffRoadTomTomNavigationFactory.create(configuration)
Next parse the imported GPX file to turn it onto a list of GeoLocation. You can use your own or a third-party GPX file parser library to create a list of geolocations from an imported GPX file. For this example com.github.ticofab:android-gpx-parser:v2.2.0 is being used.
import android.content.Context
import com.tomtom.sdk.location.GeoLocation
import com.tomtom.sdk.location.GeoPoint
import io.ticofab.androidgpxparser.parser.GPXParser
fun getGeoLocationsFromGpxFileTracks(context: Context, fileName: String): List<GeoLocation> =
context.assets.open(fileName).use { inputStream ->
GPXParser().parse(inputStream)
// list of coordinates from tracks
.tracks
.flatMap { it.trackSegments }
.flatMap { it.trackPoints }
.map { GeoLocation(GeoPoint(it.latitude, it.longitude)) }
}
fun getGeoLocationsFromGpxFileWaypoints(context: Context, fileName: String): List<GeoLocation> =
context.assets.open(fileName).use { inputStream ->
GPXParser().parse(inputStream)
// list of coordinates from waypoints
.waypoints
.map { GeoLocation(GeoPoint(it.latitude, it.longitude)) }
}
Once you have the GeoLocation list, create the Route object. For example see implementation of createRoute function:
/**
* Creates a [route][Route] from a [GeoLocation] list representing a route.
* The created route contains:
* - One leg with geometry as provided [locations].
* - Origin as the first point from provided [locations].
* - Destination as the last point from provided [locations].
* - Total length of the route.
* - Calculated route points.
*
* The created route doesn't contain:
* - Travel, departure, and arrival time.
* - Guidance instructions.
*
* @param locations The geometry of the [route][Route].
* @return Created [route][Route]
* @throws IllegalArgumentException when [locations] doesn't contain at least two points.
*/
fun createRoute(locations: List<GeoLocation>): Route {
require(locations.size >= 2) { "Locations must contains at least 2 points." }
// Calculate the total distance covered by all items in the input geoLocations list.
val distances = locations.runningFoldIndexed(Distance.ZERO) { index, distance, location ->
if (index == 0) {
Distance.ZERO
} else {
distance + location.position.distanceTo(locations[index - 1].position)
}
}.drop(1) // remove Distance.ZERO added as initial value
val routeSummary = Summary(
length = distances.last(),
travelTime = Duration.ZERO,
departureTimeWithZone = Calendar.getInstance(),
arrivalTimeWithZone = Calendar.getInstance()
)
val routeLeg = RouteLeg(
points = locations.map { it.position },
instructions = emptyList(),
summary = routeSummary
)
val origin = RouteStop(
id = RouteStopId(),
place = Place(locations.first().position),
navigableCoordinates = listOf(locations.first().position),
routeOffset = Distance.ZERO
)
val destination = RouteStop(
id = RouteStopId(),
place = Place(locations.last().position),
navigableCoordinates = listOf(locations.last().position),
routeOffset = routeSummary.length
)
// Create a route
return Route(
id = RouteId(),
summary = routeSummary,
legs = listOf(routeLeg),
routeStops = listOf(origin, destination),
sections = Sections(),
modificationHistory = RouteModificationHistory(
RouteTimestamp(0L, Calendar.getInstance())
),
// Create a list of route points
routePoints = locations.mapIndexed { index, location ->
RoutePoint(
location.position,
distances[index],
Duration.ZERO,
null,
)
}
)
}
When the user deviates or returns to the active route, the navigation engine sends route-tracking state updates to the listener.
Routes can be followed or unfollowed, depending on whether the user is on the planned route or has deviated from it. Route tracking state updates are provided through the listener method onRouteTrackingStateUpdated(routeTrackingState), which is called throughout the route navigation process. To handle these updates, implement the RouteTrackingStateUpdatedListener interface.
override fun onRouteTrackingStateUpdated(routeTrackingState: RouteTrackingState) {
val lastKnownPosition = tomtomNavigation.locationProvider.lastKnownLocation?.position ?: return
this.routeTrackingState.postValue(routeTrackingState to position)
}
private val routeTrackingStateObserver = Observer<Pair<RouteTrackingState, GeoPoint>> { trackingState ->
if (currentState is MainViewState.Navigating && isOffRoad()) {
val state = trackingState.first
if (state is RouteTrackingState.Deviated) {
// One of the possible ways of deviation handling is to show a dotted line indicating the shortest path back to the planned route from the user's current location,
// using the coordinates from backToRoutePoint, the point where the user has deviated from the planned route.
drawBackToRouteDottedPolyline(listOf(state.backToRoutePoint, trackingState.second))
} else {
// When the user is back on the planned route the previously added dotted line can be removed.
removeBackToRouteDottedPolyline()
}
}
}
To start receiving route tracking state updates, use tomTomNavigation.addRouteTrackingStateUpdatedListener(routeTrackingStateUpdatedListener):
val routeTrackingStateUpdatedListener: RouteTrackingStateUpdatedListener = ...
tomTomNavigation.addRouteTrackingStateUpdatedListener(routeTrackingStateUpdatedListener)
To stop receiving route tracking state updates, remove the previously added observer tomTomNavigation.removeRouteTrackingStateUpdatedListener(routeTrackingStateUpdatedListener):
tomTomNavigation.removeRouteTrackingStateUpdatedListener(routeTrackingStateUpdatedListener)
Finally, remember that an imported off-road route from a GPX file is parsed as it is and not checked for impassable places or closed roads. It also provides no routing guidance.
Important: This is a Public Preview API. It may be changed or removed at any time.
Functions
Creates a TomTomNavigation instance for off-road navigation.