Get real-time traffic conditions for a location

Objectives: Retrieve real-time traffic from the HERE Real Time Traffic catalog.

Complexity: Beginner

Depends on: Get your credentials, Verify Your credentials

Time to complete: 30 min

Source code: Download

This tutorial introduces HERE Real Time Traffic catalog and shows how to get information about traffic conditions data using this catalog.

The tutorial covers the following topics:

HERE Real Time Traffic catalog overview

HERE Real-Time Traffic catalog helps drivers reach their destinations efficiently and in a stress-free manner. The catalog delivers up-to-the-minute information about traffic conditions and incidents that could cause delays, including slower-than-normal traffic flow, roadworks and accidents. Moreover, it enables the display of traffic conditions on highways or arterials and is an ingredient to calculating traffic-aware expected time of arrival (ETA).

Real-time traffic data is produced by a sophisticated model that aggregates and analyzes a mix of sources, including high-quality rich vehicle sensor data. The result: best-in-class accuracy in depicting real-world traffic conditions.

HERE Real Time Traffic catalog allows to build a better traffic management solution with access to one of the largest aggregated real-time databases.

The following figure shows real-time traffic with information about the average speed and jam factor:

Get catalog information

HERE Real Time Traffic is a public catalog that provides a live depiction of conditions on the road. It can identify traffic congestion and deliver live information on road conditions and incidents to the driver.

To get the basic catalog information, you use the platform portal or run the following CLI command:

olp catalog show hrn:here:data::olp-here:olp-traffic-1

The output should contain the following information:

id                       olp-traffic-1
name                     HERE Real Time Traffic
hrn                      hrn:here:data::olp-here:olp-traffic-1
summary                  HERE Real Time Traffic provides live information on traffic conditions on roadways.
description              HERE Real Time Traffic provides a live depiction of conditions on the road. It identifies where traffic congestion occurs, and how bad it is, delivering minute-by-minute information on road conditions and incidents that could set a driver back.

notifications enabled?   false
tags                     TRAFFIC
billing tags             10648TAppsProd
created                  2018-01-24T22:20:07.462Z
owner                    HERE-383016a9-fa93-44c0-8294-a156a9df650d, olp-here
config version           80
metadata version         44377
metadata minimum version 0
marketplace ready        false
layers
type         ID                                   name
volatile     traffic-incidents-delta-volatile     Incidents - Volatile
volatile     traffic-flow                         Flow
replication
role                id
primary             eu-ireland

Based on the output, you can see that the HERE Real Time Traffic consists of two layers. The Traffic Flow layer provides the speed at which traffic is currently flowing, by road segment. The Traffic Incident layer contains records for incidents that are currently affecting traffic flow.

In the following tutorial, the traffic-flow layer is used to get information about real-time traffic. Let's get familiar with the traffic-flow layer.

Check out the traffic-flow layer in the platform portal or run the following OLP CLI command to get the information about the layer:

olp catalog layer show hrn:here:data::olp-here:olp-traffic-1 traffic-flow

The output should contain the following information:

Details of the traffic-flow layer:

id                  traffic-flow
name                Flow
summary             Current traffic speeds
description         The traffic flow layer provides the current speed of traffic on roads. Powered by HERE Traffic, the speeds are updated every minute.

Each tile contains Protobuf data, which is a list of all the current traffic flow messages based on the Traffic schema. Any message which spans across multiple tiles will be reported in all tiles where it exists, with the same ID.
layerType           volatile
partitioning        heretile, tile levels: 12
partitioningScheme  heretile
volume              volatile
contentType         application/x-protobuf
schema              hrn:here:schema::olp-here:com.here.traffic.realtime:traffic_v1:1.1.7
tags                SPEED, FLOW, TRAFFIC, CURRENT, REAL-TIME
billingTags         10648TAppsProd
coverage            VN, IN, KW, ID, BG, SG, TH, AT, TR, MY, RU, GI, PR, TW, PH, ES, SM, NZ, US, SI, BH, AD, RO, LU, IE, BE, AU, SA, HU, FI, NO, EE, LT, PL, CH, LV, SE, AE, AR, HR, GB, FR, PT, MC, UA, LI, BR, IT, CZ, GR, ZA, OM, MX, SK, QA, DK, NL, CA, IM, VA, DE
created             2018-01-24T22:23:02.543Z
volatileProperties  {"dataRedundancy":"multi-instance","storageCapacityMb":21000}
ttl                 3600000

Apparently, the layer is of the volatile type, which means whenever there is new data, the old data is overwritten. The information in the traffic-flow layer updates every minute. The layer has the following properties:

For more information on the above properties, see Data User Guide.

Use data schema

The Real-Time Traffic schema represents a traffic condition on a given road segment.

The data stored in the traffic_v1 layer is encoded using the traffic_v1 Protobuf Schema. The traffic_v1 Protobuf Schema defines the Protocol Buffer messages and enumerations used by the various data layers in HERE Real Time Traffic. The message definitions are defined in the corresponding .proto file that describes the structure of a partition in a catalog layer.

Real-time traffic conditions are provided as attributes (for example, average_speed_kph or jam_factor) for a fine-grained location grid. To describe the location, HERE uses its well-defined HERE tiling at level 12.

Let's look more closely at how the data is structured.

The traffic-flow contains flow, lane, segment, speed, and traversability status items.

The Flow) message contains information about the speed of traffic on one or more road segments. The segments contained by a flow are determined by algorithms in the HERE platform. This message can contain multiple Segment messages. In this case the segments represent connected sections of the roadway and are ordered in the driving direction. The confidence attribute in the Flow message indicates the percentage of real-time data used in the speed calculation, where:

  • a value of 0.75 or greater indicates high confidence real-time information
  • if the value is in the range of 0.5 to 0.7 - historical speeds are used to calculate the traffic speed
  • if the value is in the range of 0.0 to 0.5 - the speed limit is used to calculate the speed of traffic
  • if the value is -1 - the road is closed.

The Segment message contains information about the flow of traffic on a section of roadway. First, let's find out what a Segment is. A Segment is a directed polyline connecting two Nodes with optional intermediate Shape Points. The logical orientation of a Segment is defined as being from its starting Node to its ending Node. This orientation is not related to the direction of travel on the Segment. However, directional attributes, such as direction of travel or speed limit, reference Segments relative to this logical orientation. A given Node may be both a start and end Node for different Segments that adjoin it. For more information about Segments, see the Topology Model.

The following figure demonstrates Segments that are connected by Nodes using the topology-geometry layer from the HERE Map Content catalog:

The Segment message describes the information about the average speed of traffic for this segment using the Speed message.

The jam_factor attribute in the Segment message describes the state of traffic jams and can range from 0.0 to 10.0 indicating how freely traffic is flowing. The start_offset attribute in the Segment message describes the offset ratio from the start of this segment in relation to the entire traffic condition.

The Segment message also describes if segments are open to traffic using the TraversabilityStatus message, which can take the following values: OPEN - if the segment is open for traffic, CLOSED - if the segment is closed for traffic, and ROAD_NOT_ROUTABLE - if the segment is restricted from carrying traffic. This can happen when both directions of the reversible road are closed, for example, for construction or in case of a major accident.

The last message used in the Segment message is the Lane message that contains information about the speed of traffic in individual lanes in a roadway. This message is only provided if there are different lane speeds along a roadway.

The message definitions can be found in the following flow.proto file:

syntax = "proto3";

package com.here.traffic.realtime.v1;

/**
The `Flow` message contains information about the speed of traffic on one or more road segments. 
The segments contained by a flow are determined by algorithms in the Open Location Platform.
*/
message Flow {

    /*
    One or more messages containing information about the flow of traffic on a section of roadway, or "segment". 
    If a `Flow` message contains multiple `segment` messages, the segments represent
    connected sections of the roadway and are ordered in the driving direction. 
    Each `segment` contains a start_offset field which defines the ratio of
    this segment to the overall Flow message.
    */
    repeated Segment segment = 1;

    /*
    A number from 0.0 to 1.0 indicating the percentage of real-time data used in the speed calculation.
    You can use this field to identify whether the data for this 
    `Flow` is derived from real-time probe sources or historical information only.
    Confidence is only available for the `Flow` message and applies to all `Segment` messages.

    - 0.71 to 1.0: Real-time speeds were used to calculate the traffic speed for the `Flow`. 
      A value of 0.75 or greater indicates high confidence real-time information.

    - 0.5 to 0.7: Historical speeds were used to calculate the traffic speed for the `Flow`.

    - 0.0 to 0.5: The speed limit was used to calculate the speed of traffic for the `Flow`.

    - -1.0: The road is closed

    */
    double confidence = 2;
}
/*
The `Segment` message contains information about the flow of traffic on a section of roadway.
*/
message Segment {

    /**
    Information about the speed of traffic for this segment.
    */
    Speed speed = 1;

    /**
    A number between 0.0 and 10.0 indicating how freely traffic is flowing. 
    A value of 0 means traffic is flowing freely. 
    A value of 10 means traffic is stopped.
    A value of -1.0 indicates that `jam_factor` could not be calculated.

    If a road is closed, `jam_factor` is 10.

    If a road is reversible and traffic is flowing opposite the driving direction, 
    `jam_factor` is -1. 
    This value is useful when displaying traffic on a map and you do not want to display the road as closed.
    */
    double jam_factor = 2;

    /**
    The offset ratio from the start of this segment in relation to the entire traffic condition.
    */
    double start_offset = 3;

    /**
    Indicates whether the segment is traversable.  See `Flow.TraversabilityStatus` for valid values.
    */
    TraversabilityStatus traversability_status = 4;

    /**
    The speed of traffic in each lane. 
    The `lanes` field is only provided if there are different lane speeds along a roadway.
    When there is lane-level traffic along a roadway, 
    there will be two or more `Lane` messages in the `Segment`.
    */
    repeated Lane lanes = 5;
}

/*
   The `Speed` message contains information 
   about the velocity of traffic traveling along the segment.
   */
message Speed {

    /**
    The average speed that traffic is traveling, in Kilometers per hour.
    A value of -1.0 indicates that the average speed could not be calculated.
    */
    double average_speed_kph = 1;

    /**
    The average speed that traffic is traveling, but limited to the speed limit. 
    If the traffic speed is greater than the speed limit, 
    the value of this field will be the speed limit instead of the actual
    traffic speed. 
    The speed is in in Kilometers per hour.
    A value of -1.0 indicates that the average speed could not be calculated.
    */
    double average_speed_capped_kph = 2;

    /**
    The speed at which vehicles can travel the segment 
    when there is no traffic congestion or other impediments such as a road closure.
    This speed is calculated as the 80th percentile of observed speeds during non-rush hour periods.

    Free flow is useful for understanding the level of congestion.  
    When the average speed is greater than or equal to the free flow speed,
    it can be assumed that there is no traffic congestion.
    */
    double free_flow_speed_kph = 3;
}

/**
The `TraversablityStatus` field indicates whether a segment is open to traffic.

- `OPEN`: The segment is open for traffic. This includes reversible roads that are open.
- `CLOSED`: The segment is closed to traffic. No `Speed` messages will be provided for this segment.
- `ROAD_NOT_ROUTABLE`: The segment is restricted from carrying traffic. 
  In some situations, portions of a reversible road will be marked as CLOSED rather than ROAD_NOT_ROUTABLE. 
  This can happen when both directions of the reversible road are closed, such as for construction or major accidents. 
  In a map display, we recommend that you use ROAD_NOT_ROUTABLE to indicate that the road is not routable, 
  the road segment is not drivable, and not to show traffic on this roadway.
*/
enum TraversabilityStatus {
    OPEN = 0;
    CLOSED = 1;
    ROAD_NOT_ROUTABLE = 2;
}

/**
The `Lane` message contains information about the speed of traffic in individual lanes in a roadway.  
A `Lane` message is only provided if there are different lane speeds along a roadway.

The number of lanes along a roadway can be determined by looking at the maximum lane number in all `Lane` messages in the
segment.
*/
message Lane {

    /**
    A list of lanes associated with the traffic. Lane numbers use the HERE Map method of lane numbering where the left lane
    is 1 and each lane to the right of the left lane is numbered sequentially. For example, in a three-lane road, the
    left lane is 1, the center lane is 2, and the right lane is 3. Lane 1 is always the left lane, regardless of the driving side.
    If multiple lane numbers are presented, all lanes will have the traffic condition. Lane numbers will always be sequential.
    */
    repeated int32 lane_number = 1;

    /**
    A Flow.Speed message containing the traffic speed for this lane.
    */
    Speed speed = 2;

    /**
    The jam factor for this `Lane`. See `jam_factor` field in `Segment` message for definition.
    */
    double jam_factor = 3;
}

Set up the Maven project

In order to get real-time traffic conditions, you may download the source code at the beginning of the tutorial and store it in a folder of your choice, or create a folder structure for your project from scratch as follows:

here-realtime-traffic
└── src
    └── main
        ├── java
        └── resources
        └── scala

You can do this with a single bash command:

mkdir -p here-realtime-traffic/src/main/{java,resources,scala}

The Maven POM file is similar to the one in the Verify Maven Settings tutorial, with the parent POM and dependencies sections updated:

The Parent POM is sdk-standalone-bom_2.12 as this tutorial is designed to run locally for the sake of simplicity.

<parent>
    <groupId>com.here.platform</groupId>
    <artifactId>sdk-standalone-bom_2.12</artifactId>
    <version>2.42.4</version>
    <relativePath/>
</parent>

The following dependencies are used:

  • hrn_2.12 to initialize Real Time Traffic catalog hrn.
  • traffic_v1_java to decode Partitions data.
  • data-client_2.12 and data-engine_2.12 to download partition data.

Dependencies:

<dependencies>
    <dependency>
        <groupId>com.here.platform.data.client</groupId>
        <artifactId>data-client_${scala.compat.version}</artifactId>
    </dependency>
    <dependency>
        <groupId>com.here.platform.data.client</groupId>
        <artifactId>data-engine_${scala.compat.version}</artifactId>
    </dependency>
    <dependency>
        <groupId>com.here.hrn</groupId>
        <artifactId>hrn_2.12</artifactId>
    </dependency>
    <dependency>
        <groupId>com.here.traffic.realtime</groupId>
        <artifactId>traffic_v2_java</artifactId>
    </dependency>

</dependencies>

Get real-time conditions for a specific location

This tutorial demonstrates how to fetch the real-time traffic data from the HERE Real Time Traffic catalog at a given location described with road segments - in this case the Brandenburg Gate.

The input to this tutorial is a Tile ID 23618402 on zoom level 12 that covers the Brandenburg Gate and segment IDs 202981252, 203203107 82419435 covering a small part of Unter der Linden street near Brandenburg Gate) and Pariser Platz square.

Road segments near Brandenburg Gate and Pariser Platz square
Figure 1. Road segments near Brandenburg Gate and Pariser Platz square

The code snippet below does the following:

Step 1:

Retrieve Partition metadata for the obtained Tile ID on zoom level 12 using the getVolatilePartitions() method from the Data Client Library.

Step 2:

Download partition for the given Brandenburg Gate Tile ID on zoom level 12 using the getDataAsBytes() method from the Data Client library.

Step 3:

Using the downloaded partition in Step 2, parse data with the traffic_v1 Protobuf Schema.

Step 4:

Fetch speed item list that contains information about topology segment IDs and then get all segments with information about traffic by filtering results by given segments IDs: 202981252, 203203107 82419435.

Scala
Java

/*
 * Copyright (c) 2018-2022 HERE Europe B.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import akka.NotUsed
import akka.actor.{ActorSystem, CoordinatedShutdown}
import akka.stream.ActorMaterializer
import akka.stream.javadsl.{Sink, Source}
import com.here.hrn.HRN
import com.here.platform.data.client.common.VolatilePartitionsFilter.byIds
import com.here.platform.data.client.engine.javadsl.{DataEngine, ReadEngine}
import com.here.platform.data.client.javadsl.{DataClient, Partition, QueryApi}
import com.here.platform.data.client.model.AdditionalFields
import com.here.traffic.realtime.v2.Traffic.TrafficItems

import scala.collection.convert.ImplicitConversions.`collection AsScalaIterable`
import scala.concurrent.ExecutionContext.Implicits.global

object RealTimeTrafficTutorialScala {

  private val FLOW_CATALOG = HRN.fromString("hrn:here:data::olp-here:olp-traffic-1")
  private val FLOW_LAYER = "traffic-flow"

  def main(args: Array[String]): Unit = {

    val actorSystem: ActorSystem = ActorSystem.create("flow")
    val actorMaterializer: ActorMaterializer = ActorMaterializer.create(actorSystem)
    val queryApi: QueryApi = DataClient.get(actorSystem).queryApi(FLOW_CATALOG)
    val readEngine: ReadEngine = DataEngine.get(actorSystem).readEngine(FLOW_CATALOG)

    val berlinCityCenterTileId = "23618402"

    val segmentsIdForStreet = List(202981252, 203203107, 82419435)

    // Step 1: Retrieve Partition metadata for the given Brandenburg Gate Tile ID on zoom level 8
    val partition = queryApi
      .getVolatilePartitions(FLOW_LAYER,
                             byIds(Set(berlinCityCenterTileId)),
                             AdditionalFields.AllFields)
      .thenCompose((partitionsSource: Source[Partition, NotUsed]) =>
        partitionsSource.runWith(Sink.head(), actorMaterializer))
      .toCompletableFuture
      .join()

    // Step 2: Download partition for the given `Brandenburg Gate` Tile ID on zoom level `12`
    val partDownloadedTraffic = readEngine.getDataAsBytes(partition).toCompletableFuture.join()

    // Step 3: Parse real-time traffic data
    val speedsTrafficItems = TrafficItems.parseFrom(partDownloadedTraffic)

    // Step 4: Fetch speed item list that contains information about topology segment IDs
    // and then get all segments with information about traffic
    // by filtering results by given segments IDs: `202981252, 203203107 82419435`.
    val realTimeTraffic = speedsTrafficItems.getItemsList
      .filter(item =>
        item.getTopologySegment.getTopologySegmentIdList.exists(segmentsIdForStreet.contains))
      .flatMap(traffic => traffic.getFlow.getSegmentList)

    printf(
      s"The real-time traffic data for the given segments Ids [${segmentsIdForStreet.map(_.longValue()).mkString(", ")}] is: $realTimeTraffic")

    CoordinatedShutdown
      .get(actorSystem)
      .run(CoordinatedShutdown.unknownReason)
      .onComplete(print)

  }

}



/*
 * Copyright (c) 2018-2022 HERE Europe B.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import akka.actor.ActorSystem;
import akka.actor.CoordinatedShutdown;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Sink;
import com.google.protobuf.InvalidProtocolBufferException;
import com.here.hrn.HRN;
import com.here.platform.data.client.common.VolatilePartitionsFilter;
import com.here.platform.data.client.engine.javadsl.DataEngine;
import com.here.platform.data.client.engine.javadsl.ReadEngine;
import com.here.platform.data.client.javadsl.DataClient;
import com.here.platform.data.client.javadsl.Partition;
import com.here.platform.data.client.javadsl.QueryApi;
import com.here.traffic.realtime.v2.*;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

public class RealTimeTrafficTutorial {

  private static final HRN FLOW_CATALOG = HRN.fromString("hrn:here:data::olp-here:olp-traffic-1");
  private static final String FLOW_LAYER = "traffic-flow";

  public static void main(String[] args)
      throws ExecutionException, InterruptedException, InvalidProtocolBufferException {
    ActorSystem actorSystem = ActorSystem.create("flow");
    ActorMaterializer actorMaterializer = ActorMaterializer.create(actorSystem);
    QueryApi queryApi = DataClient.get(actorSystem).queryApi(FLOW_CATALOG);
    ReadEngine readEngine = DataEngine.get(actorSystem).readEngine(FLOW_CATALOG);

    String berlinCityCenterTileId = "23618402";

    List<Integer> segmentsIdForStreet =
        new ArrayList<>(Arrays.asList(202981252, 203203107, 82419435));

    // Step 1: Retrieve Partition metadata for the given Brandenburg Gate Tile ID on zoom level 8
    Partition partition =
        queryApi
            .getVolatilePartitions(
                FLOW_LAYER,
                new VolatilePartitionsFilter.Builder()
                    .withIds(Collections.singleton(berlinCityCenterTileId))
                    .build(),
                Collections.emptySet())
            .thenCompose(
                partitionsSource -> partitionsSource.runWith(Sink.head(), actorMaterializer))
            .toCompletableFuture()
            .join();

    // Step 2: Download partition for the given `Brandenburg Gate` Tile ID on zoom level `12`
    byte[] partDownloadedTraffic = readEngine.getDataAsBytes(partition).toCompletableFuture().get();

    // Step 3: Parse real-time traffic data
    Traffic.TrafficItems speedsTrafficItems = Traffic.TrafficItems.parseFrom(partDownloadedTraffic);

    // Step 4: Fetch speed item list that contains information about topology segment IDs
    // and then get all segments with information about traffic
    // by filtering results by given segments IDs: `202981252, 203203107 82419435`.
    List<FlowOuterClass.Segment> realTimeTraffic =
        speedsTrafficItems
            .getItemsList()
            .stream()
            .filter(
                item ->
                    !Collections.disjoint(
                        item.getTopologySegment().getTopologySegmentIdList(), segmentsIdForStreet))
            .flatMap(t -> t.getFlow().getSegmentList().stream())
            .collect(Collectors.toList());

    System.out.printf(
        "The real-time traffic data for the given segments Ids %s is: %s",
        segmentsIdForStreet, realTimeTraffic);

    CoordinatedShutdown.get(actorSystem)
        .run(CoordinatedShutdown.unknownReason(), Optional.empty())
        .toCompletableFuture()
        .join();
  }
}


To execute the application, run the following command:

Scala
Java

mvn compile exec:java -D"exec.mainClass"="RealTimeTrafficTutorialScala"


mvn compile exec:java -D"exec.mainClass"="RealTimeTrafficTutorial"

According to the results of the program the traffic jam is 1.53047 out of 10.0 possible, the average speeds for 202981252 and 82419435 segments are 10.0 kph, for the 203203107 segment, the average speed is 8.35 kph. The speed at which vehicles can travel the segment, when there is no traffic congestion or other impediments, such as a road closure, is 10.0 for all segments, as indicated by free_flow_speed_kph. The average speed that traffic is traveling, but limited to the speed limit is 10.0 for 202981252 and 82419435 segments and 8.35 for 82419435 segment as indicated by average_speed_capped_kph.

The real-time traffic data for the given segments Ids [202981252, 203203107, 82419435] is: 
[
speed {
  average_speed_kph: 10.0
  average_speed_capped_kph: 10.0
  free_flow_speed_kph: 10.0
}
, speed {
  average_speed_kph: 8.35
  average_speed_capped_kph: 8.35
  free_flow_speed_kph: 10.0
}
jam_factor: 1.53047
, speed {
  average_speed_kph: 10.0
  average_speed_capped_kph: 10.0
  free_flow_speed_kph: 10.0
}
]

Conclusion

In this tutorial, you got acquainted with the HERE Real Time Traffic catalog and learned how to get information about traffic conditions data using this catalog.

Further information

For more details on the topics covered in this tutorial, see the following sources:

results matching ""

    No results matching ""