TrafficManager

This module provides realtime traffic information.

It can be used individually to retrieve traffic events in an area, it can also be used by the Planner module to compute routes that will take into account the realtime traffic information, or in the Navigation module.

Notes: Only one instance of Traffic Manager can exist. The Core must be initialized before using this module.

Dependencies

This module depends on other BeNomad's module :

  • Core

Other module's dependencies :

implementation "androidx.appcompat:appcompat:1.3.0"
implementation "com.google.android.material:material:1.8.0"
implementation "androidx.core:core-ktx:1.9.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.8.10"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1"

Start

Here is a sample code that shows how the Traffic Manager can be initialized :

import com.benomad.msdk.trafficmanager.TrafficManager

TrafficManager.getInstance().start()

Once started the TrafficManager will be ready to retrieve events. It must be started before anything else.

The method will return immediately if the Traffic is not allowed in the license.

Stop

TrafficManager.getInstance().stop()

Once the traffic stopped it won't be available in the Planner or Navigation modules.

Suspend / Resume

TrafficManager.getInstance().suspend()
TrafficManager.getInstance().resume()

If the traffic is used in the Navigation module, you can use those methods to temporarily suspend the traffic automatic download triggered by the navigation. This can be useful to save data if the vehicle is not moving for a while.

getEventsAround

To retrieve events around a point you can use this method.

  • point: Center of the zone

  • radius: Radius of the zone

  • forceUpdateTraffic: if true new events will be downloaded in this zone, otherwise only the events already in cache will be used. The downloaded events will replace the ones in cache.

val lastKnownLocation = GPSManager.getLastKnownLocation()
if (TrafficManager.getInstance().isRunning() && lastKnownLocation != null) {
TrafficManager.getInstance().getEventsAround(
GeoPoint(lastKnownLocation.longitude, lastKnownLocation.latitude)
30000,
true,
object : NewEventsListener {
override fun onNewEvents(stats: TrafficStats) {
// "stats" contains data about NEW events retrieved
}
})
}

NewEventsListener

Interface used to be notified when new traffic events are retrieved.

New events are retrieved:

  • Periodically during a navigation, after a call to Navigation.startSession and until Navigation.stopSession is called.

  • After a call to TrafficManager.getEventsAround.

Mapping

The traffic events can be displayed on any MapView.

Traffic Event representation

A traffic event is represented by a polyline (traffic flow) and an optional POI (cause of the traffic event)

Traffic Flow

The polyline will represent the event flow: the impact of the traffic on the road. The color of the polyline will tell the level of traffic: low, medium, high and closed. All the colors are defined in the graphic chart:

<CLASS id="c6910" name="Traffic flow affect" scale_visibility="0.000:200.000">
<FORM type="open" name="Normal traffic" scale_validity="0.500:5.000" att_condition="1 == 0">
<PEN style="solid" width="8" color="H20F020" half_width="right"/>
</FORM>
<FORM type="open" name="Normal traffic" scale_validity="0.500:5.000" att_condition="1 == 10">
<PEN style="solid" width="6" color="H20F020" half_width="left"/>
</FORM>
<FORM type="open" name="Low traffic" scale_validity="0.500:10.000" att_condition="1 == 11">
<PEN style="solid" width="6" color="HFFA236" half_width="left"/>
</FORM>
<FORM type="open" name="Low traffic" scale_validity="0.500:10.000" att_condition="1 == 1">
<PEN style="solid" width="6" color="HFFA236" half_width="right"/>
</FORM>
<FORM type="open" name="Medium traffic" scale_validity="0.500:20.000" att_condition="1 == 2">
<PEN style="solid" width="7" color="HFB0000" half_width="right"/>
</FORM>
<FORM type="open" name="Medium traffic" scale_validity="0.500:20.000" att_condition="1 == 12">
<PEN style="solid" width="7" color="HFB0000" half_width="left"/>
</FORM>
<FORM type="open" name="High traffic" scale_validity="0.500:0.000" att_condition="1 == 3">
<PEN style="solid" width="7" color="HAE0000" half_width="right"/>
</FORM>
<FORM type="open" name="High traffic" scale_validity="0.500:0.000" att_condition="1 == 13">
<PEN style="solid" width="7" color="HAE0000" half_width="left"/>
</FORM>
<FORM type="open" name="Blocked traffic" scale_validity="0.500:0.000" att_condition="1 == 4">
<PEN style="solid" width="7" color="H000000" border="HA2B8C9" half_width="right"/>
</FORM>
<FORM type="open" name="Blocked traffic" scale_validity="0.500:0.000" att_condition="1 == 14">
<PEN style="solid" width="7" color="H000000" border="HA2B8C9" half_width="left"/>
</FORM>
<FORM type="open" name="Normal traffic" scale_validity="0.000:0.500" att_condition="1 == 0">
<PEN style="solid" width="7" unit="real" color="H20F020" half_width="right"/>
</FORM>
<FORM type="open" name="Normal traffic" scale_validity="0.000:0.500" att_condition="1 == 10">
<PEN style="solid" width="7" unit="real" color="H20F020" half_width="left"/>
</FORM>
<FORM type="open" name="Low traffic" scale_validity="0.000:0.500" att_condition="1 == 1">
<PEN style="solid" width="7" unit="real" color="HFFA236" half_width="right"/>
</FORM>
<FORM type="open" name="Low traffic" scale_validity="0.000:0.500" att_condition="1 == 11">
<PEN style="solid" width="7" unit="real" color="HFFA236" half_width="left"/>
</FORM>
<FORM type="open" name="Medium traffic" scale_validity="0.000:0.500" att_condition="1 == 2">
<PEN style="solid" width="7" unit="real" color="HFB0000" half_width="right"/>
</FORM>
<FORM type="open" name="Medium traffic" scale_validity="0.000:0.500" att_condition="1 == 12">
<PEN style="solid" width="7" unit="real" color="HFB0000" half_width="left"/>
</FORM>
<FORM type="open" name="High traffic" scale_validity="0.000:0.500" att_condition="1 == 3">
<PEN style="solid" width="7" unit="real" color="HAE0000" half_width="right"/>
</FORM>
<FORM type="open" name="High traffic" scale_validity="0.000:0.500" att_condition="1 == 13">
<PEN style="solid" width="7" unit="real" color="HAE0000" half_width="left"/>
</FORM>
<FORM type="open" name="Blocked traffic" scale_validity="0.000:0.500" att_condition="1 == 4">
<PEN style="solid" width="7" unit="real" color="H000000" border="HA2B8C9" half_width="right"/>
</FORM>
<FORM type="open" name="Blocked traffic" scale_validity="0.000:0.500" att_condition="1 == 14">
<PEN style="solid" width="7" unit="real" color="H000000" border="HA2B8C9" half_width="left"/>
</FORM>
<FORM type="open" name="Informative" scale_validity="0.000:0.500" att_condition="1 == 5">
<PEN style="solid" width="7" unit="real" color="HBFBFBF" half_width="right"/>
</FORM>
<FORM type="open" name="Informative" scale_validity="0.000:0.500" att_condition="1 == 15">
<PEN style="solid" width="7" unit="real" color="HBFBFBF" half_width="left"/>
</FORM>
</CLASS>

The colors and width of polylines can be changed here.

Traffic POI

Depending on the type of event, a POI can be displayed. All the POI are also defined in the graphic chart:

