Electronic horizon
Mapbox Electronic Horizon is a feature of the Mapbox Navigation SDK that surfaces map data along the probable path (or paths) of a vehicle within the road network to anticipate conditions beyond the physical "visible" horizon.
The data provided by the electronic horizon enables capabilities like adaptive cruise control, proactive driver alerts for upcoming congestion, speed change and dangerous curves, and available alternative paths. Mapbox Electronic Horizon is designed for Advanced Driver Assistance Systems (ADAS) for in-vehicle deployment, but it can also be used in mobile Android applications.
Active guidance and free drive mode
The Mapbox Navigation SDK allows users to navigate in two different modes: active guidance and free-drive mode. The electronic horizon feature works in both modes.
When navigation is in Active guidance mode the user-selected route and its metadata are used as the path for the electronic horizon.
When navigation is in Free-drive mode the electronic horizon will determine the most probable path from the vehicle's current location.
For both active guidance and free-drive, the electronic horizon and its metadata are exposed via the same interface in the Navigation SDK as described below.
Most probable path (MPP)
Mapbox Electronic Horizon represents the road network ahead of the user as a tree of edges. Each intersection has outbound edges and each edge has a probability of transition to another edge as well as metadata that can be used to implement sophisticated features on top of it.
Based on the device's location and user-selected route (if applicable), Mapbox Electronic Horizon determines the most likely path a user may take and provides a most probable path (MPP). The MPP contains data in a tree-like structure where edges have a level
attribute equal to 0
and side-branches have a level
attribute equal to 1
or higher based on their position relative to the current edge.
In most cases the electronic horizon will return one MPP, but if there are two or more alternatives at an intersection that have a similar probability (a difference less or equal to 5%) the electronic horizon might return several MPP paths. You can choose the MPP with a slightly higher probability or, if you have additional information about the road conditions, you can suggest which MPP the user should choose.
How to configure the electronic horizon
EHorizonOptions
defines the options for the EHorizon
.
Attribute | Description | Type | Default value |
---|---|---|---|
length | The minimum length of the MPP in meters. This does not include the trailingLength . The actual MPP length may be bigger. | Double in range [1.0, 10000.0] | 500 |
expansion | The number of branches to include from the MPP. When set to 0 only the MPP is returned. Higher values will result in deeper nesting. | Int in range [0, 2] | 0 |
branchLength | When expansion is anything but 0 , this specifies the minimum length in meters branches will be expanded from the MPP. | Double in range [1.0, 5000.0] | 50 |
minTimeDeltaBetweenUpdates | The minimum time which should pass between consecutive navigation statuses to update the electronic horizon (seconds). If null the horizon will be updated on each navigation status. | Double | null |
These can be specified through the NavigationOptions
.
The electronic horizon data
To get the electronic horizon data you can use callbacks
and direct calls
. With callbacks
you get only the most important data, which can be more efficient and save resources. If you need additional data (for example: edge metadata, edge shape, road object metadata) you can make a direct call
.
navigation tiles
, are downloaded, so callbacks might not fire right away.The electronic horizon callbacks
Create the EHorizonObserver
interface object:
interface EHorizonObserver {
fun onPositionUpdated(position: EHorizonPosition, distances: List<RoadObjectDistanceInfo>)
fun onRoadObjectEnter(objectEnterExitInfo: EHorizonObjectEnterExitInfo)
fun onRoadObjectExit(objectEnterExitInfo: EHorizonObjectEnterExitInfo)
fun onRoadObjectPassed(objectPassInfo: RoadObjectPassInfo)
fun onRoadObjectAdded(roadObjectId: String)
fun onRoadObjectUpdated(roadObjectId: String)
fun onRoadObjectRemoved(roadObjectId: String)
}
Register the EHorizonObserver
object with MapboxNavigation
object.
override fun onStart() {
super.onStart()
mapView.onStart()
mapboxNavigation.registerEHorizonObserver(eHorizonObserver)
}
EHorizonObserver
activates the electronic horizon module.Don't forget to unregister the EHorizonObserver
interface.
override fun onStop() {
super.onStop()
mapView.onStop()
mapboxNavigation.unregisterEHorizonObserver(eHorizonObserver)
}
The electronic horizon position
EHorizonPosition
is the current electronic horizon position
Property name | Description | Type | Optional |
---|---|---|---|
eHorizonGraphPosition | Current graph position. | EHorizonGraphPosition | No |
eHorizon | Tree of edges. | EHorizon | No |
eHorizonResultType | Result type (INITIAL for the first EHorizon and after an EHorizon reset, UPDATE for continuation of the EHorizon ) | String | No |
The electronic horizon graph position
EHorizonGraphPosition
is the position on the current EHorizon
.
Property name | Description | Type | Optional |
---|---|---|---|
edgeId | Current edge id. | Long | No |
percentAlong | The progress along the current edge [0,1) | Double | No |
The electronic horizon
EHorizon
uses map data along the probable path (or paths) of a vehicle within the road graph to surface metadata about the underlying edges of the graph for a certain distance in front of the vehicle. The electronic horizon has a tree structure that can be navigated by traversing the edges and their outgoing connections.
Property name | Description | Type | Optional |
---|---|---|---|
start | The first edge of the electronic horizon tree. | EHorizonEdge | No |
The electronic horizon edge
Property name | Description | Type | Optional |
---|---|---|---|
id | A unique identifier of the directed edge. This identifier may be different for the same actual edge in different dataset versions. | Long | No |
level | The nesting level relative to MPP inside eHorizon (0 being the MPP, 1 branches of the MPP, 2 branches of level 1 branches). | Byte | No |
probability | The probability (as a percentage) for the driver to take this edge. The probabilities of all outgoing edges on a single intersection sum up to 1. | Double | No |
out | A list of outgoing edges. | List<Edge> | No |
The electronic horizon edge metadata
Property name | Description | Type | Optional |
---|---|---|---|
heading | The heading (sometimes referred to as bearing) when starting to move along the edge in degrees (0-360). | Double | No |
length | The edge's length in meters. | Double | No |
functionRoadClass | Functional road class (as defined by OpenStreetMap). One of the following: MOTORWAY , TRUNK , PRIMARY , SECONDARY , TERTIARY , UNCLASSIFIED , RESIDENTIAL , SERVICE_OTHER . | String | No |
speedLimit | The max speed of the edge (speed limit) in meters per second. | Double | Yes |
speed | Average speed along the edge in meters per second. | Double | No |
ramp | If the edge is a ramp. | Boolean | No |
motorway | If the edge is a motorway. | Boolean | No |
bridge | If the edge is a bridge. | Boolean | No |
tunnel | If the edge is a tunnel. | Boolean | No |
toll | If there is a toll on the edge. | Boolean | No |
names | A list of road names. | List<NameInfo> | No |
laneCount | The number of lanes on the edge (does not change mid-edge). | Byte | Yes |
meanElevation | The mean elevation along the edge in meters. | Double | Yes |
curvature | Binned number denoting the curvature degree of the edge (0-15). | Byte | No |
countryCode | The ISO 3166-1 alpha-3 country code. | String | Yes |
stateCode | A state inside a country (ISO 3166-2). | String | Yes |
isRightHandTraffic | True if in the current place/state a right-hand traffic is used, false if left-hand. | Boolean | No |
isOneWay | True if current edge is one-way. | Boolean | No |
Direct calls to the electronic horizon
MapboxNavigation
object provides three objects:
roadObjectsStore
: Provides methods to get the current road object, get upcoming road objects, and add or remove custom road objects.graphAccessor
: Provides methods to get the shape and metadata for an edge (EHorizonEdge
).roadObjectMatcher
: It offers techniques for matching custom objects to the road graph and obtaining aRoadObject
. To receive matching results, set theRoadObjectMatcherObserver
.
class RoadObjectsStore {
fun getRoadObjectsOnTheEdge(edgeId: Long): Map<String, EHorizonObjectEdgeLocation>
fun getRoadObject(roadObjectId: String): RoadObject?
fun getRoadObjectIdsByEdgeIds(edgeIds: List<Long>): List<String>
fun addCustomRoadObject(roadObject: RoadObject)
fun removeCustomRoadObject(roadObjectId: String)
fun removeAllCustomRoadObjects()
fun getUpcomingRoadObjects(distances: List<RoadObjectDistanceInfo>): List<UpcomingRoadObject>
}
class GraphAccessor {
fun getEdgeShape(edgeId: Long): List<Point>?
fun getEdgeMetadata(edgeId: Long): EHorizonEdgeMetadata?
fun getPathShape(graphPath: EHorizonGraphPath): List<Point>?
fun getGraphPositionCoordinate(graphPosition: EHorizonGraphPosition): Point?
}
class RoadObjectMatcher {
fun registerRoadObjectMatcherObserver(roadObjectMatcherObserver: RoadObjectMatcherObserver)
fun matchOpenLRObject(roadObjectId: String, openLRLocation: String, openLRStandard: String)
fun matchPolylineObject(roadObjectId: String, polyline: List<Point>)
fun matchPolygonObject(roadObjectId: String, polygon: List<Point>)
fun matchGantryObject(roadObjectId: String, gantry: List<Point>)
fun matchPointObject(roadObjectId: String, point: Point)
fun cancel(roadObjectId: String)
}
interface RoadObjectMatcherObserver {
fun onRoadObjectMatched(result: Expected<RoadObject, RoadObjectMatcherError>)
}
You can get the shape and metadata of each edge from the MPP
using the following code:
override fun onPositionUpdated(
position: EHorizonPosition,
distances: List<RoadObjectDistanceInfo>
) {
val mpp = position.eHorizon.mpp()
mpp.forEach { edge ->
val edgeShape = mapboxNavigation.graphAccessor.getEdgeShape(edge.id)
val edgeMetadata = mapboxNavigation.graphAccessor.getEdgeMetadata(edgeId)
}
}
You can add a custom road object
using the following code:
val objectId = "objectId"
val openLRLocation = "CwMisiQpOhZUF/lR/eUTZGMH"
val openLRStandard = OpenLRStandard.TOM_TOM
mapboxNavigation.roadObjectMatcher.registerRoadObjectMatcherObserver(object : RoadObjectMatcherObserver {
override fun onRoadObjectMatched(result: Expected<RoadObject, RoadObjectMatcherError>) {
if (result.isValue) {
// matching finished, add object to the store
mapboxNavigation.roadObjectsStore.addCustomRoadObject(result.value!!)
} else {
// handle RoadObjectMatcherError
}
}
})
mapboxNavigation.roadObjectMatcher.matchOpenLRObject(objectId, openLRLocation, openLRStandard)
Graph path
EHorizonGraphPath
is a path on a map graph.
Property name | Description | Type | Optional |
---|---|---|---|
edges | Ids of edges on the road graph. | List<Long> | No |
percentAlongBegin | Offset from the start of the edge (0 - 1) pointing to the start of the road object on the first edge. | Double | No |
percentAlongEnd | Offset from the start of the edge (0 - 1) pointing to the end of the road object on the last edge. | Double | No |
length | Length of the path. | Double | No |
Road object edge location
RoadObjectEdgeLocation
is location of the road object on the edge.
Property name | Description | Type | Optional |
---|---|---|---|
percentAlongBegin | Offset from the start of edge (0 - 1) pointing to the beginning of road object on this edge. Will be 0 for all edges in the line-like road object except the first one in the case of point-like object percentAlongBegin == percentAlongEnd . | Double | No |
percentAlongEnd | Offset from the start of edge (0 - 1) pointing to the end of road object on this edge. Will be 1 for all edges in the line-like road object except the first one in the case of point-like object percentAlongBegin == percentAlongEnd . | Double | No |
Road object
RoadObject
is an abstract class that serves as a base for all road objects.
There are two sources of road objects:
- active route
- the electronic horizon
Objects coming from different sources might be duplicated. Duplicates will not have the same IDs.
Property name | Description | Type | Optional |
---|---|---|---|
id | Id of the road object. If you receive duplicate objects (for example, 'RoadObjectType.TUNNEL') from the electronic horizon and the active route, the two objects will not have the same IDs. | String | No |
objectType | Constant describing the object type. Available road object types are: TUNNEL , COUNTRY_BORDER_CROSSING , TOLL_COLLECTION , REST_STOP , RESTRICTED_AREA , BRIDGE , INCIDENT , CUSTOM . | Int | No |
length | Length of the object, null if the object is point-like. | Double | Yes |
location | Location of the road object. Road objects coming from the electronic horizon might have the next RoadObjectLocationType : GANTRY , OPEN_LR_LINE , OPEN_LR_POINT , POINT , POLYGON , POLYLINE . Road objects coming from the active route will have RoadObjectLocationType.ROUTE_ALERT location type only. | RoadObjectLocation | No |
provider | Provider of the road object. Might be MAPBOX or CUSTOM . | String | No |
Inheritors of the RoadObject
are: CountryBorderCrossing
, Bridge
, Custom
, Incident
, RestrictedArea
, RestStop
, TollCollection
, Tunnel
.
Road object location information
RoadObjectLocation
contains information about the location of the road object of a specific type (for example gantry, polygon, line, or point) on the road graph.
Property name | Description | Type | Optional |
---|---|---|---|
locationType | Type of the road object location. | Int | No |
shape | Geometry of the road object. | Geometry | No |
Inheritors of the RoadObjectLocation
are: GantryLocation
, OpenLRLineLocation
, OpenLRPointLocation
, PointLocation
, PolygonLocation
, PolylineLocation
, RouteAlertLocation
.
Road object distance information
RoadObjectDistanceInfo
contains information about the distance to the road object of a specific type (for example gantry, polygon, line, or point).
Property name | Description | Type | Optional |
---|---|---|---|
roadObjectId | Id of the road object. | String | No |
roadObjectType | Type of the road object. | Int | No |
distanceInfoType | Type of the distance info object. | Int | No |
Inheritors of the RoadObjectDistanceInfo
are: GantryDistanceInfo
, LineDistanceInfo
, PointDistanceInfo
, PolygonDistanceInfo
, SubGraphDistanceInfo
.
On entering or exiting an object
RoadObjectEnterExitInfo
contains information about the object that has been entered or exited.
Property name | Description | Type | Optional |
---|---|---|---|
roadObjectId | Road object id. | String | No |
enterFromStartOrExitFromEnd | If the object was entered via its start for EHorizonObserver#onRoadObjectEnter or if the object was exited via its end for EHorizonObserver#onRoadObjectExit . | Boolean | No |
type | Type of road object. | String | No |
On passing an object
RoadObjectPassInfo
contains a unique ID and the type of road object the driver has passed.
Property name | Description | Type | Optional |
---|---|---|---|
roadObjectId | Road object id. | String | No |
type | Type of road object. | String | No |
Use the electronic horizon output
The EHorizon
is a tree structure that can be navigated by traversing the edges and their outgoing connections. This can be accomplished by looping over the edges. For common cases, some utilities have been added which are described below.
Get the current Edge
To get the current edge from the EHorizon
, an EHorizon#current
utility function is provided.
Get the MPP
To collect the entire MPP from the EHorizon
, an EHorizon#mpp()
utility function is provided which returns an ordered list of edges.
To collect only the edges starting at the current edge (which is important when the trailing length is greater than 0
), pass in the current EHorizonPosition
EHorizon#mpp(position)
.