Horizon safety locations
The Safety Cameras SDK for Android 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:
Red light cameras
Fixed speed cameras
Mobile speed cameras
Speed enforcement zones
Restricted areas
Danger zones
Risk zones
Configuring the horizon engine
Having completed the Retrieving horizon data
guide, you are now able to set up the horizon engine and start navigation to retrieve horizon data.
Specifying horizon options
To subscribe to safety location horizon elements, specify SafetyLocationElementType
in the list of element types of interest.
1private val horizonOptionsSafetyLocations =2 HorizonOptions(3 elementTypes = listOf(SafetyLocationElementType),4 mainPathSearchOptions =5 MainPathSearchOptions(6 searchDistancePolicy = RouteLengthPolicy,7 ),8 )
Configuring navigation
The Safety Cameras feature requires configuring the safety locations data source before starting navigation. You need to create a SafetyLocationConfiguration
object and inject it into the navigation Configuration
constructor. When you set up the SafetyLocationConfiguration
object, specify the API key that grants your application access to the TomTom Safety Cameras service.
In addition to configuring the safety locations data source, you also need to increase the navigation tile prefetching radius to 15 km. This ensures that enough map data is prefetched to allow exposing safety location data at the current vehicle position. With a smaller prefetching radius there is no guarantee that a zone safety location is exposed in the horizon.
1val navigationTileStore =2 NavigationTileStore.create(3 this,4 NavigationTileStoreConfiguration(5 apiKey = TOMTOM_API_KEY,6 prefetchingConfiguration = PrefetchingConfiguration(prefetchedAreaRadius = PREFETCHED_AREA_RADIUS),7 ),8 )9val navigationConfiguration =10 Configuration(11 context = this,12 locationProvider = locationProvider,13 navigationTileStore = navigationTileStore,14 routePlanner = routePlanner,15 safetyLocationsConfiguration = SafetyLocationsConfiguration(TOMTOM_API_KEY),16 )
Registering a horizon updated listener
Before starting navigation, register a HorizonUpdatedListener
to listen to horizon updates for the horizon options you defined.
val tomTomNavigation = OnlineTomTomNavigationFactory.create(navigationConfiguration)tomTomNavigation.addHorizonUpdatedListener(horizonOptionsSafetyLocations, 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:
- Configure
HorizonOptions
to also subscribe tocountry information
in addition tosafety locations
:1private val horizonOptions =2 HorizonOptions(3 elementTypes = listOf(SafetyLocationElementType, CountryInformationElementType),4 mainPathSearchOptions =5 MainPathSearchOptions(6 searchDistancePolicy = RouteLengthPolicy,7 ),8 ) - Implement a listener to get horizon updates and filter out safety locations:
1private val horizonUpdatedListener =2 object : HorizonUpdatedListener {3 private var horizonSnapshot: HorizonSnapshot? = null45 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()1516 val legalSafetyLocationElements =17 retrieveLegalSafetyLocationElements(18 safetyLocationElements,19 forbiddenCountryInformationElements,20 )2122 Log.v(TAG, "Safety locations for which alerts are legal:")23 legalSafetyLocationElements.forEach { safetyLocation ->24 Log.v(TAG, "$safetyLocation")25 }26 }27 }28 }2930 override fun onHorizonReset(options: HorizonOptions) {31 Log.v(TAG, "Horizon reset")32 }3334 override fun onSnapshotUpdated(35 options: HorizonOptions,36 snapshot: HorizonSnapshot,37 ) {38 horizonSnapshot = snapshot39 }
- 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 California6 (it.countryCodeIso3 == "DEU") ||7 (it.countryCodeIso3 == "USA" && it.regionCode == "CA")8 } - 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}910private 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.endOffset17} else {18 false19}
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 RestrictionCamera6 element.safetyLocation.type != SafetyLocationType.RestrictionCamera7 }
Next steps
Now that you know how to retrieve horizon hazards data, here are the recommendations on what to explore next: