How to work with TMC references

The
referencing
module contains interfaces and classes that enable the conversion of location
references to
Optimized Map for Location Library
vertices (reference resolution) and the creation of location references from
Optimized Map for Location Library
vertices (reference creation).

This module supports the TMC and Extended TMC location referencing methods
described in detail below.

Note: TMC implementation restrictions

The base implementation of TMC location referencing is restricted to resolving
and creating references with a maximum extent of 1. The references also need
a valid extendedCountryCode to be resolved.

In order to resolve or create references that have a greater extent a
TmcAdjacencyProvider needs to be passed in.

To use location referencing, you need to add the module to the project
dependencies:

libraryDependencies ++= Seq(
  "com.here.platform.location" %% "location-referencing" % "<version>"
)
<dependencies>
    <dependency>
        <groupId>com.here.platform.location</groupId>
        <artifactId>location-referencing_${scala.compat.version}</artifactId>
    </dependency>
</dependencies>
dependencies {
    compile group: 'com.here.platform.location', name: 'location-referencing_2.13', version:'<version>'
}

Resolving a location reference

The interface
LocationReferenceResolver
provides a method to resolve location references. Instances of the interface can
be created through the factory object
LocationReferenceResolvers.

The counterpart interface
LocationReferenceCreator
provides methods necessary to create location references. Instances of the type
can be created through the factory object
LocationReferenceCreators.

These factory objects provide factories for all the different location reference
types supported by the library.

The snippet below demonstrates how to create a TMC resolver and how to resolve
an existing TMC location reference with it.

import com.here.platform.location.referencing._
import com.here.platform.location.tpeg2.tmc.TMCLocationReference

val tmcReference: TMCLocationReference = getTmcLocationReference

val tmcResolver: LocationReferenceResolver[TMCLocationReference, BidirectionalLinearLocation] =
  LocationReferenceResolvers(optimizedMap).tmc

val location: BidirectionalLinearLocation = tmcResolver.resolve(tmcReference)

println(s"""Vertices in the:
           |  - location: ${location.location.path}
           |  - opposite location: ${location.oppositeLocation.map(_.path)}
           |""".stripMargin)
import com.here.platform.location.referencing.BidirectionalLinearLocation;
import com.here.platform.location.referencing.LocationReferenceResolver;
import com.here.platform.location.referencing.javadsl.LocationReferenceResolvers;
import com.here.platform.location.tpeg2.tmc.TMCLocationReference;
final TMCLocationReference tmcReference = getTmcLocationReference();

final LocationReferenceResolver<TMCLocationReference, BidirectionalLinearLocation> tmcResolver =
    new LocationReferenceResolvers(optimizedMap).tmc();

final BidirectionalLinearLocation location = tmcResolver.resolve(tmcReference);

System.out.println("Resolved location: " + location);

TMC location references can, at the same time, refer to the positive and
negative direction of the linear location. Therefore, TMC resolvers return a
BidirectionalLinearLocation.

Creating a location reference

Note: Migration to topology attributes

TMC creators now use Topology Attributes instead of the deprecated Navigation
Attributes layer. If you use a map version where the Topology Attributes layer
is empty, you will encounter a
LinearLocationNotRepresentedInTmcException.

Refer to the documentation section how to
use deprecated layers in TMC.

The interface
LocationReferenceCreator
provides a method to create location references. Instances of the interface can
be created through the factory object
LocationReferenceCreators.

The snippet below demonstrates how to create a TMC creator and how to create a
TMC location reference with it. TMC location references use a pre-coded
referencing scheme, therefore you can only create a reference for paths that are
covered by TMC tables.

import com.here.platform.location.referencing._
import com.here.platform.location.tpeg2.XmlMarshallers
import com.here.platform.location.tpeg2.lrc.LocationReferencingContainer
import com.here.platform.location.tpeg2.tmc.TMCLocationReference

val location: LinearLocation = findLinearLocation(optimizedMap)

val tmcRefCreator: LocationReferenceCreator[LinearLocation, TMCLocationReference] =
  LocationReferenceCreators(optimizedMap).tmc

val tmcRef: TMCLocationReference = tmcRefCreator.create(location)

XmlMarshallers.locationReferencingContainer
  .marshall(LocationReferencingContainer(Seq(tmcRef)), Console.out)
import com.here.platform.location.referencing.LinearLocation;
import com.here.platform.location.referencing.LocationReferenceCreator;
import com.here.platform.location.referencing.javadsl.LocationReferenceCreators;
import com.here.platform.location.tpeg2.XmlMarshallers;
import com.here.platform.location.tpeg2.lrc.LocationReferencingContainer;
import com.here.platform.location.tpeg2.tmc.TMCLocationReference;

import java.util.Collections;
final LinearLocation location = findLinearLocation(optimizedMap);

final LocationReferenceCreator<LinearLocation, TMCLocationReference> tmcRefCreator =
    new LocationReferenceCreators(optimizedMap).tmc();

final TMCLocationReference tmcRef = tmcRefCreator.create(location);

XmlMarshallers.locationReferencingContainer()
    .marshall(new LocationReferencingContainer(Collections.singletonList(tmcRef)), System.out);

If a path is not fully covered by TMC or cannot be covered by a single TMC
reference, because it doesn't follow a single TMC linear location, there is the
possibility to use the piecewiseExtendedTmc, which can return multiple TMC
references along with the linear location that is covered by each one.

Attribute retention in TMC

By default, TMC creators retain all Topology Attributes in memory, which can
lead to increased memory usage. To optimize memory consumption, configure the
map to retain only the required attribute, TrafficMessageChannelCode.

import com.here.platform.data.client.base.scaladsl.BaseClient
import com.here.platform.location.compilation.heremapcontent.TopologyAttributeDescription
import com.here.platform.location.integration.optimizedmap.OptimizedMapLayers
import com.here.platform.location.integration.optimizedmap.dcl2.OptimizedMapCatalog

val baseClient = BaseClient()
val optimizedMap: OptimizedMapLayers =
  OptimizedMapCatalog
    .from(optimizedMapHRN)
    .usingBaseClient(baseClient)
    .withTopologyAttributes(TopologyAttributeDescription.TrafficMessageChannelCode)
    .newInstance
    .latest
import com.here.platform.data.client.base.javadsl.BaseClient;
import com.here.platform.data.client.base.javadsl.BaseClientJava;
import com.here.platform.location.compilation.heremapcontent.TopologyAttributeDescription;
import com.here.platform.location.integration.optimizedmap.OptimizedMapLayers;
import com.here.platform.location.integration.optimizedmap.dcl2.javadsl.OptimizedMapCatalog;
BaseClient baseClient = BaseClientJava.instance();
OptimizedMapLayers optimizedMap =
    OptimizedMapCatalog.from(optimizedMapHRN)
        .usingBaseClient(baseClient)
        .withTopologyAttributes(TopologyAttributeDescription.TrafficMessageChannelCode())
        .newInstance()
        .latest();

How TMC works

This section provides more detail about the TMC and Extended TMC location
references that can be embedded in TPEG2 messages. The
first part explains the concepts of TMC locations and location
tables.

The second part explains how to use these to refer
to paths in the road network.

TMC locations

The Traffic Message Channel (TMC) location referencing method uses tables of
pre-coded locations. While TMC defines many different types of location codes,
point and linear location codes are of particular interest as both these
location codes are used to refer to locations on the road network.

Linear location codes refer to major roads or longer subsections of these
roads. Point location codes refer to short stretches of a road involving exits
and entries, such as where it intersects with another road.

When two roads that are coded in TMC intersect, there will be two point location
codes describing their intersection: one from each road's point of view. For
example, at the Frankfurter Kreuz junction, the motorways A3 and A5 intersect.
The current version of the TMC table for Germany (version 18) has two point
location codes for this junction: 10871 for the Frankfurter Kreuz on the A3, and
11623 for the Frankfurter Kreuz on the A5.

For each road coded in TMC, one direction is designated as the positive
direction, and the opposite direction is designated as the negative direction.

A location code can potentially have references to the previous and next coded
location along the positive direction of the road. The next location code is
called the positive offset and the previous code the negative offset. (This
use of "offset" can be somewhat confusing. It is helpful to think of the point
locations being part of linked lists, with offsets being pointers to the next
nodes in their respective directions.)

Each TMC code actually has four logical road sections associated with it: The
internal and external road sections for each of the positive and negative
directions. The internal road sections of a point location are the sections of
the road that are within the area of the intersection, that is between the first
and last of the many entries and exits involved in that intersection. The
external road sections are the part of the road leading toward the internal
sections.

In the Frankfurter Kreuz example given above, TMC point location code 10871
represents the part of east-west motorway A3 where it has a cloverleaf
intersection with north-south motorway A5, with the westbound direction coded as
the positive direction. The intersection involves four ramps interacting with
each direction of the A3 (an off-ramp and an on-ramp heading to/from each
direction of the A5). The internal section for a given direction is the stretch
of motorway between the first off-ramp and the last on-ramp. The external
positive section of location code 10871 is the westbound part of the A3 between
the internal section of the preceding point location in that direction (location
code 10871's negative offset: location code 59628) and the internal part of
intersection with motorway B, and the external negative section of location code
123 will be the eastbound part of A3 between the previous point location in that
direction (location code 10872) and the intersection with motorway B.

TMC Frankfurter Kreuz example

There can be multiple TMC location tables defined for a given country. For
example, a country might use different tables for different location types or
different administrative areas. For a given country, each table is assigned a
number. To uniquely identify a table, it's necessary to specify both the country
and the table number.

For historical reasons, TMC has two mechanisms to identify a country. Each
country is assigned a country code, which is a nonzero 4-bit number
represented as a single hexadecimal digit (1 through F). This is sufficient for
radio broadcasts in border areas to distinguish between neighbouring countries,
but there are not enough unique values to assign each country a unique code, so
the country code doesn't uniquely identify a country. Each country is also
assigned an extended country code, which is a 8-bit number represented by two
hexadecimal digits. Unfortunately, there are also duplicate uses of the extended
country code, but combining the country code and extended country code does
uniquely identify the country.

A TMC location reference refers to a particular table as well as the location
code. To work properly, the sender and receiver of a TMC reference must share
the same location tables. This allows TMC references to be very small. However,
not all locations are pre-coded and thus, there are locations that cannot be
referred to using TMC location referencing.

TMC location references

A TMC location reference is always built around a TMC location code. To uniquely
identify the code, it is necessary to provide a country code, extended country
code, table number, and the code itself. (The extended country code is optional
in the TPEG formats, but we expect it to always be present.) The location code
that is explicitly given in the reference is called the primary location.

The reference also specifies an extent. Extents allow you to specify a
location that spans more than one road section by defining an integer number of
preceding location codes that are involved in the reference. The furthest such
location code is known as the secondary location. By convention, travel moves
from the secondary location to the primary location.

Your need to specify the direction (positive or negative) as a boolean value,
where true means positive and false means negative. The value here is the
direction to follow from the primary location to the secondary location. Since
traffic flow is from the secondary location to the primary location, the
direction indicator is for the direction opposite to the traffic flow!

For example, assume that the TMC table includes the entries shown below, that
the primary location code in the reference is 8, and the extent is 4. Then if
the direction is false, we follow the negative offsets and the secondary
location code is 2. If the direction is true, we follow the positive offsets and
the secondary location code is 14.

Location CodeNegative OffsetPositive Offset
2(none)4
426
648
8610
10812
121014
141216

When the extent is 0, there is no secondary location, and only the internal
section of the primary location is included in the reference. The external
section of the primary location is not included.

When the extent is greater than 1, we have the internal and external sections of
the primary and secondary locations to consider, as well as all the the location
codes in between:

  • The external part of the secondary location is excluded.
  • The inclusion/exclusion of the internal part of the secondary location is
    described below.
  • All of the external and internal parts of the codes between the primary and
    secondary location are included.
  • The external part of the primary location is included.
  • The inclusion/exclusion of the internal part of the secondary location is
    described below.

There are actually two parts of TPEG2 that define TMC location references: The
older TMC Location Referencing (TMC), represented by the code in our
tmc
package, and the newer Extended TMC Location Referencing (ETL), represented by
the code in our
etl
package. Both of these packages have a class named TMCLocationReference. The
etl
version of TMC referencing allows the reference to explicitly specify whether
the internal sections of the secondary location are included, and whether the
internal sections of the primary location are included. The
tmc
version does not allow these to be specified: the internal sections of the
secondary location are always excluded, and those of the primary location are
always included. The following table shows how the
etl
flags affect the referenced location.

ExtentUse Primary InternalUse Secondary InternalSecondary ExternalSecondary InternalPrimary ExternalPrimary Internal
0__
1+FF
1+FT
1+TF
1+TT

You can then use "precise TMC" information in the form of a hazard distance
and problem length to restrict the extent of the location. Both values are
specified in hectometers (1 hectometer = 100 meters).

The hazard distance, when specified, is the distance backwards from the primary
location to the start of the referenced location. In principle, the hazard
distance shouldn't be longer than the combined length of all the road sections
included by the parameters described above. When decoding references, if the
hazard distance exceeds the combined road length, we use the combined road
length (the same as if the hazard distance isn't specified).

The problem length, when specified, is the distance from the start of the
referenced location (potentially modified by the hazard distance) to the end of
the referenced location. In principle, the problem length shouldn't be longer
than the combined length of the remaining road segments after they are modified
by the hazard distance. When decoding references, if the problem length exceeds
this length, we use the full remaining length (the same as if the problem length
isn't specified).