<CLASS id="c9990" name="Traffic POI" scale_visibility="0.000:3.000">
<FORM type="point" name="congestion" scale_validity="0.000:2.000" att_condition="1 == 0">
<BRUSH style="image" src="img/tmc/congestion.png"/>
</FORM>
<FORM type="point" name="road condition" scale_validity="0.000:1.000" att_condition="1 == 1">
<BRUSH style="image" src="img/tmc/road_condition.png"/>
</FORM>
<FORM type="point" name="work" scale_validity="0.000:1.000" att_condition="1 == 2">
<BRUSH style="image" src="img/tmc/work.png"/>
</FORM>
<FORM type="point" name="road blocled" att_condition="1 == 3">
<BRUSH style="image" src="img/tmc/road_blocked.png"/>
</FORM>
<FORM type="point" name="accident" att_condition="1 == 4">
<BRUSH style="image" src="img/tmc/accident.png"/>
</FORM>
<FORM type="point" name="incident" scale_validity="0.000:2.000" att_condition="1 == 5">
<BRUSH style="image" src="img/tmc/incident.png"/>
</FORM>
<FORM type="point" name="info" scale_validity="0.000:1.000" att_condition="1 == 6">
<BRUSH style="image" src="img/tmc/info.png"/>
</FORM>
<FORM type="point" name="lane restriction" scale_validity="0.000:1.000" att_condition="1 == 7">
<BRUSH style="image" src="img/tmc/lane_restriction.png"/>
</FORM>
</CLASS>

The POI resources must be deployed in the Assets along with the graphic chart.

Show / Hide events on map

You can chose to show or hide the events flow and POI independently. To change the visibility on any given MapView:

mapView?.getMapStyle()?.showTraffic(showFlow, showPOI)

Planner

If the TrafficManager is running, you can plan a route with the traffic information.

First, you need to retrieve the traffic events located in the area of the route (see getEventsAround section)

You have to enable the traffic in the RoutePlan before using the Planner:

// 
routePlan = RoutePlan(
departures = listOf(departure.location ?: return),
destinations = listOf(arrival.location ?: return),
viaPoints = addresses.subList(1, addresses.size - 1).mapNotNull { it.location },
routeOptions = RouteOptions(maxAlternativeRoutes = 10, vehicle = chosenVehicle, withLiveTraffic = prefsManager.routeWithTraffic)
)

Then you can call a Planner method to compute a route with the RoutePlan with traffic enabled.

planner.computeRoute(
routePlan!!,
object : ComputeRouteListener {
...
}
)

Navigation

The Navigation module will also benefit from the TrafficManager. If enabled, it will be used to navigate avoiding traffic jams automatically.

Pre-requisites:

  • The TrafficManager must be started and running.

  • The route must have been computed with the RouteOption "withTraffic" enabled.

Simply pass the route to the Navigation.startSession method.

The Navigation will automatically refresh the traffic events every 5 minutes by default, and closed roads every 30 minutes.

When new events are downloaded, they are added to the cache and can be retrieved by getEventsAround.

Configuration

  • var standardRadius: Int = 30000 Radius (in meters) used to download all events excepted blocked roads.

BetterRouteListener

When new traffic events are retrieved automatically by the Navigation, the module will automatically try to find a faster or better route:

  1. If a traffic jam with high impact appeared on the current route, a new faster route may be available.

  2. If a new closed road is now on the road we must change the route, event if it's slower than the current route.

To receive a notification when a better route is found, you can use the dedicated listener of BetterRouteListener.

First, add your listener using method addBetterRouteListener(listener: BetterRouteListener) of Navigation class. (add it before starting a guidance session). Then, the object/class of BetterRouteListener type can override onBetterRouteFound(deltaTime: Int) to receive the delta in seconds between the current route and the alternative found.

  • If the delta is >0 the alternative route found is slower than the current one.

  • If the delta is <0 the alternative route found is faster than the current one. Note: If a closed road is on the current route, we'll force the delta to "0xFFFFFFFF" to ensure that you are notified that you must do a rerouting.

Now that you know that a better route exists, if the delta is above your threshold (no need to reroute if it's only 1 second), you have to manually trigger a rerouting:

navigation.reroute()

Packages

Link copied to clipboard
Link copied to clipboard