Source code for opengnc.interfaces.ccsds.opm

"""
CCSDS Orbit Parameter Message (OPM) implementation.
"""

import datetime
from typing import Dict, Optional, Union

import numpy as np


[docs] class OPM: """ Orbit Parameter Message (OPM) handler. Supports reading and writing CCSDS OPM files (KVN format). """ def __init__(self, data: Optional[Dict] = None) -> None: self.header = { "CCSDS_OPM_VERS": "2.0", "CREATION_DATE": datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S"), "ORIGINATOR": "OPENGNC", } self.metadata = { "OBJECT_NAME": "SPACECRAFT", "OBJECT_ID": "OPEN-GNC-01", "CENTER_NAME": "EARTH", "REF_FRAME": "EME2000", "TIME_SYSTEM": "UTC", } self.state: Dict[str, Union[float, str]] = { "EPOCH": "", "X": 0.0, "Y": 0.0, "Z": 0.0, "X_DOT": 0.0, "Y_DOT": 0.0, "Z_DOT": 0.0, } if data: self.state.update(data)
[docs] @classmethod def from_file(cls, filepath: str) -> "OPM": """Load OPM from a KVN file.""" opm = cls() with open(filepath) as f: for line in f: if "=" in line: key, val = line.split("=", 1) key = key.strip() val = val.split("#")[0].strip() # Remove comments # Handle units in brackets, e.g., "6678.14 [km]" clean_val = val.split("[")[0].strip() if key in opm.header: opm.header[key] = val elif key in opm.metadata: opm.metadata[key] = val elif key in opm.state: try: opm.state[key] = float(clean_val) except ValueError: opm.state[key] = val return opm
[docs] def write(self, filepath: str) -> None: """Write OPM to a KVN file.""" with open(filepath, "w") as f: f.write(f"CCSDS_OPM_VERS = {self.header['CCSDS_OPM_VERS']}\n") f.write(f"CREATION_DATE = {self.header['CREATION_DATE']}\n") f.write(f"ORIGINATOR = {self.header['ORIGINATOR']}\n\n") f.write("COMMENT Metadata\n") for k, v in self.metadata.items(): f.write(f"{k} = {v}\n") f.write("\nCOMMENT State Vector\n") f.write(f"EPOCH = {self.state['EPOCH']}\n") f.write(f"X = {self.state['X']:.6f} [km]\n") f.write(f"Y = {self.state['Y']:.6f} [km]\n") f.write(f"Z = {self.state['Z']:.6f} [km]\n") f.write(f"X_DOT = {self.state['X_DOT']:.9f} [km/s]\n") f.write(f"Y_DOT = {self.state['Y_DOT']:.9f} [km/s]\n") f.write(f"Z_DOT = {self.state['Z_DOT']:.9f} [km/s]\n")
[docs] def get_state_vector(self) -> np.ndarray: """Return state vector in SI units (m, m/s).""" return np.array( [ float(self.state["X"]) * 1000.0, float(self.state["Y"]) * 1000.0, float(self.state["Z"]) * 1000.0, float(self.state["X_DOT"]) * 1000.0, float(self.state["Y_DOT"]) * 1000.0, float(self.state["Z_DOT"]) * 1000.0, ] )