Creating OMMs

An Orbit Mean-Elements Message (OMM) is represented by the OrbitMeanElementsMessage type. Although this structure follows the nested hierarchy defined by the CCSDS standard (header, metadata, and data), we can create a complete message using a single keyword constructor. It takes care of assembling the internal sections for us.

OrbitMeanElementsMessage(; kwargs...) -> OrbitMeanElementsMessage

Date Fields

The fields creation_date, epoch, and ref_frame_epoch must be provided as NanoDate objects so that the message can retain the sub-second precision usually present in orbit data. We can build a NanoDate from a string or from a Dates.DateTime:

julia> using NanoDates
julia> NanoDate("2025-12-30T18:12:04.533984")2025-12-30T18:12:04.533984
julia> NanoDate(DateTime(2025, 12, 30, 18, 12, 4))2025-12-30T18:12:04

Minimal Example

The keyword constructor requires the mandatory fields defined by the standard: the message originator, the object identification, the reference frame and time system, and the mean Keplerian elements. The following example creates the OMM for the Amazonia 1 satellite:

julia> omm = OrbitMeanElementsMessage(;
           # == Header ========================================================
           creation_date       = NanoDate("2025-12-30T23:36:37"),
           originator          = "18 SPCS",
       
           # == Metadata ======================================================
           object_name         = "AMAZONIA 1",
           object_id           = "2021-015A",
           center_name         = "EARTH",
           ref_frame           = "TEME",
           time_system         = "UTC",
           mean_element_theory = "SGP4",
       
           # == Mean Keplerian Elements =======================================
           epoch               = NanoDate("2025-12-30T18:12:04.533984"),
           mean_motion         = 14.40772474,
           eccentricity        = 0.00011240,
           inclination         = 98.3721,
           raan                = 75.0877,
           arg_of_pericenter   = 97.3772,
           mean_anomaly        = 262.7545,
       )OrbitMeanElementsMessage:
  ├─ Header
  │    Creation Date : 2025-12-30T23:36:37
  │    Originator    : 18 SPCS
  ├─ Metadata
  │    Object Name         : AMAZONIA 1
  │    Object ID           : 2021-015A
  │    Center Name         : EARTH
  │    Ref. Frame          : TEME
  │    Time System         : UTC
  │    Mean Element Theory : SGP4
  └─ Data
       └─ Mean Keplerian Elements
            Epoch              : 2025-12-30T18:12:04.533984
            Mean Motion        : 14.40772474 rev/day
            Eccentricity       : 0.0001124
            Inclination        : 98.3721°
            RA of Asc. Node    : 75.0877°
            Arg. of Pericenter : 97.3772°
            Mean Anomaly       : 262.7545°
Note

The mean elements section requires either mean_motion or semi_major_axis. All angular quantities (inclination, raan, arg_of_pericenter, and mean_anomaly) are expressed in degrees, following the CCSDS 502.0-B-3 convention.

Adding Optional Sections

The OMM standard defines several optional sections. They can be populated by passing the corresponding keywords. For example, we can add the TLE-related parameters and some spacecraft data:

julia> omm = OrbitMeanElementsMessage(;
           creation_date       = NanoDate("2025-12-30T23:36:37"),
           originator          = "18 SPCS",
           object_name         = "AMAZONIA 1",
           object_id           = "2021-015A",
           center_name         = "EARTH",
           ref_frame           = "TEME",
           time_system         = "UTC",
           mean_element_theory = "SGP4",
           epoch               = NanoDate("2025-12-30T18:12:04.533984"),
           mean_motion         = 14.40772474,
           eccentricity        = 0.00011240,
           inclination         = 98.3721,
           raan                = 75.0877,
           arg_of_pericenter   = 97.3772,
           mean_anomaly        = 262.7545,
       
           # == Spacecraft Data ===============================================
           mass                = 640.0,
           drag_area           = 8.5,
           drag_coeff          = 2.2,
       
           # == TLE-Related Parameters ========================================
           norad_cat_id        = 47699,
           classification_type = 'U',
           element_set_number  = 999,
           rev_at_epoch        = 25439,
           bstar               = 0.0001533,
           mean_motion_dot     = 0.00000447,
           mean_motion_ddot    = 0.0,
       
           # == User-Defined Parameters =======================================
           user_defined_parameters = [
               "COUNTRY_CODE" => "BRAZ",
               "LAUNCH_DATE"  => "2021-02-28",
           ],
       )OrbitMeanElementsMessage:
  ├─ Header
  │    Creation Date : 2025-12-30T23:36:37
  │    Originator    : 18 SPCS
  ├─ Metadata
  │    Object Name         : AMAZONIA 1
  │    Object ID           : 2021-015A
  │    Center Name         : EARTH
  │    Ref. Frame          : TEME
  │    Time System         : UTC
  │    Mean Element Theory : SGP4
  └─ Data
       ├─ Mean Keplerian Elements
       │    Epoch              : 2025-12-30T18:12:04.533984
       │    Mean Motion        : 14.40772474 rev/day
       │    Eccentricity       : 0.0001124
       │    Inclination        : 98.3721°
       │    RA of Asc. Node    : 75.0877°
       │    Arg. of Pericenter : 97.3772°
       │    Mean Anomaly       : 262.7545°
       ├─ Spacecraft Parameters
       │    Mass             : 640.0 kg
       │    Drag Area        : 8.5 m²
       │    Drag Coefficient : 2.2
       ├─ TLE Related Parameters
       │    Classification Type : U
       │    NORAD Cat ID        : 47699
       │    Element Set Number  : 999
       │    Rev at Epoch        : 25439
       │    B*                  : 0.0001533 1/ER
       │    ∂(Mean Motion)/∂t   : 4.47e-6 rev/day²
       │    ∂²(Mean Motion)/∂t² : 0.0 rev/day³
       └─ User-Defined Parameters
            COUNTRY_CODE : BRAZ
            LAUNCH_DATE  : 2021-02-28

Building the Sections Individually

The sections can also be created one at a time with the keyword constructors of OmmHeader, OmmMetadata, and OmmData, whose keywords are the section fields, and then assembled into the message. This form is convenient when the sections come from different sources or are reused across messages:

julia> header = OmmHeader(;
           creation_date = NanoDate("2025-12-30T23:36:37"),
           originator    = "18 SPCS",
       )OmmHeader(String[], nothing, 2025-12-30T23:36:37, "18 SPCS", nothing)
julia> metadata = OmmMetadata(; object_name = "AMAZONIA 1", object_id = "2021-015A", center_name = "EARTH", ref_frame = "TEME", time_system = "UTC", mean_element_theory = "SGP4", )OmmMetadata(String[], "AMAZONIA 1", "2021-015A", "EARTH", "TEME", nothing, "UTC", "SGP4")
julia> data = OmmData(; epoch = NanoDate("2025-12-30T18:12:04.533984"), mean_motion = 14.40772474, eccentricity = 0.00011240, inclination = 98.3721, raan = 75.0877, arg_of_pericenter = 97.3772, mean_anomaly = 262.7545, )OmmData(String[], String[], 2025-12-30T18:12:04.533984, nothing, 14.40772474, 0.0001124, 98.3721, 75.0877, 97.3772, 262.7545, nothing, String[], nothing, nothing, nothing, nothing, nothing, String[], nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing, Pair{String, String}[])
julia> omm = OrbitMeanElementsMessage(header, metadata, data)OrbitMeanElementsMessage: ├─ Header │ Creation Date : 2025-12-30T23:36:37 │ Originator : 18 SPCS ├─ Metadata │ Object Name : AMAZONIA 1 │ Object ID : 2021-015A │ Center Name : EARTH │ Ref. Frame : TEME │ Time System : UTC │ Mean Element Theory : SGP4 └─ Data └─ Mean Keplerian Elements Epoch : 2025-12-30T18:12:04.533984 Mean Motion : 14.40772474 rev/day Eccentricity : 0.0001124 Inclination : 98.3721° RA of Asc. Node : 75.0877° Arg. of Pericenter : 97.3772° Mean Anomaly : 262.7545°

The rules relating the fields (for example, exactly one of semi_major_axis and mean_motion) are checked when the message is assembled, so an invalid section is rejected at that point. Each section also has a copy constructor that overrides selected fields, e.g. OmmData(data; mean_motion = 14.5).

