Skip to content

adding support for the OMM format (JSON/XML/KVN/CSV) - #26

Merged
Sceki merged 1 commit into
esa:masterfrom
Sceki:omm-format
Aug 7, 2026
Merged

adding support for the OMM format (JSON/XML/KVN/CSV)#26
Sceki merged 1 commit into
esa:masterfrom
Sceki:omm-format

Conversation

@Sceki

@Sceki Sceki commented Aug 7, 2026

Copy link
Copy Markdown
Member

This PR adds support for the CCSDS OMM (Orbit Mean-Elements Message, 502.0-B-3), the format Space-Track
distributes alongside the TLEs. The TLE support is untouched: this is purely additive for the user.

New dsgp4.omm module:

  • reads and writes all four serializations of the standard (JSON, XML, KVN, CSV), with format
    auto-detection from content and file extension: omm.load, omm.loads, omm.dumps,
    omm.parse_json/parse_xml/parse_kvn/parse_csv;
  • dsgp4.omm.OMM objects can be built from a dictionary of OMM fields (e.g. what the Space-Track
    API returns), from a string containing a single message, or from the usual dictionary of elements;
  • TLE.to_omm() and OMM.to_tle() convert between the two formats.

OMM subclasses dsgp4.tle.TLE and fills the very same _data dictionary, so an OMM can be used
everywhere a TLE is expected without touching a single line of the propagator: initialize_tle,
propagate, propagate_batch, newton_method, plot_tles and mldsgp4 all work as they are
(there are tests for this). What an OMM does not inherit is the two fixed-width lines: objects
whose catalog number is above 339999 cannot be encoded even with Alpha-5, so they only exist as
OMMs, and to_tle() raises the ValueError that #25 already pointed at.

Three small things also had to change in the TLE side, all needed to let the OMM subclass reuse the machinery:

  • the block that derives the Julian dates, the semi-major axis and the epoch was duplicated
    verbatim in load_from_lines and load_from_data: it is now tle.add_derived_quantities,
    which the OMM loader uses too (behaviour is identical, the TLE tests are untouched);
  • copy, set_time and update now build an object of type(self) instead of hard-coding
    TLE, so they round-trip for the classes that inherit from it (same reason for the two
    type(...) in newton_method);
  • TLE.__getattr__ raises a proper AttributeError for unknown attributes, instead of the
    confusing 'super' object has no attribute '__getattr__' it raised before.

Tests wise:

  • The OMM and the TLE of the same object give bit-identical _bstar, _ndot, _nddot,
    _ecco, _argpo, _inclo, _mo, _no_kozai, _nodeo, _jdsatepoch, _jdsatepochF, and
    therefore identical states.
  • Cross-checked against the OMM support of python-sgp4: the elements are exactly equal, and the
    states agree to ~5e-5 mm once the gravity model matches (their omm.initialize seems to use WGS-72).
  • 15 new tests in tests/test_omm.py, covering the four formats, the
    TLE/OMM conversions, files, the >339999 catalog numbers, the optional and empty fields, and the
    error paths. The whole suite is 58 passing tests.

New doc/notebooks/omm_object.ipynb tutorial (with example_omm.json), a quick-start section in
the README, and the new entries in api.rst, tutorials.rst and capabilities.ipynb.

Other notes:

  • Non-standard fields that Space-Track adds to its OMMs (e.g. SEMIMAJOR_AXIS, DECAY_DATE,
    TLE_LINE1) are kept in omm._fields as they were read, but they are not regenerated when the
    fields are rebuilt from the elements (i.e. after copy, set_time or update).
  • Only the flat Space-Track JSON is read, not the nested NDM/JSON form; and only SGP4-like
    MEAN_ELEMENT_THEORY values are accepted, since dSGP4 cannot propagate (for now :)) e.g. SGP4-XP elements.

@Sceki
Sceki merged commit 8ef7820 into esa:master Aug 7, 2026
10 checks passed
@Sceki
Sceki deleted the omm-format branch August 7, 2026 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant