DIS pipelines
HEAT records Distributed Interactive Simulation (DIS, IEEE 1278.1) traffic exactly as it was sent, and decodes it afterwards. The recording is done by HEAT Capture on the network. The decoding is done by nodes of a session template, on the platform’s runners.
Keeping the two steps apart has a purpose. The stored capture is the original bytes of every Protocol Data Unit (PDU), so nothing is lost to a decoder’s assumptions. A session can be decoded again later with a newer template, and the capture step stays light enough to run beside a simulator.
Decoding a PDU is not the same as understanding an exercise. A decoded PDU is a JSON object with the fields DIS defines. What those fields mean for a training objective is decided by the nodes that follow.
The path
DIS network
-> Open DIS module (HEAT Capture) records each PDU, untouched, with a capture time
-> input node the stored capture
-> hydrate-protobuf (PDU) decodes every PDU into JSON, JSON Lines or CSV
-> opendis-decode reshapes the decoded list
-> entity-state-to-records turns Entity State PDUs into entity-state records
-> entity-state-to-mapdisplay movement tracks for the MapDisplay widget
-> entity-state-to-flightpath flight paths for the FlightPath widgetRecording
The Open DIS module listens for DIS-7 PDUs on a UDP port, as broadcast or multicast. It checks the PDU header, wraps the raw bytes in a HEAT ProtoLib PDU message and stamps the message with the capture time. It does not read the content of the PDU.
The module can also start and stop a capture session from the DIS traffic it sees. See its Configure page.
A DIS recording made by another tool can be uploaded as a file instead. opendis-parser splits a raw DIS byte stream into PDUs and converts each one to JSON.
Decoding
hydrate-protobuf with targetProtoType set to HEAT.OpenDISModule.PDU decodes every recorded PDU. It runs on the core-utils runner.
| Output | Setting | Use it for |
|---|---|---|
JSON, one open_dis_pdu array | The default | Small captures and the nodes below |
| JSON Lines, one PDU on each line | lineDelimitedJson: true | Large captures and streaming readers |
CSV with dotted column names such as pdu.pduType | outputFormat: csv with incrementalHydration: true | tabular-query, spreadsheets and Bulk analytics |
incrementalHydration decodes only the PDUs that arrived since the last run, which suits a live capture. excludePduTypes drops PDU types you do not need. hydrate-protobuf-journal is the form for a live session. It publishes only the newly decoded rows as an append-only journal.
Radio traffic has its own path. With targetProtoType set to SignalPDU, the node decodes DIS Signal PDUs to audio and publishes a WAV file. With groupByOrigin: true it publishes one WAV file for each radio, so speech can be attributed and placed on the timeline.
PDU types
The node decodes PDUs with the open-source Open DIS library for Python. Every PDU type that library implements becomes a JSON object with its DIS field names.
| Family | PDU types decoded |
|---|---|
| Entity information | Entity State, Entity State Update, Collision, Collision Elastic |
| Warfare | Fire, Detonation, Entity Damage Status |
| Radio communications | Transmitter, Signal, Receiver, Intercom Signal, Intercom Control |
| Distributed emission | Electromagnetic Emission, Designator, Underwater Acoustic |
| Simulation management | Create Entity, Remove Entity, Start or Resume, Stop or Freeze, Acknowledge, Action Request, Action Response, Data Query, Set Data, Data, Event Report, Comment, and their reliable variants |
| Logistics | Service Request, Resupply Received, Repair Complete, Repair Response |
| Entity management | Is Part Of |
| Minefield | Minefield State, Minefield Response NACK |
| Synthetic environment | Point Object State, Linear Object State, Areal Object State |
The library version in the runner image decides the exact list. A PDU of a type the library does not implement is not decoded. Its original bytes remain in the stored capture.
From decoded PDUs to results
| Need | Nodes | Result |
|---|---|---|
| Entity movement on a map | opendis-decode, entity-state-to-records, entity-state-to-mapdisplay | A channel for the MapDisplay widget |
| Flight paths with altitude | The same chain, ending in entity-state-to-flightpath | Channels for the FlightPath widget |
| Radio audio | hydrate-protobuf with SignalPDU | One WAV file, or one for each radio |
| Counts, timings and sequences of any PDU type | hydrate-protobuf to CSV, then tabular-query or an Arbex script | Tables, measures and chart channels that you define |
Ready-made result nodes exist for Entity State PDUs and Signal PDUs. A node that turns Fire and Detonation PDUs directly into engagement results is not available today. Those PDUs are decoded, and a session template works on them with tabular-query or Arbex.
Where the meaning is added
The decoded PDUs say what happened on the network. They do not say whether a crew met a standard. A session template adds that meaning in its later nodes, where it matches events to entities, measures the time between them and compares the result with the criteria the training audience set.
Write the measures a report should carry into the session metadata. See Reports API.