Files
2026-03-31 09:44:27 +02:00

134 lines
4.7 KiB
Python

"""Export orbit data to a Two-Line-Element representation.
Contributed by Egemen Imre https://github.com/egemenimre
"""
from math import pi
from sgp4.io import compute_checksum
from sgp4.conveniences import sat_epoch_datetime
# Define constants
_deg2rad = pi / 180.0 # 0.0174532925199433
_xpdotp = 1440.0 / (2.0 * pi) # 229.1831180523293
def export_tle(satrec):
"""Generate the TLE for a given `Satrec` object; returns two strings."""
# --------------------- Start generating line 1 ---------------------
# Build the list by appending successive items
pieces = ['1 ', satrec.satnum_str]
append = pieces.append
# Add classification code (use "U" if empty)
classification = getattr(satrec, 'classification', 'U')
append(classification.strip() or 'U')
append(' ')
# Add int'l designator and pad to 8 chars
intldesg = getattr(satrec, 'intldesg', '')
append('{0:8} '.format(intldesg))
# Add epoch year and days in YYDDD.DDDDDDDD format
epochyr = satrec.epochyr
# Undo non-standard 4-digit year for old satrec objects
epochyr %= 100
append(str(epochyr).zfill(2) + "{:012.8f}".format(satrec.epochdays) + " ")
# Add First Time Derivative of the Mean Motion (don't use "+")
append("{0: 8.8f}".format(satrec.ndot * (_xpdotp * 1440.0)).replace("0", "", 1) + " ")
# Add Second Time Derivative of Mean Motion
append(_abbreviate_rate(satrec.nddot * _xpdotp * 20736000.0, '-0'))
# Add BSTAR
append(_abbreviate_rate(satrec.bstar * 10.0, '+0'))
# Add Ephemeris Type and Element Number
ephtype = getattr(satrec, 'ephtype', 0)
elnum = getattr(satrec, 'elnum', 0)
append('{0} {1:4}'.format(ephtype, elnum))
# Join all the parts and add the Checksum
line1 = ''.join(pieces)
line1 += str(compute_checksum(line1))
# --------------------- Start generating line 2 ---------------------
# Reset the str array
pieces = ['2 ', satrec.satnum_str]
append = pieces.append
# Add the inclination (deg)
if not 0 <= satrec.inclo <= pi:
raise ValueError("Inclination must be between 0 and pi, got %r", satrec.inclo)
append(' {0:8.4f} '.format(satrec.inclo / _deg2rad))
# Add the RAAN (deg)
if not 0 <= satrec.nodeo <= 2 * pi:
raise ValueError("RAAN must be between 0 and 2 pi, got %r", satrec.nodeo)
append("{0:8.4f}".format(satrec.nodeo / _deg2rad).rjust(8, " ") + " ")
# Add the eccentricity (delete the leading zero an decimal point)
append("{0:8.7f}".format(satrec.ecco).replace("0.", "") + " ")
# Add the Argument of Perigee (deg)
if not 0 <= satrec.argpo <= 2 * pi:
raise ValueError("Argument of Perigee must be between 0 and 2 pi, got %r", satrec.argpo)
append("{0:8.4f}".format(satrec.argpo / _deg2rad).rjust(8, " ") + " ")
# Add the Mean Anomaly (deg)
if not 0 <= satrec.mo <= 2 * pi:
raise ValueError("Mean Anomaly must be between 0 and 2 pi, got %r", satrec.mo)
append("{0:8.4f}".format(satrec.mo / _deg2rad).rjust(8, " ") + " ")
# Add the Mean Motion (revs/day)
append("{0:11.8f}".format(satrec.no_kozai * _xpdotp).rjust(8, " "))
# Add the rev number at epoch
append(str(satrec.revnum).rjust(5))
# Join all the parts and add the Checksum
line2 = ''.join(pieces)
line2 += str(compute_checksum(line2))
return line1, line2
def _abbreviate_rate(value, zero_exponent_string):
return (
'{0: 4.4e} '.format(value)
.replace('.', '')
.replace('e+00', zero_exponent_string)
.replace('e-0', '-')
.replace('e+0', '+')
)
def export_omm(satrec, object_name):
launch_year = int(satrec.intldesg[:2])
launch_year += 1900 + (launch_year < 57) * 100
object_id = '{0}-{1}'.format(launch_year, satrec.intldesg[2:])
return {
"OBJECT_NAME": object_name,
"OBJECT_ID": object_id,
"CENTER_NAME": "EARTH",
"REF_FRAME": "TEME",
"TIME_SYSTEM": "UTC",
"MEAN_ELEMENT_THEORY": "SGP4",
"EPOCH": sat_epoch_datetime(satrec).strftime('%Y-%m-%dT%H:%M:%S.%f'),
"MEAN_MOTION": satrec.no_kozai * _xpdotp,
"ECCENTRICITY": satrec.ecco,
"INCLINATION": satrec.inclo / _deg2rad,
"RA_OF_ASC_NODE": satrec.nodeo / _deg2rad,
"ARG_OF_PERICENTER": satrec.argpo / _deg2rad,
"MEAN_ANOMALY": satrec.mo / _deg2rad,
"EPHEMERIS_TYPE": satrec.ephtype,
"CLASSIFICATION_TYPE": satrec.classification,
"NORAD_CAT_ID": satrec.satnum,
"ELEMENT_SET_NO": satrec.elnum,
"REV_AT_EPOCH": satrec.revnum,
"BSTAR": satrec.bstar,
"MEAN_MOTION_DOT": satrec.ndot * (_xpdotp * 1440.0),
"MEAN_MOTION_DDOT": satrec.nddot * (_xpdotp * 1440.0 * 1440),
}