Astro~/0.4
** Conformance / TDM * PAGE 26 / 30
** Astro * Conformance
** /conformance/tdm

Tracking Data Message

Coverage matrix: what this package implements, clause by clause.

Conformance Statement for pkg/tdm, CCSDS 503.0-B-2

CCSDS 503.0-B-2 annex A ships an Implementation Conformance Statement. What follows fills in its shape for both forms: the key-value notation and the XML form of section 5.


A1 IDENTIFICATION

FieldValue
Date of Statement (DD/MM/YYYY)04/09/2026
ICS Serial NumberASTRO-TDM-ICS-001
Implementation Nameastro/pkg/tdm
Implementation VersionSee go.mod / latest commit on main
SupplierRavi Suhag
Contact Point for QueriesGitHub, github.com/ravisuhag/astro
SpecificationCCSDS 503.0-B-2 (Tracking Data Message, Blue Book, June 2020, with updates)
Time formatsCCSDS 301.0-B-4 ASCII time codes A and B, via pkg/tcf
Have any exceptions been required?Yes [X] No [ ], see A3

A2 REQUIREMENTS

Structure

FeatureReferenceStatusSupport
TDM is ASCII text3.1.1MY
Header, then a body of one or more segments3.1.3MY
Segment is a metadata section plus a data section3.1.2MY
A data section holds at least one record3.1.3MY: ErrNoRecords
No limit on segments3.1.3MY: bounded by the input only
A metadata section precedes each data section3.3.1.3MY: ErrMissingDataSection
A new segment on any metadata change3.3.1.4MY: segments are kept separate, never flattened
META_START and META_STOP first and last in a metadata section3.3.1.5MY
DATA_START and DATA_STOP first and last in a data section3.4.7, 3.5.1MY
Exchange as a stream or a file3.1.5MN: a file only, see A3
FeatureReferenceStatusSupport
CCSDS_TDM_VERSTable 3-2MY
COMMENTTable 3-2OY
CREATION_DATETable 3-2MY: UTC
ORIGINATORTable 3-2MY: not checked against the SANA registry
MESSAGE_IDTable 3-2OY
No CLASSIFICATIONTable 3-2Y: refused, since table 3-2 does not list it

Metadata

FeatureReferenceStatusSupport
keyword = value on every line but a comment3.3.1.2MY
Only the keywords of table 3-33.3.1.7MY: ErrUnknownKeyword
TIME_SYSTEMTable 3-3MY: ErrMissingTimeSystem
PARTICIPANT_n, at least one, index 1 to 5Table 3-3MY: ErrMissingParticipant, ErrParticipantIndex
The other forty-odd optional keywordsTable 3-3OY: carried in wire order, reachable by Get
Indexed families TRANSMIT_DELAY_n, RECEIVE_DELAY_nTable 3-3OY
Default values applied where the table defines one3.3.1.7MPartial: RANGE_UNITS only, see A3

Data

FeatureReferenceStatusSupport
Record is keyword = timetag measurement3.4.1, Table 3-4MY
One record per line3.4.2MY
A timetag and one observable, both required3.4.3MY: ErrMalformedRecord
At least one blank between them3.4.4MY: any run of blanks
No mandatory data keywords beyond the delimiters3.4.6MY
Only the keywords of table 3-53.5.1MY
Indexed families to index 5Table 3-5OY: including TRANSMIT_FREQ_RATE_n, which shares a prefix with TRANSMIT_FREQ_n
RECEIVE_FREQ legal bare and indexedTable 3-5OY: TRANSMIT_FREQ bare is refused, as the table lists only the indexed form

Syntax

FeatureReferenceStatusSupport
Line length ceiling4.2MY: 254 characters
Printable ASCII and blanks only4.2MY
Integer and non-integer value forms4.3MY: shared with the ODM through internal/ndm
Timetag formats4.3.9MY: both ASCII time codes, via pkg/tcf
Comment placement4.5OY: header, metadata section, data section

XML form, section 5

FeatureReferenceStatusSupport
Root element with id and version attributes5M
Master schema for the TDM5O
NDM namespace declared505.0-B-3 clause 4.3.4M
One observation element per record5M
A timetag and exactly one observable per observation3.4.3M
Metadata as a flat element list5M
NDM combined instantiation505.0-B-3 clause 4.11O

A3 EXCEPTIONS AND UNSUPPORTED FEATURES

Streaming is not supported. Clause 3.1.5 says a TDM may be exchanged as a real-time stream or as a file. Decode takes a complete message. A stream would need the segment structure delivered incrementally, and the delimiters make that possible, but nothing here does it.

No tracking mathematics. Nothing differences a range, unwraps an ambiguous one, applies a media, clock or delay correction, or converts an angle between frames. The metadata that describes those corrections is carried faithfully and acted on by nobody. This matters most for two keywords: a non-zero RANGE_MODULUS means clause 3.5.2.7's ambiguous range, which "does not represent the actual range to the spacecraft" until the modulus is applied, and CORRECTIONS_APPLIED tells a reader whether the producer has already folded its corrections in.

Only one default is applied. Clause 3.3.1.7 says a keyword with a defined default should be assumed when absent. RANGE_UNITS is implemented that way, because reading a range in the wrong units is a silent order-of-magnitude error. The other defaults are left to the caller: applying them would mean this package deciding what a segment meant, and Get reports absence truthfully so a caller can decide.

Enumerated values are not enforced. MODE, RANGE_MODE, TIMETAG_REF, DATA_QUALITY and the rest have normative value sets in table 3-3. They are carried as written. Refusing an unlisted value would refuse a message a later issue of the standard makes legal.

Registry values are not checked. PARTICIPANT_n may be a station name, a spacecraft designator or a quasar catalogue name; ORIGINATOR points at the SANA organizations registry. Neither is validated.


A4 IMPLEMENTATION LIMITS

LimitValueSource
Line length254 charactersClause 4.2
Participant index1 to 5Table 3-3
Data keyword index1 to 5Table 3-5
Segments per messagebounded by the inputClause 3.1.3 imposes none
Records per segmentbounded by the inputRecords are read into memory rather than streamed

Wire test vectors

The files backing this statement live in the vector corpus — 1 decode vector and 1 corpus file.

File
tdm/tracking.json1 vector
tdm/two-way-range.kvnthe annex E example as a readable file

Both are published text rather than derived values: annex E of the Blue Book prints the example.

The vector asserts the metadata that decides how a measurement must be read — the time system, the participants, the mode and path, and above all the range units and whether they were stated or defaulted — plus the record counts. The measurements are floats, which a vector field cannot hold, and are checked in pkg/tdm against the same published text.

See CONTRACT.md for how to consume these, and how this is verified for what rests on a published vector versus a reading of the clause.