Retrieving horizon data

VERSION 1.20.0

Navigation SDK for Android is only available upon request. Contact us to get started.

Virtual Horizon acts as a digital assistant, extending the driver’s location context beyond their immediate view. It can be used by UI components to improve the driving experience, for example, by informing the driver of what is ahead. This information includes details about upcoming traffic events, vehicle restrictions, and more.

horizon image

While navigating, you can use Virtual Horizon to retrieve detailed information about the horizon ahead of the vehicle, along the possible trajectories of the vehicle across the road network. The HorizonEngine delivers this information as a combination of a HorizonPosition and a HorizonSnapshot.

The SDK provides horizon data for various elements, including:

This guide focuses on demonstrating how to utilize the HorizonEngine for extracting specific speed-related data, including the current speed limit, the distance to the next speed limit, and the value of the upcoming speed limit. These insights allow you to create navigation applications that not only guide users accurately but also enhance their road experience by keeping them well-informed.

For more in-depth information, refer to the HorizonEngine API reference.

Configuring the horizon engine

Incorporating horizon data into your navigation application requires the following steps:

Specifying horizon options

First, define the set of HorizonOptions. To indicate that you are interested in SpeedLimitElement horizon elements, specify SpeedLimitElementType in the list of element types of interest.

1private val horizonOptions =
2 HorizonOptions(
3 elementTypes = listOf(SpeedLimitElementType),
4 mainPathSearchOptions =
5 MainPathSearchOptions(
6 searchDistancePolicy =
7 ExplicitDistancePolicy(
8 searchDistance =
9 PathSearchDistance(
10 maxHorizonLength = Distance.kilometers(1),
11 ),
12 ),
13 ),
14 )

Starting navigation

Then, start navigation with a route as described in the Starting navigation guide.

But, instead of adding a listener for route progress updates, make sure you add a HorizonUpdatedListener to listen to horizon updates for the horizon options you defined.

1fun startNavigation() {
2 val tomTomNavigation = OnlineTomTomNavigationFactory.create(navigationConfiguration)
3 tomTomNavigation.addHorizonUpdatedListener(horizonOptions, horizonUpdatedListener)
4
5 val routePlan = RoutePlan(route, routePlanningOptions)
6 val navigationOptions = NavigationOptions(routePlan)
7 tomTomNavigation.start(navigationOptions)
8}

Retrieving horizon data

With navigation started, you can listen to horizon updates and retrieve horizon data.

1private val horizonUpdatedListener =
2 object : HorizonUpdatedListener {
3 private var horizonSnapshot: HorizonSnapshot? = null
4
5 override fun onPositionUpdated(
6 options: HorizonOptions,
7 position: HorizonPosition,
8 ) {
9 horizonSnapshot?.let { snapshot ->
10 position.takeIf { it.isOnRoad }?.let { position ->
11 snapshot.displayCurrentSpeedLimit(position)
12 snapshot.displayNextSpeedLimit(position)
13 }
14 }
15 }
16
17 override fun onSnapshotUpdated(
18 options: HorizonOptions,
19 snapshot: HorizonSnapshot,
20 ) {
21 horizonSnapshot = snapshot
22 }
23
24 override fun onHorizonReset(options: HorizonOptions) {
25 // do nothing
26 }
27 }

Once you have retrieved the data, you can use it to extract the value of the current speed limit.

1private fun HorizonSnapshot.displayCurrentSpeedLimit(position: HorizonPosition) {
2 mainPath()?.getElements(SpeedLimitElementType)
3 ?.firstOrNull { element -> element.startOffset < position.offset && element.endOffset >= position.offset }
4 ?.let { element -> (element as SpeedLimitElement).speedLimit }
5 ?.also { speedLimit ->
6 when (speedLimit.type) {
7 SpeedLimit.Type.Limited -> Log.v(TAG, "Speed limit value: " + speedLimit.speed)
8 SpeedLimit.Type.Unlimited -> Log.v(TAG, "Unlimited speed")
9 }
10 }
11}

You can also extract the distance to the next speed limit and the value of the next speed limit.

1private fun HorizonSnapshot.displayNextSpeedLimit(position: HorizonPosition) {
2 mainPath()?.getElements(SpeedLimitElementType)
3 ?.firstOrNull { element -> element.startOffset >= position.offset }
4 ?.let { element ->
5 Log.v(TAG, "Distance to the next speed limit: " + distanceTo(element, position))
6 (element as SpeedLimitElement).speedLimit
7 }
8 ?.also { speedLimit ->
9 when (speedLimit.type) {
10 SpeedLimit.Type.Limited -> Log.v(TAG, "Next speed limit value: " + speedLimit.speed)
11 SpeedLimit.Type.Unlimited -> Log.v(TAG, "Next, unlimited speed")
12 }
13 }
14}

Next steps

Now that you know how to retrieve horizon data, here are the recommendations on what to explore next: