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 transformation provider ALcdASTERIXTransformationProvider can be specified for both decoders using the setTransformationProvider method. The provided transformations are used to convert the relative ASTERIX coordinates to absolute ASTERIX WGS84 latitude longitude coordinates. Refer to Model references for more information on transformation providers. Note that for category 240 radar video data, an ALcdASTERIXReferenceProvider is used instead. This provider supplies an ILcdModelReference that encapsulates the position and orientation of the radar platform.

  • 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));
openSupport.addModelProducerListener(new ASTERIXModelProducerListener());
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) {

  ILspEditableStyledLayer radarLayer = TLspRadarVideoLayerBuilder
      .newBuilder()
      .selectable(false)
      .model(aRadarModel)
      .build();

  return radarLayer;

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

Radar

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.

features
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

TLcdRadar

TLcdASTERIXRadarVideoModelDescriptor

ALcdASTERIXModelDescriptor

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

  • An ALcdASTERIXModelDescriptor is an ILcdDataModelDescriptor. It allows you to retrieve the data model of the model it represents, as well as a list of the data types used by the elements of the model.

  • The methods getCategory and getUAP can be used to retrieve the category and UAP that corresponds with the data. This can for instance be used in the ILcdGXYLayerFactory to distinct between the different categories and UAP.

  • The methods getTransformationProvider and getScalingFactorProvider can be used to retrieve the providers used to extract the domain objects in the model from the ASTERIX data. For more info on these providers refer to Transformation to WGS84 and Scaling factors

  • TLcdASTERIXRadarVideoModelDescriptor, which is used for category 240 radar video, has a method getReferenceProvider. It returns the provider for the model reference of the decoded ASTERIX data. See Model references for more details.

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.

Using the TLcdASTERIXLiveDecoder with a TLcdASTERIXFinalReplayInputStream allows to replay ASTERIX data.

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
  aDecoder.setRecordFilter(new TrackNumberRecordFilter());
}

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.