Horizon safety locations

VERSION 2.1.2

The Safety Cameras entitlement for a TomTom API key is only available upon request. Contact us to get started.

Legal Restrictions.

Local law in certain jurisdictions can prohibit the use of speed camera warning and detection systems. To the extent a TomTom customer uses the Speed Camera Data in connection with any such warning or detection system, the TomTom customer shall do so entirely at their own risk. TomTom shall be entitled to immediately cease the delivery of the Speed Camera Data or part thereof in the event delivery of such Speed Camera Data infringes applicable law. In order to comply with the applicable legal requirements, application developers can use the Navigation SDK to filter safety cameras with the purpose of:

  • disabling/enabling all types of safety cameras for an individual country
  • disabling/enabling all types of safety cameras for a region of a country
  • disabling/enabling some types of safety cameras (fixed/mobile) for a specific country

Safety locations are used worldwide to enforce speed limits and other traffic regulations. Cameras are frequently placed in high-risk areas to minimize the impact of difficult and dangerous stretches of road.

The Safety Cameras SDK provides data for various types of safety locations, including:

Configuring horizon

Having completed the Retrieving horizon data guide, you are now able to subscribe for horizon updates and start navigation to retrieve horizon data.

Specifying horizon options

To subscribe to safety location horizon elements, create HorizonOptions via the buildHorizonOptions method and specify SafetyLocationElementType in the list of element types of interest. The horizon path parameters defined within buildHorizonOptions are appropriate for most use cases and can be utilized in both free driving and active guidance scenarios. The buildHorizonOptions method will create a HorizonOptions instance with a main path search distance that is the minimum between 25 km and the remaining route length when navigating with a route, or 10 km when free driving.

val horizonOptions =
buildHorizonOptions(listOf(SafetyLocationElementType))
When using the Extended flavor

The Extended flavor of Maps and Navigation SDK for Android is only available upon request. Contact us to get started.

If you prefer to configure the horizon path parameters manually, you can create the HorizonOptions as follows:

1val horizonOptions =
2 HorizonOptions(
3 elementTypes = listOf(SafetyLocationElementType),
4 mainPathSearchOptions =
5 MainPathSearchOptions(
6 searchDistancePolicy = ExplicitDistancePolicy(
7 searchDistance = PathSearchDistance(maxHorizonLength = Distance.kilometers(2)),
8 ),
9 ),
10 subPathSearchOptions = listOf(
11 SubPathSearchOptions(
12 searchDistance = PathSearchDistance(maxHorizonLength = Distance.meters(100)),
13 ),
14 ),
15 numberOfPaths = 10,
16 )

Registering a horizon updated listener

Before starting navigation, register a HorizonUpdatedListener to listen to horizon updates for the horizon options you defined.

tomTomNavigation.addHorizonUpdatedListener(horizonOptions, horizonUpdatedListener)

Starting navigation

Then, start navigation with a route as described in the Retrieving horizon data guide.

1val routePlan = RoutePlan(route, routePlanningOptions)
2val navigationOptions = NavigationOptions(routePlan)
3tomTomNavigation.start(navigationOptions)

Retrieving safety locations

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

If a zone safety location stretches beyond the end of the horizon, the SDK only provides data for the part of the zone within the horizon length. As the horizon is extended ahead of the vehicle while the vehicle moves along the zone safety location, the end offset of the safety location horizon element is updated accordingly.

Filtering safety locations

Some of the retrieved safety locations might be located in a country where it is prohibited to use devices that alert the driver about safety locations. Moreover, the legislation of a country may also be ambiguous with respect to safety locations. You have to assess the situation and, if necessary, filter out safety locations for which it is illegal to issue alerts.

Crossing into another country implies complying with different legislation. To filter out safety locations from countries where reporting them is illegal, you can take the following steps:

  1. Configure HorizonOptions to also subscribe to country information in addition to safety locations:
    val horizonOptions =
    buildHorizonOptions(listOf(SafetyLocationElementType, CountryInformationElementType))
  2. Implement a listener to get horizon updates and filter out safety locations:
    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 { horizonSnapshot ->
    10 horizonSnapshot.mainPath()?.let { mainPath ->
    11 val forbiddenCountryInformationElements =
    12 mainPath.retrieveForbiddenCountryInformationElements()
    13 val safetyLocationElements =
    14 mainPath.retrieveSafetyLocationElements()
    15
    16 val legalSafetyLocationElements =
    17 retrieveLegalSafetyLocationElements(
    18 safetyLocationElements,
    19 forbiddenCountryInformationElements,
    20 )
    21
    22 Log.v(TAG, "Safety locations for which alerts are legal:")
    23 legalSafetyLocationElements.forEach { safetyLocation ->
    24 Log.v(TAG, "$safetyLocation")
    25 }
    26 }
    27 }
    28 }
    29
    30 override fun onHorizonReset(options: HorizonOptions) {
    31 Log.v(TAG, "Horizon reset")
    32 }
    33
    34 override fun onSnapshotUpdated(
    35 options: HorizonOptions,
    36 snapshot: HorizonSnapshot,
    37 ) {
    38 horizonSnapshot = snapshot
    39 }
  3. Extract the country information elements that correspond to countries where reporting safety locations is illegal.
    1private fun HorizonPath.retrieveForbiddenCountryInformationElements(): List<CountryInformationElement> =
    2 getElements(CountryInformationElementType)
    3 .map { it as CountryInformationElement }
    4 .filter {
    5 // Allows only country information elements from Germany or the US state of California
    6 (it.countryCodeIso3 == "DEU") ||
    7 (it.countryCodeIso3 == "USA" && it.regionCode == "CA")
    8 }
  4. Filter out the safety locations from those countries:
    1private fun retrieveLegalSafetyLocationElements(
    2 safetyLocationElements: List<SafetyLocationElement>,
    3 forbiddenCountryInformationElements: List<CountryInformationElement>,
    4): List<SafetyLocationElement> = safetyLocationElements.filterNot { safetyLocationElement ->
    5 forbiddenCountryInformationElements.map { countryInformationElement ->
    6 safetyLocationElement.isInCountry(countryInformationElement)
    7 }.any { it }
    8}
    9
    10private fun SafetyLocationElement.isInCountry(
    11 countryInformationElement: CountryInformationElement,
    12): Boolean = if (this.pathId == countryInformationElement.pathId) {
    13 this.startOffset >= countryInformationElement.startOffset &&
    14 this.startOffset < countryInformationElement.endOffset ||
    15 this.endOffset > countryInformationElement.startOffset &&
    16 this.endOffset <= countryInformationElement.endOffset
    17} else {
    18 false
    19}

You can also filter out specific safety location types:

1private fun HorizonPath.retrieveSafetyLocationElements(): List<SafetyLocationElement> =
2 getElements(SafetyLocationElementType)
3 .map { it as SafetyLocationElement }
4 .filter { element ->
5 // Filters out safety locations of type RestrictionCamera
6 element.safetyLocation.type != SafetyLocationType.RestrictionCamera
7 }

Next steps

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