The type name is long, so the package exports the alias OMM, which can be used wherever OrbitMeanElementsMessage is expected:

julia> OMM === OrbitMeanElementsMessagetrue

Covariance Matrix

The covariance matrix section, OmmCovarianceMatrix, stores the 21 elements of the lower triangle with their CCSDS names (cx_x, cy_x, etc.). It can be created from a 6×6 matrix whose rows and columns are ordered as (x, y, z, ẋ, ẏ, ż), and the full matrix is recovered with Matrix or SMatrix:

julia> using StaticArrays
julia> matrix = [i == j ? 1.0 : 0.1 for i in 1:6, j in 1:6]6×6 Matrix{Float64}: 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0
julia> cov = OmmCovarianceMatrix(matrix; cov_ref_frame = "RTN")OmmCovarianceMatrix(String[], "RTN", 1.0, 0.1, 1.0, 0.1, 0.1, 1.0, 0.1, 0.1, 0.1, 1.0, 0.1, 0.1, 0.1, 0.1, 1.0, 0.1, 0.1, 0.1, 0.1, 0.1, 1.0)
julia> cov.cy_x0.1
julia> Matrix(cov)6×6 Matrix{Float64}: 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0
julia> SMatrix(cov)6×6 StaticArraysCore.SMatrix{6, 6, Float64, 36} with indices SOneTo(6)×SOneTo(6): 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0 0.1 0.1 0.1 0.1 0.1 0.1 1.0

Copying and Modifying a Message

Since OrbitMeanElementsMessage is immutable, we can create a modified copy of an existing message by passing it to the constructor together with the keywords we want to override. The remaining fields are copied from the original message:

julia> new_omm = OrbitMeanElementsMessage(omm; originator = "SATELLITE TOOLBOX")OrbitMeanElementsMessage:
  ├─ Header
  │    Creation Date : 2025-12-30T23:36:37
  │    Originator    : SATELLITE TOOLBOX
  ├─ Metadata
  │    Object Name         : AMAZONIA 1
  │    Object ID           : 2021-015A
  │    Center Name         : EARTH
  │    Ref. Frame          : TEME
  │    Time System         : UTC
  │    Mean Element Theory : SGP4
  └─ Data
       └─ Mean Keplerian Elements
            Epoch              : 2025-12-30T18:12:04.533984
            Mean Motion        : 14.40772474 rev/day
            Eccentricity       : 0.0001124
            Inclination        : 98.3721°
            RA of Asc. Node    : 75.0877°
            Arg. of Pericenter : 97.3772°
            Mean Anomaly       : 262.7545°
julia> new_omm.header.originator"SATELLITE TOOLBOX"

Available Keywords

The following table lists all keywords accepted by the constructor. Fields marked as required must always be provided.

KeywordTypeSectionRequired
header_commentsVector{String}Header
classificationStringHeader
creation_dateNanoDateHeader✅
originatorStringHeader✅
message_idStringHeader
metadata_commentsVector{String}Metadata
object_nameStringMetadata✅
object_idStringMetadata✅
center_nameStringMetadata✅
ref_frameStringMetadata✅
ref_frame_epochNanoDateMetadata
time_systemStringMetadata✅
mean_element_theoryStringMetadata✅
data_commentsVector{String}Data
mean_elements_commentsVector{String}Mean Elements
epochNanoDateMean Elements✅
semi_major_axisFloat64Mean Elements✅ [1]
mean_motionFloat64Mean Elements✅ [1]
eccentricityFloat64Mean Elements✅
inclinationFloat64Mean Elements✅
raanFloat64Mean Elements✅
arg_of_pericenterFloat64Mean Elements✅
mean_anomalyFloat64Mean Elements✅
GMFloat64Mean Elements
spacecraft_parameters_commentsVector{String}Spacecraft Data
massFloat64Spacecraft Data
solar_rad_areaFloat64Spacecraft Data
solar_rad_coeffFloat64Spacecraft Data
drag_areaFloat64Spacecraft Data
drag_coeffFloat64Spacecraft Data
tle_parameters_commentsVector{String}TLE Parameters
ephemeris_typeIntTLE Parameters
classification_typeCharTLE Parameters
norad_cat_idIntTLE Parameters
element_set_numberIntTLE Parameters
rev_at_epochIntTLE Parameters
bstarFloat64TLE Parameters
btermFloat64TLE Parameters
mean_motion_dotFloat64TLE Parameters
mean_motion_ddotFloat64TLE Parameters
agomFloat64TLE Parameters
covariance_matrixOmmCovarianceMatrixCovariance Matrix
user_defined_parametersVector{Pair{String, String}}User-Defined

Comment keywords accept vectors because each XML section may contain multiple COMMENT elements. data_comments applies directly to <data>, while mean_elements_comments applies to <meanElements>.

If any TLE-related parameter is supplied, mean_motion_dot is required. Exactly one of bstar or bterm, and exactly one of mean_motion_ddot or agom, must also be supplied. The constructor throws ArgumentError when these constraints are not met.

Covariance Matrix

The OMM standard defines an optional covariance matrix section. It is represented by the OmmCovarianceMatrix type, which stores the 21 unique upper-triangular elements of the symmetric 6×6 matrix, along with an optional comment and reference frame:

julia> cov = OmmCovarianceMatrix(;
           cov_ref_frame = "ITRF",
           cx_x           = 1.0,
           cy_x           = 2.0,
           cy_y           = 3.0,
           cz_x           = 4.0,
           cz_y           = 5.0,
           cz_z           = 6.0,
           cx_dot_x       = 7.0,
           cx_dot_y       = 8.0,
           cx_dot_z       = 9.0,
           cx_dot_x_dot   = 10.0,
           cy_dot_x       = 11.0,
           cy_dot_y       = 12.0,
           cy_dot_z       = 13.0,
           cy_dot_x_dot   = 14.0,
           cy_dot_y_dot   = 15.0,
           cz_dot_x       = 16.0,
           cz_dot_y       = 17.0,
           cz_dot_z       = 18.0,
           cz_dot_x_dot   = 19.0,
           cz_dot_y_dot   = 20.0,
           cz_dot_z_dot   = 21.0,
       )OmmCovarianceMatrix(String[], "ITRF", 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0)
julia> omm = OrbitMeanElementsMessage(omm; covariance_matrix = cov)OrbitMeanElementsMessage: ├─ Header │ Creation Date : 2025-12-30T23:36:37 │ Originator : 18 SPCS ├─ Metadata │ Object Name : AMAZONIA 1 │ Object ID : 2021-015A │ Center Name : EARTH │ Ref. Frame : TEME │ Time System : UTC │ Mean Element Theory : SGP4 └─ Data ├─ Mean Keplerian Elements │ Epoch : 2025-12-30T18:12:04.533984 │ Mean Motion : 14.40772474 rev/day │ Eccentricity : 0.0001124 │ Inclination : 98.3721° │ RA of Asc. Node : 75.0877° │ Arg. of Pericenter : 97.3772° │ Mean Anomaly : 262.7545° └─ Covariance Matrix Ref. Frame : ITRF CX_X : 1.0 km² CY_X : 2.0 km² CY_Y : 3.0 km² CZ_X : 4.0 km² CZ_Y : 5.0 km² CZ_Z : 6.0 km² CX_DOT_X : 7.0 km²/s CX_DOT_Y : 8.0 km²/s CX_DOT_Z : 9.0 km²/s CX_DOT_X_DOT : 10.0 km²/s² CY_DOT_X : 11.0 km²/s CY_DOT_Y : 12.0 km²/s CY_DOT_Z : 13.0 km²/s CY_DOT_X_DOT : 14.0 km²/s² CY_DOT_Y_DOT : 15.0 km²/s² CZ_DOT_X : 16.0 km²/s CZ_DOT_Y : 17.0 km²/s CZ_DOT_Z : 18.0 km²/s CZ_DOT_X_DOT : 19.0 km²/s² CZ_DOT_Y_DOT : 20.0 km²/s² CZ_DOT_Z_DOT : 21.0 km²/s²
julia> omm.data.covariance_matrix.cov_ref_frame"ITRF"
  • 1At least one of semi_major_axis or mean_motion must be provided.