Horizon safety locations
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 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
If you prefer to configure the horizon path parameters manually, you can create the HorizonOptions as follows:
val horizonOptions = HorizonOptions( elementTypes = listOf(SafetyLocationElementType), mainPathSearchOptions = MainPathSearchOptions( searchDistancePolicy = ExplicitDistancePolicy( searchDistance = PathSearchDistance(maxHorizonLength = Distance.kilometers(2)), ), ), subPathSearchOptions = listOf( SubPathSearchOptions( searchDistance = PathSearchDistance(maxHorizonLength = Distance.meters(100)), ), ), numberOfPaths = 10, )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.
val routePlan = RoutePlan(route, routePlanningOptions)val navigationOptions = NavigationOptions(routePlan)tomTomNavigation.start(navigationOptions)Retrieving safety locations
With navigation started, you can listen to horizon updates and retrieve safety location data.
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
HorizonOptionsto also subscribe tocountry informationin addition tosafety locations:val horizonOptions =buildHorizonOptions(listOf(SafetyLocationElementType, CountryInformationElementType)) - Implement a listener to get horizon updates and filter out safety locations:
private val horizonUpdatedListener =object : HorizonUpdatedListener {private var horizonSnapshot: HorizonSnapshot? = nulloverride fun onPositionUpdated(options: HorizonOptions,position: HorizonPosition,) {horizonSnapshot?.let { horizonSnapshot ->horizonSnapshot.mainPath()?.let { mainPath ->val forbiddenCountryInformationElements =mainPath.retrieveForbiddenCountryInformationElements()val safetyLocationElements =mainPath.retrieveSafetyLocationElements()val legalSafetyLocationElements =retrieveLegalSafetyLocationElements(safetyLocationElements,forbiddenCountryInformationElements,)Log.v(TAG, "Safety locations for which alerts are legal:")legalSafetyLocationElements.forEach { safetyLocation ->Log.v(TAG, "$safetyLocation")}}}}override fun onHorizonReset(options: HorizonOptions) {Log.v(TAG, "Horizon reset")}override fun onSnapshotUpdated(options: HorizonOptions,snapshot: HorizonSnapshot,) {horizonSnapshot = snapshot}
- Extract the
country information elementsthat correspond to countries where reporting safety locations is illegal.private fun HorizonPath.retrieveForbiddenCountryInformationElements(): List<CountryInformationElement> =getElements(CountryInformationElementType).map { it as CountryInformationElement }.filter {// Allows only country information elements from Germany or the US state of California(it.countryCodeIso3 == "DEU") ||(it.countryCodeIso3 == "USA" && it.regionCode == "CA")} - Filter out the
safety locationsfrom those countries:private fun retrieveLegalSafetyLocationElements(safetyLocationElements: List<SafetyLocationElement>,forbiddenCountryInformationElements: List<CountryInformationElement>,): List<SafetyLocationElement> = safetyLocationElements.filterNot { safetyLocationElement ->forbiddenCountryInformationElements.map { countryInformationElement ->safetyLocationElement.isInCountry(countryInformationElement)}.any { it }}private fun SafetyLocationElement.isInCountry(countryInformationElement: CountryInformationElement,): Boolean = if (this.pathId == countryInformationElement.pathId) {this.startOffset >= countryInformationElement.startOffset &&this.startOffset < countryInformationElement.endOffset ||this.endOffset > countryInformationElement.startOffset &&this.endOffset <= countryInformationElement.endOffset} else {false}
You can also filter out specific safety location types:
private fun HorizonPath.retrieveSafetyLocationElements(): List<SafetyLocationElement> = getElements(SafetyLocationElementType) .map { it as SafetyLocationElement } .filter { element -> // Filters out safety locations of type RestrictionCamera element.safetyLocation.type != SafetyLocationType.RestrictionCamera }Next steps
Now that you know how to retrieve horizon safety locations, here are the recommendations on what to explore next: