## ASTERIX formats

ASTERIX data can be decoded from file or from a live stream of radar data. These file formats are supported:

• ASTERIX format: concatenated blocks of ASTERIX data, possibly of different categories. The file extension is by default assumed to be `.asterix` or `.ast`.

• ASTERIX Final format: blocks of ASTERIX data, possibly of different categories, surrounded by headers and footers. The format is described in the ASTERIX Final format guide. The file extension is assumed to be `.astfin` by default.

• PCAP files: ASTERIX data captured from a network with capturing tools such as Wireshark. The LuciadLightspeed decoder supports a specific subset of ASTERIX PCAP files: it only supports captures of raw Ethernet packages (version II, LLC, LLC+SNAP blocks), with additional support for UDP over (fragmented) IPv4 network protocol. The file extension is assumed to be `.pcap` by default.

## How to decode ASTERIX data

### Decoders

In the `com.luciad.format.asterix` package two decoders are available. Use the `TLcdASTERIXModelDecoder` to decode ASTERIX data from file and the `TLcdASTERIXLiveDecoder` to decode ASTERIX data from a live stream of data.

The `TLcdASTERIXModelDecoder` is an `ILcdModelDecoder`. The `decode` method produces an `ILcdModel` which is in fact a `TLcdModelList` containing an `ILcdModel` for every combination of category and UAP encountered. You can also use the `decodeSource` method of its `ILcdModelDecoder` interface to decode multiple ASTERIX files at once. Using this method, a trajectory that is split across multiple files can still be decoded as a single trajectory.

The `TLcdASTERIXLiveDecoder` on the other hand is not an `ILcdModelDecoder`. It has a method `decodeSFCT(InputStream aInputStream, int aFireEventMode, TLcdModelList aModelSFCT)`, which must be called to start reading data from a live stream. Here you must create a `ILcdModelContainer` yourself and pass it as an argument to the `decodeSFCT` method. During the decode an `ILcdModel` is added for every combination of category and UAP encountered. The `aInputStream` argument of the `decodeSFCT` method specifies the stream from which data is read. For the `TLcdASTERIXLiveDecoder` the reading must be started from a dedicated thread. It can then be stopped by calling the `interrupt` method on the thread.

`TLcdASTERIXLiveModelDecoder` offers the functionality if the `TLcdASTERIXLiveDecoder` as an `ILcdModelDecoder`. This is useful when your application uses the `TLcdServiceLoader` to find all model decoders, or when you have another centralized list of model decoders. Since there are no standard protocols for live ASTERIX data, you need to set your own `ILcdInputStreamFactory` on the `TLcdASTERIXLiveModelDecoder` that can create an `InputStream` based on your needs.

The decoders group data of one category and UAP into one `ILcdModel`. The objects of the individual models are domain objects that reflect the type of data the category or more specific the UAP represents. The objects also depend on the type of decoder : `TLcdASTERIXModelDecoder` and `TLcdASTERIXLive(Model)Decoder` will create different domain objects, each containing the same UAP data, but in another representation. The following table describes which type of domain objects are contained in which model, and also mentions the data item that is used as ID for the domain objects:

 Cat UAP ASTERIX data item used for ID Domain objects created by TLcdASTERIXModelDecoder Domain Objects created by TLcdASTERIXLiveDecoder and TLcdASTERIXLiveModelDecoder 1 Track Track Plot Number TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot 8 / Not applicable TLcdASTERIXWeatherPicture TLcdASTERIXWeatherPicture 11 Track Track Number TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot 21 Track Target Identification TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot 21 v0.23 Track Target Address TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot 30 Track Track Number TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot 30 v2.5 ter Track Track Number TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot 48 Track Track Number TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot 62 Track Track Number TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot 240 Radar video Data Source Identifier TLcdRadar TLcdRadar 244 Track Track Number TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot 10 Track Track Number TLcdASTERIXTrajectory TLcdASTERIXPlot TLcdASTERIXTrack TLcdASTERIXPlot

The model descriptors of the individual models depend on the type of domain object in the model. They can be used to check the type of domain object in the model. Refer to Model descriptors for more information on model descriptors.

The decoders can be configured in several ways:

• By default the decoders decode the ASTERIX data from all categories that are supported. The `setCategories(ALcdASTERIXCategory[] aCategories)` method can be used to limit the categories that are processed to a well defined subset.

• All times in ASTERIX are relative to midnight. Refer to Domain object times for more information on ASTERIX times. By default the decoders create absolute times from these relative times by adding the current day as time offset. This behavior can be overwritten for the `TLcdASTERIXModelDecoder`. It has a method `setTimeOffset` that allows to specify a day offset manually.

• A scaling factor provider `ALcdASTERIXScalingFactorProvider` can be specified for both decoders using the `setScalingFactorProvider` method. The provided factors are used to scale the values in the ASTERIX data fields when those factors are not available from the data itself. Refer to Scaling factors for more information on scaling factor providers.

• For the `TLcdASTERIXModelDecoder` the method `setInputStreamFactory(com.luciad.io. ILcdInputStreamFactory aInputStreamFactory)` can be used to specify the input stream factory for creating input streams from source file names. By default the `com.luciad.io.TLcdInputStreamFactory` is used.

• The `ILcdModelContainer` filled by the `TLcdASTERIXLiveDecoder` always represents the situation at the current time. You can use the `setHistoryLength` method to specify the maximum history to keep in memory. Note that if more history is available as the specified maximum , the oldest information is purged. For instance for `TLcdASTERIXTrack` domain objects you can use the `setHistoryLength` method to specify the maximum number of tracks that must be kept in memory for the encapsulated trajectory (`TLcdASTERIXTrack.getTrajectory`).

### Samples

#### Decoding from file

The sample class `samples.decoder.asterix.file.MainPanel` implements a sample that allows to decode ASTERIX data from file and display that data on a map. It starts with creating a `TLcdASTERIXModelDecoder` and registering it as one of the `ILcdModelDecoder` objects that must be checked when a file is opened.

Program: Creating an ASTERIX model decoder (from `samples/decoder/asterix/file/MainPanel`)
``````public TLcdASTERIXModelDecoder createAsterixModelDecoder(
ILcdInputStreamFactory aInputStreamFactory,
ALcdASTERIXTransformationProvider aTransformationProvider
) {
TLcdASTERIXModelDecoder decoder = new TLcdASTERIXModelDecoder();
decoder.setInputStreamFactory(aInputStreamFactory);
if (aTransformationProvider != null) {
decoder.setTransformationProvider(aTransformationProvider);
}
return decoder;
}``````

Program: Creating an ASTERIX model decoder shows the implementation of the method `createAsterixModelDecoder` that is used to create the `TLcdASTERIXModelDecoder`. The argument `aInputStreamFactory` represents the `ILcdInputStreamFactory` that the decoder must use for creating input streams from source file names. It is customized in this sample to inform the user about decoding progress. The method first creates a `TLcdASTERIXModelDecoder`. Then it attaches the `aInputStreamFactory` and `aTransformationProvider` arguments to it.

Program: Using an action to load ASTERIX files (from `samples/decoder/asterix/file/MainPanel`)
``````//create and initialize the ASTERIX model decoder.
fModelDecoder = createAsterixModelDecoder(new TLcdInputStreamFactory(), transformationProvider);
OpenSupport openSupport = new OpenSupport(this, Collections.singletonList(fModelDecoder));
OpenAction openAction = new OpenAction(openSupport);``````

Since the `TLcdASTERIXModelDecoder` is an `ILcdModelDecoder` it can be assigned to a `com.luciad.model.TLcdOpenAction`. A `TLcdOpenAction` is a `java.awt.event.ActionListener` that can be attached to a menu item for loading a file. To load a file the `TLcdOpenAction` tries to find the correct `ILcdModelDecoder` for the file by calling the `canDecode` method on all registered `ILcdModelDecoder`. If a `ILcdModelDecoder` is found, its `decode` method is called to load the file. Program: Using an action to load ASTERIX files shows how an `ILcdAction` can be used to load ASTERIX files..

The complete sample code can be found in the packages `samples.decoder.asterix.file` and `samples.decoder.asterix`.

#### Decoding from a live stream

The sample class `samples.decoder.asterix.live.MainPanel` implements a sample that loads live ASTERIX data and displays it continuously on a map. The code for creating the `TLcdASTERIXLiveDecoder` and to start reading data from the live stream is explained below.

Program: Starting an ASTERIX live decoder (from `samples/decoder/asterix/LiveDecodedModel`)
``````private void startLiveDecoder(
ALcdASTERIXTransformationProvider aTransformationProvider,
int aHistoryLength,
final InputStream aInputStream) {
final TLcdASTERIXLiveDecoder liveDecoder = new TLcdASTERIXLiveDecoder();
liveDecoder.setHistoryLength(aHistoryLength);
if (aTransformationProvider != null) {
liveDecoder.setTransformationProvider(aTransformationProvider);
}

liveDecoder.initDecode(aInputStream);
fTimer = new Timer(50, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
int decodedMessages = 0;
while (liveDecoder.blockAvailable()) {
liveDecoder.decodeBlockSFCT(ILcdModel.FIRE_LATER, LiveDecodedModel.this);
decodedMessages++;
}
if (decodedMessages > 0) {
fireCollectedModelChanges();
fCallback.update(LiveDecodedModel.this);
}
} catch (EOFException ex) {
((Timer) e.getSource()).stop();
fCallback.finished(LiveDecodedModel.this);
} catch (IOException ex) {
((Timer) e.getSource()).stop();
LOGGER.error(ex.getMessage(), ex);
fCallback.error(LiveDecodedModel.this);
}
}
});
fTimer.setCoalesce(true);
fTimer.setRepeats(true);
fTimer.start();
}``````

Program: Starting an ASTERIX live decoder shows the implementation of the method `startLiveDecoder` that is used to create and start a `TLcdASTERIXLiveDecoder`. The argument `aInputStream` represents the input stream with live data. The argument `aModelList` is the `ILcdModelContainer` that must be filled by this live decoder. The method first creates a `TLcdASTERIXLiveDecoder`. Then it attaches the `aTransformationProvider` and `aHistoryLength` arguments to it. The decoder is now configured and can be started. The `TLcdASTERIXLiveDecoder` is not an `ILcdModelDecoder`, hence there is no `decode` method. A `ILcdModelContainer` must be created before the decoder can be started. In the sample the `TLcdModelList` to fill is offered as an input parameter `aModelList`. Since we need to update the models on the application toolkit thread, we use a `javax.swing.Timer` to regularly check whether new ASTERIX data is available on the input stream. If so, the method decodes that data and fires the necessary model events when the available data is decoded. To make the labels of the tracks move more fluently, the track layer is also refreshed every time, using the method `invalidateGXYLayer`. For instance, if the user dragged a label away, it will gently move back

The complete sample code can be found in the packages `samples.decoder.asterix.live` and `samples.decoder.asterix`.

#### Decoding category 240 radar video

The package `samples.decoder.asterix.lightspeed.radarvideo` demonstrates how raw radar video data can be visualized in a Lightspeed view. The sample sets up a `TLcdASTERIXLiveDecoder` in a similar way as the other samples described above. It then uses the class `TLspRadarVideoLayerBuilder` to create a layer that visualizes the data. Program: Creating a radar video layer illustrates this.

Program: Creating a radar video layer (from `samples/realtime/lightspeed/radarvideo/RadarVideoLayerFactory`)
``````public ILspEditableStyledLayer createLayer(ILcdModel aRadarModel) {

.newBuilder()
.selectable(false)
.build();

 Category 240 data requires an `ALcdASTERIXReferenceProvider` instead of an `ALcdASTERIXTransformationProvider`. The reference provider supplies a model reference that encapsulates the position and the orientation of the radar platform. The sample uses the default implementation, `TLcdASTERIXReferenceProvider`, which is sufficient for static radars. When you are working with moving platforms such as radars on a ship or aircraft, the reference provider needs to supply model references in which the origin of the projection follows the radar platform.

## Domain object times

All ASTERIX domain objects are time-aware, except for category 240 for which the time information is optional. The time information is extracted from one of the time related data items. The following table summarizes the time mapping for the available categories and UAP:

Cat UAP ASTERIX data item used for property Time

1

Track Plot

Truncated Time of Day

8

/

Time of Day

11

/

Time of Track Information

21

/

Time of Applicability for Position or Time of Message Reception for Position (depends on record data)

21 v0.23

/

Time of Day

30

/

Time of Last Update

30 v2.5 ter

/

Time of Last Update

48

/

Time of Day

62

/

Time of Day

240

Time Of Day

244

/

Time of Day

10

/

Time of Day

All time-related ASTERIX data items contain relative times. Usually these are times since midnight. However, the time properties of the domain objects need to reflect absolute times. Therefore, a time offset needs to be added to the ASTERIX times. The ASTERIX decoders take care of this. For the `TLcdASTERIXModelDecoder`, a day offset can be configured manually. For the `TLcdASTERIXLiveDecoder` and `TLcdASTERIXLiveModelDecoder`, the actual time is taken as offset. See ASTERIX Decoder Time for more information.

Some categories only have so-called truncated times. These are times since midnight that are truncated at the most significant side. For instance, only two bytes are available for representing the time for category 1, where in fact three would be required to represent all times to midnight. This means that for category 1, only relative times up to approximately eight minutes are available. The times in the headers of the ASTERIX Final Format files or PCAP files are used here to derive a time to midnight.

 The decoders can read files with the .asterix extension, which do not have any headers, but keep in mind that this can lead to incorrect times for categories that contain truncated times (category 1).

## Domain Object Properties

### Track properties mapped from ASTERIX data items

In the ASTERIX specification, each UAP of each category contains a number of data items. Refer to ASTERIX domain object modeling for more information on the ASTERIX data structure.

Data items in ASTERIX are mapped to values of properties (represented by `ILcdDataObject`) of ASTERIX tracks or plots in LuciadLightspeed . This is visualized in the diagram shown in Figure 1, “Mapping of data items to the LuciadLightspeed data object interface”. Note that `ILcdDataObject` is mentioned twice to simplify the diagram layout.

Figure 1. Mapping of data items to the LuciadLightspeed data object interface

A data record for a category can contain information for all or part of the data items. Data items that are not present in the data records are returned as `null` values.

A data item can be described by a data field, but can also have a more complex structure. Depending on its structure a data item can be mapped to a property in different ways:

• A data item that contains only one data field is mapped to a value of a simple type:

• This can be any standard data type like `java.lang.String`, `java.lang.Boolean`, `java.lang.Number`, `java.lang.Double`, …​

• A numeric data field that contains a measured value expressed in a certain unit, is mapped to a property of the LuciadLightspeed `com.luciad.util.iso19103.TLcdISO19103Measure`. This class is an extension of the standard `java.lang.Number` class . It has a method `ILcdISO19103UnitOfMeasure getUnitOfMeasure()` to retrieve the unit associated with the value. The unit is an `ILcdISO19103UnitOfMeasure` object, which has various methods to retrieve the (short) name, type, conversion to a standard unit, and so on. The data type for this this class is `TLcdASTERIXDataTypes.ISO_19103_MEASURE_TYPE`.

• Often a data field contains an integer value that can be chosen from a list of possibilities, each described by a `String`. Such values are mapped to `TLcdASTERIXMappedInteger` properties. The `TLcdASTERIXMappedInteger` class is an extension from the standard `Number` class. The method `intValue` returns the actual integer value. The methods `getValueDescription` and `toString` on the other hand return the descriptive `String` that corresponds with the integer value. The data type for this class is `TLcdASTERIXDataTypes.ABSTRACT_ASTERIX_MAPPED_INTEGER_TYPE`. This type is defined to be abstract. The data types that define this as a supertype will also include a list of possible values.

• A data item that consists of a list of data fields is mapped to a property that is of type `ILcdDataObject` itself. All properties of the `ILcdDataObject` will be primitive. For instance, a data item that represents a location in the longitude/latitude format, has two data fields: longitude and latitude. It is mapped to a property of type `ILcdDataObject` that contains two properties, each of the type `TLcdASTERIXDataTypes.ISO_19103_MEASURE_TYPE`, one for the longitude value and one for the latitude value.

• A data item that consists of a list of data fields is mapped to a list of `ILcdDataObject` instances. Each `ILcdDataObject` will have the given list of data fields as its properties.

• A data item can also be compound: it can consist of a list of data items, of which each contained data item can be present or not in a concrete data record. Such a data item is mapped to a property of type `ILcdDataObject` where all properties are as described in the previous points.

### Trajectory properties

All trajectories have at least an 'ID' property.

Depending on the UAP of the data, trajectories may have more properties. These extra properties represent the track properties that usually remain the same for the entire trajectory. For instance, trajectories of category 30 have a property 'Departure Airport' as each track of a trajectory usually describes the same departure airport.

The actual value of the trajectory property is the last track-value that is not `null`, or `null` if all track-values are `null`.

This is the list of available trajectory properties per category and UAP:

category 1, track UAP

no extra properties

category 1, plot UAP

no extra properties

category 10
• `TargetIdentification` : compound property, corresponds to the compound `TargetIdentification` track property.

category 11
• `TargetIdentification`: compound property, corresponds to the compound `TargetIdentification` track-property.

• `Callsign`: simple property, corresponds to the `Callsign` property of the compound `FlightPlanRelatedData` track-property.

• `IFPS_FLIGHT_ID`: compound property, corresponds to the `IFPS_FLIGHT_ID` property of the compound `FlightPlanRelatedData` track-property.

• `FlightCategory`: compound property, corresponds to the `FlightCategory` property of the compound `FlightPlanRelatedData` track-property.

• `TypeOfAircraft`: simple property, corresponds to the `TypeOfAircraft` property of the compound `FlightPlanRelatedData` track-property.

• `WakeTurbulenceCategory`: simple property, corresponds to the `WakeTurbulenceCategory` property of the compound `FlightPlanRelatedData` track-property.

• `DepartureAirport`: simple property, corresponds to the `DepartureAirport` property of the compound `FlightPlanRelatedData` track-property.

• `DestinationAirport`: simple property, corresponds to the `DestinationAirport` property of the compound `FlightPlanRelatedData` track-property.

category 21
• `EmitterCategory`: simple property, corresponds to the simple `EmitterCategory` track-property.

• `TargetIdentification`: simple property, corresponds to the simple `TargetIdentification` track-property.

category 21, version 0.23
• `EmitterCategory`: simple property, corresponds to the simple `EmitterCategory` track-property.

• `TargetIdentification`: simple property, corresponds to the simple `TargetIdentification` track-property.

category 30
• `Callsign`: simple property, corresponds to the simple `Callsign` track-property.

• `PLNNumber`: simple property, corresponds to the simple `PLNNumber` track-property.

• `DepartureAirport`: simple property, corresponds to the simple `DepartureAirport` track-property.

• `DestinationAirport`: simple property, corresponds to the simple `DestinationAirport` track-property.

• `CategoryOfTurbulence`: simple property, corresponds to the simple `CategoryOfTurbulence` track-property.

• `TypeOfAircraft`: simple property, corresponds to the simple `TypeOfAircraft` track-property.

• `FlightCategory`: compound property, corresponds to the compound `FlightCategory` track-property.

category 30, version 2.5 ter
• `Callsign`: simple property, corresponds to the simple `Callsign` track-property.

• `PLNNumber`: simple property, corresponds to the simple `PLNNumber` track-property.

• `DepartureAirport`: simple property, corresponds to the simple `DepartureAirport` track-property.

• `DestinationAirport`: simple property, corresponds to the simple `DestinationAirport` track-property.

• `CategoryOfTurbulence`: simple property, corresponds to the simple `CategoryOfTurbulence` track-property.

• `TypeOfAircraft`: simple property, corresponds to the simple `TypeOfAircraft` track-property.

• `FlightCategory`: compound property, corresponds to the compound `FlightCategory` track-property.

category 48
• `AircraftIdentification`: simple property, corresponds to the simple `AircraftIdentification` track-property.

category 62
• `TargetIdentification`: compound property, corresponds to the compound `TargetIdentification` track-property.

• `Callsign`: simple property, corresponds to the `Callsign` property of the compound `FlightPlanRelatedData` track-property.

• `IFPSFlightId`: compound property, corresponds to the `IFPSFlightId` property of the compound `FlightPlanRelatedData` track-property.

• `FlightCategory`: compound property, corresponds to the `FlightCategory` property of the compound `FlightPlanRelatedData` track-property.

• `TypeOfAircraft`: simple property, corresponds to the `TypeOfAircraft` property of the compound `FlightPlanRelatedData` track-property.

• `WakeTurbulenceCategory`: simple property, corresponds to the `WakeTurbulenceCategory` property of the compound `FlightPlanRelatedData` track-property.

• `DepartureAirport`: simple property, corresponds to the `DepartureAirport` property of the compound `FlightPlanRelatedData` track-property.

• `DestinationAirport`: simple property, corresponds to the `DestinationAirport` property of the compound `FlightPlanRelatedData` track-property.

category 244
• `TargetIdentification`: simple property, corresponds to the simple `TargetIdentification` track-property.

• `AircraftType`: simple property, corresponds to the simple `AircraftIdentification` track-property.

• `ADSBEmitterCategory`: simple property, corresponds to the simple `ADSBEmitterCategory` track-property.

The `TLcdDataType` of a trajectory describes which properties are available. These `TLcdDataType` instances are available as Java constants in the `TLcdASTERIXDataTypes` class. The constants for the trajectory data types all end in `*TrajectoryType`. You can inspect the trajectory-related `TLcdDataType` instances for each UAP with the `datamodelviewer` sample.

### Weather pictures and precipitation zones properties

The `TLcdDataType` of the weather picture contains the following properties :

• `DataSourceIdentifier`: an `ILcdDataObject` that contains the `System Area code` and `System Identifier Code` of the sensor that took the weather picture.

• `PrecipitationZones`: a `Collection` of the precipitation zones.

• `BeginTime`: the begin time of the weather picture, `null` if the time is undefined.

• `EndTime`: the end time of the weather picture, `null` if the time is undefined.

The `TLcdDataType` for precipitation zone contains only one property : `Intensity`, which is the intensity of the precipitation.

Like the `TLcdDataType` of trajectory, you can inspect the `TLcdDataType` of the weather picture with the `datamodelviewer` sample.

### Data types and properties

Category data items are mapped to properties of tracks or plots in LuciadLightspeed . You can inspect which properties are available by running the `datamodelviewer` sample.

The data type for each of the categories can be retrieved through the `TLcdASTERIXDataTypes.getTrackModelElementDataType(ALcdASTERIXUserApplicationProfile)` method. This method takes a UAP as an argument to determine the data type used by the elements of any given ASTERIX track or plot model.

The data models for the different tracks can be obtained through the `TLcdASTERIXDataTypes.getDataModel(ALcdASTERIXUserApplicationProfile aUserApplicationProfile)` method.

The data type used by `TLcdASTERIXTrajectory` domain objects can be retrieved using the static `TLcdASTERIXDataTypes.getTrajectoryDataType(ALcdASTERIXUserApplicationProfile)` method. To retrieve the data model, use the same method, and call the `getDataModel()` on the resulting `TLcdDataType`.

### Changing the value of properties

The object type determines whether you can change the value of the object properties:

`TLcdASTERIXTrajectory`

you can change all properties that correspond to a track-property that can change. Any other properties, such as the 'ID' of the trajectory cannot be changed. When you change a property of a trajectory, the property is changed for all points in time. How the properties of the trajectories correspond the those of the tracks is detailed in Trajectory properties.

`TLcdASTERIXTrack`

the properties that can be changed depend on the category and UAP. They are listed below. The property is only changed at the specific time of the track.

`TLcdASTERIXPlot`

the properties that can be changed for `TLcdASTERIXTrack` can also be changed for `TLcdASTERIXPlot`.

`TLcdASTERIXWeatherPicture`

the properties cannot be changed.

This is the list of track and plot properties that can be changed:

category 1, track UAP

none of the properties can be changed.

category 1, plot UAP

none of the properties can be changed.

category 10
• `TargetIdentification`: this is a compound property, all its sub-properties can be changed as well.

category 11
• `TargetIdentification`: this is a compound property, all its sub-properties can be changed as well.

• `FlightPlanRelatedData.Callsign`

• `FlightPlanRelatedData.IFPS_FLIGHT_ID`: this is a compound property, all its sub-properties can be changed as well.

• `FlightPlanRelatedData.FlightCategory`: this is a compound property, all its sub-properties can be changed as well.

• `FlightPlanRelatedData.TypeOfAircraft`

• `FlightPlanRelatedData.WakeTurbulenceCategory`

• `FlightPlanRelatedData.DepartureAirport`

• `FlightPlanRelatedData.DestinationAirport`

category 21
• `EmitterCategory`

• `TargetIdentification`

category 21, version 0.23
• `EmitterCategory`

• `TargetIdentification`

category 30
• `Callsign`

• `PLNNumber`

• `DepartureAirport`

• `DestinationAirport`

• `CategoryOfTurbulence`

• `TypeOfAircraft`

• `FlightCategory`: this is a compound property, all its sub-properties can be changed as well.

category 30, version 2.5 ter
• `Callsign`

• `PLNNumber`

• `DepartureAirport`

• `DestinationAirport`

• `CategoryOfTurbulence`

• `TypeOfAircraft`

• `FlightCategory`: this is a compound property, all its sub-properties can be changed as well.

category 48
• `AircraftIdentification`

category 62
• `TargetIdentification`: this is a compound property, all its sub-properties can be changed as well.

category 244
• `TargetIdentification`

• `AircraftType`

• `ADSBEmitterCategory`

You can change the value of the properties by calling the `setValue` method on the domain object. This method is part of the `ILcdDataObject` interface. See the Working with domain object properties page for more information.

Note that you cannot change the geometry or the timing information of a trajectory, track or plot.

### Support for the ILcdFeatured interface

Since LuciadLightspeed V10.1, the `ILcdDataObject` interface is used to represent the data of a domain object in ASTERIX. This interface contains all the information of the previous `ILcdFeatured` interface and more. The older `ILcdFeatured` interface is still supported for reasons of backward compatibility, but it is advised that you use `ILcdDataObject` where possible.

For more information on how to use the `ILcdFeatured` interface, consult the API documentation of the `ALcdASTERIXModelDescriptor` class.

## Model descriptors

The model descriptors of the category and UAP models depend on the type of domain objects in the model. They however all extend from `ALcdASTERIXModelDescriptor`. Following table gives an overview of the model descriptors that are currently used:

Domain Object Model Descriptor

TLcdASTERIXTrajectory

TLcdASTERIXTrajectoryModelDescriptor

TLcdASTERIXTrack

TLcdASTERIXTrackModelDescriptor

TLcdASTERIXPlot

TLcdASTERIXPlotModelDescriptor

TLcdASTERIXWeatherPicture

TLcdASTERIXWeatherModelDescriptor

### ALcdASTERIXModelDescriptor

Following information is always available through the interfaces and methods implemented by the class `ALcdASTERIXModelDescriptor`:

## Model references

### Transformation to WGS84

With the exception of category 240, which will be discussed below, all ASTERIX domain objects have a shape which allows to visualize them on a map. The points that define the shape are extracted from the data items that represent coordinates. The models containing the ASTERIX domain objects must be assigned an `ILcdModelReference` which corresponds to the ASTERIX coordinates. Two things must be considered here:

• ASTERIX coordinates can be in various formats (polar, Cartesian) and can be expressed with respect to different reference systems. Typically a local coordinate system is used. Locations are specified in coordinates relative to the radar location, for example.

• Since the ASTERIX decoders group category and UAP models (containing the ASTERIX domain objects) in a `TLcdModelList`, and all `ILcdModel` objects of a `TLcdModelList` need to have the same model reference, all category and UAP models must have the same model reference. This is chosen to be a WGS84 geodetic reference (`TLcdGeodeticReference`).

This implies that the coordinates of the ASTERIX data items must be transformed to express WGS84 geodetic coordinates. That’s where the `ALcdASTERIXTransformationProvider` comes in: it handles the coordinate transformations between the decoded ASTERIX coordinates and WGS84. An ASTERIX decoder can be assigned an `ALcdASTERIXTransformationProvider` that it then uses for the necessary transformations. (Refer to ASTERIX Transformation Provider.)

The `ALcdASTERIXTransformationProvider` is an abstract class. Make an extension of it and implement the `provideModelModelTransformation(int aSacSic, ILcdModel aModel, Object aObject)` method to provide the correct `ILcdModelModelTransformation` for the data you want to decode. The argument `aSacSic` represents the System Area Code (SAC) and System Identification Code (SIC). These codes define which radar surveillance system is used. The `aModel` argument can be used to retrieve the data category or UAP the data belongs to, so you can use it to implement a transformation per radar system and per data category.

For instance, for locations specified relative to the radar location, you need to know the position of the radar and also the exact definition of the radar-dependent grid reference. This extra information is not present in the data. You must therefore provide it by implementing a `ALcdASTERIXTransformationProvider`.

### Georeferencing of category 240 data

As mentioned above, ASTERIX category 240 is an exception to the rule that all model elements must be transformed to a WGS84 geodetic reference. For category 240 data, the decoder uses an `ALcdASTERIXReferenceProvider` to assign a model reference to the model. As a consequence, category 240 data cannot be decoded into a single `TLcdModelList` together with other data categories. Use a `TLcdModelTreeNode` instead of a `TLcdModelList` if you expect to decode category 240 data as well as other categories.

`ALcdASTERIXReferenceProvider` must return a model reference that encapsulates the position and orientation of the radar platform. Typically, this is an azimuthal equidistant reference. Its origin is the position of the radar and its rotation is the orientation of the radar platform. `TLcdASTERIXReferenceProvider` can be used for static radar platforms, where the model reference never needs to change. If the radar is on a moving platform such as a ship, however, the provider should return a model reference that reflects the current position and heading of the ship.

## Scaling factors

ASTERIX categories specify floating point data in fixed point notation, that is an integer value together with a factor. The factors are normally fixed for specific data items. However for some data items these factors are relative to a 'scaling factor' (f-value), for example one factor is specified as $2^{-6+f}$. That scaling factor is to be found elsewhere in the data, or from an external source.

The `ALcdASTERIXScalingFactorProvider` serves the purpose of providing the scaling factor to the ASTERIX decoders when it cannot be retrieved from the data source because it is not specified where to retrieve the scaling factor from, or if it is specified, but the actual data doesn’t contain a value for it.

Different data items can have different scaling factors. Constants are defined for all existing scaling factors. For instance the constant `TLcdASTERIXCategory1.CAT_1_CARTESIAN_COORDINATES` identifies the scaling factor for the Cartesian coordinates of category 1 data.

To implement a `ALcdASTERIXScalingFactorProvider` create a class that extends from `ALcdASTERIXScalingFactorProvider` and implement the `scalingFactor(ILcdModel aModel, int aID)` method to provide the correct scaling factor. The `aModel` argument represents the model containing the data for which the scaling factors are needed. The `aID` represents the id of the scaling factor to retrieve. It is one of the constants mentioned above. Finally attach your `ALcdASTERIXScalingFactorProvider` class to the decoder.

## Replaying recorded ASTERIX data

### Replay ASTERIX data with the LuciadLightspeed Real-Time Engine

The sample class `samples.decoder.asterix.file.MainPanel` demonstrates how to use ASTERIX data with the Real-Time Engine option for two types of models: ASTERIX trajectory models and ASTERIX weather models. In both cases, a `samples.decoder.asterix.ASTERIXTrackSimulatorModelFactory` first tries to create an instance of `ILcdSimulatorModel` for the ASTERIX model.

For trajectory models, the implementation of `ILcdSimulatorModel` creates and keeps track models that hold the simulated trajectory data. This data changes dynamically, in function of the time set by the simulator. The sample class `samples.decoder.asterix.SimulatorGXYLayerFactory` creates a layer for such dynamic models.

The `ILcdSimulatorModel` treats weather data differently. Instead of making track models, it filters the layer created from the weather model: only the weather pictures that are active for the given time are displayed. If there are no active weather pictures, the most recent previous weather pictures are shown.

### Replay input stream

It is also possible to replay the data from files in ASTERIX Final format or PCAP format as if it came from a live stream of data.

For this purpose, a class `TLcdASTERIXFinalReplayInputStream` is introduced. It reads an `.astfin` file in the ASTERIX Final Format or a `.pcap` file in the PCAP format, and uses the time information in the headers to replay the data: the data is only made available after the time between 2 headers has passed.

The `TLcdASTERIXFinalReplayInputStream` can be configured through the following classes and methods:

• Constructors with `InputStream`: unless the format is explicitly specified, it is assumed that the data is in the ASTERIX final format. So when you are reading PCAP files, you need to specify the PCAP format in the constructor. Please refer to the reference documentation for more details.

• Constructors with `TLcdASTERIXDataSource`: the extension of the source names in the `TLcdASTERIXDataSource` are used to determine the format of the file. Again. only files in ASTERIX final format and PCAP format are supported.

• The `TLcdASTERIXFinalReplayInputStream` is an extension of `java.io.PipedInputStream`, so it offers all methods that are available here.

• The `void setExceptionHandler( ILcdExceptionHandler aExceptionHandler )` method allows to specify an exception handler that is called whenever a non recoverable exception occurs. It can for example be used to pop up a dialog that informs the user about the problem.

#### Sample

The sample class `samples.decoder.asterix.live.MainPanel` implements a sample that creates a `TLcdASTERIXLiveDecoder` using a `TLcdASTERIXFinalReplayInputStream`.

Program: Create a replay stream (from `samples/decoder/asterix/LiveDecodedModel`)
``````private InputStream createFinalReplayInputStream(String aAsterixFile, int aFileFormat) throws IOException {
try {
TLcdInputStreamFactory inputStreamFactory = new TLcdInputStreamFactory();
InputStream inputStream = inputStreamFactory.createInputStream(aAsterixFile);
return new TLcdASTERIXFinalReplayInputStream(inputStream, 20, aFileFormat);
} catch (IOException e) {
LOGGER.error(TLcdASTERIXFinalReplayInputStream.class.getName() + ".<init>", "The file [" + aAsterixFile + "] could not be found.", e);
throw e;
}
}``````

Program: Create a replay stream shows the implementation of the method `createFinalReplayInputStream(String aASTERIXFinalFormatFile)` that is used to create the `TLcdASTERIXFinalReplayInputStream`. It has an argument `aASTERIXFinalFormatFile` that is the name of the Final Format file containing the ASTERIX data to replay. The method first creates a `InputStream` on the specified file using the `createInputStream` method of the `TLcdInputStreamFactory`. In the next step a `TLcdASTERIXFinalReplayInputStream` is created for this `InputStream`, and is returned as result of the method.

The resulting `InputStream` can then be used in the `startLiveDecoder` of Program: Starting an ASTERIX live decoder.

The complete sample code can be found in the packages `samples.decoder.asterix.live` and `samples.decoder.asterix`.

## Filtering ASTERIX data

When decoding ASTERIX data by reading a live stream, files, or when using the replay facility, you may need to filter the data. You may want to ignore data from a certain radar system, for example, or ignore all coasted tracks. To that end, all ASTERIX decoders can filter data on a record level (see ASTERIX domain object modeling for what a data record is). For every record, the filter can inspect the values of every data item and decide to keep or reject the record. Such a data record is provided as an `ILcdDataObject`, bringing the power of the data model API, for example its expression language to select the required data properties.

The API conveniently provides a `TLcdASTERIXSacSicRecordFilter` to filter data based on its originating radar systems, defined by its SAC/SIC code. This could for example be useful to remove zig-zag effects caused by two radar systems reporting on the same tracks in turn, but with slightly different locations.

The API also provides a `TLcdASTERIXAltitudeRecordFilter` to filter tracks and plots based on their altitude. This can be useful when your data contains tracks with an invalid altitude. Typically in those cases the altitude of such a track is unrealistically high.

Next to that, a dedicated filter sample demonstrates how to implement a custom record filter. A record filter should be set to the decoder as shown in Program: Set a record filter to an ASTERIX decoder.

Program: Set a record filter to an ASTERIX decoder (from `samples/decoder/asterix/filter/MainPanel`)
``````private void initializeRecordFilter(ALcdASTERIXDecoder aDecoder) {
// Specify the filter that should be used during decoding
}``````

The custom record filter implementation is shown in Program: Record filter implementation. In the `accept` method, it first verifies the data type of the given record with the expected category 62 track type. Other data, for example from other categories, is left untouched and `true` is returned.

It then requests the data property `TrackNumber` using a data model expression. The expression was generated using the `datamodelviewer` sample: start the sample, click the `Category62Type` button and browse for `TrackNumber`. It shows the return type is an `Integer`, and it generates the expression as shown in Program: Track number expression generated by datamodelviewer sample.. Because our filter constantly reuses the same expression, it was restructured to be precompiled, which is slightly more efficient. Please refer to the data model API for more information.

Program: Track number expression generated by datamodelviewer sample.
``````new TLcdDataObjectExpressionLanguage().evaluate(
"TrackNumber",
category62 //specify the actual domain object instance here
);``````

Finally if the track number is present, and if the track number is less than 30, the record is accepted. Otherwise it is rejected. This is of course not a real-world scenario, mostly because fake data is used that does not specify other data items. But this filter does show the potential possibilities, and can easily be adapted to match specific needs.

Program: Record filter implementation (from `samples/decoder/asterix/filter/MainPanel`)
``````private static class TrackNumberRecordFilter implements ILcdASTERIXRecordFilter {
// Expression was created using the datamodelviewer sample: select Category62Type and
// browse for the track number property. It is specified to be an integer.
private final ILcdDataObjectExpression fTrackNumberExpression =
new TLcdDataObjectExpressionLanguage().compile("TrackNumber");

@Override
public boolean accept(ILcdDataObject aASTERIXRecord) {
// If we have tracks from category 62
if (TLcdASTERIXDataTypes.Category62TrackType.equals(aASTERIXRecord.getDataType())) {
// Fetch the track number if available
Integer trackNumber = (Integer) fTrackNumberExpression.evaluate(
new TLcdDataObjectExpressionContext(aASTERIXRecord));

// Only keep tracks that specify their track number to be less than 30
return trackNumber != null && trackNumber < 30;
} else {
// Accept other data, for example other categories
return true;
}
}
}``````

## Supported versions of category 21

For category 21, two versions are supported:

• Version 2.1: the final version from 2011 (default)

• Version 0.23 : a draft version from 2003

Data in either of these two versions cannot be automatically distinguished: only the category number is available from the data, not the version number. Although both versions are fairly similar, the binary data is incompatible. You must therefore explicitly enable version 0.23 if you want to use it. Please refer to `TLcdASTERIXCategory21Version0Dot23` for more information. If an attempt is made to read data from version 0.23 with the decoder assuming the default v2.1, the behavior is unpredictable. Typically, these attempts result in runtime errors such as `ArrayIndexOutOfBoundsException` instances or `IllegalArgumentException` instances.

## Supported versions of category 30

For category 30, two versions are supported:

• Version 6.1: the final version from 2000 (default)

• Version 2.5 ter: a draft version from 1997

Data in either of these two versions cannot be automatically distinguished: only the category number is available from the data, not the version number. Although both versions are fairly similar, the binary data is incompatible. You must therefore explicitly enable version 2.5 ter if you want to use it. Please refer to `TLcdASTERIXCategory30Version2Dot5Ter` for more information. If an attempt is made to read data from version 2.5 ter with the decoder assuming the default v6.1, the behavior is unpredictable. Typically, these attempts result in runtime errors such as `ArrayIndexOutOfBoundsException` instances or `IllegalArgumentException` instances.