Skip to content

Instantly share code, notes, and snippets.

@ckuethe
Created September 20, 2021 01:00
Show Gist options
  • Save ckuethe/eb37e8a99d9f7fd5842d2e54212e62ad to your computer and use it in GitHub Desktop.
Save ckuethe/eb37e8a99d9f7fd5842d2e54212e62ad to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import sys
from collections import namedtuple
import datetime
import sgp4
from sgp4 import exporter
from sgp4.api import Satrec, WGS72
from sgp4.model import Satellite
from sgp4.io import _alpha5, _to_alpha5
# If you're running this against built but not installed code, eg.
# env PYTHONPATH=~/python-sgp4/build/lib.linux-x86_64-3.9/ python alpha5test.py
# print out where sgp4 and friends are loaded from.
print("SGP4 from", sgp4)
print("Exporter from", exporter)
# from https://celestrak.com/NORAD/elements/stations.txt
original_tle = (
"1 25544U 98067A 21245.66660925 .00003909 00000-0 80185-4 0 9991",
"2 25544 51.6444 319.5951 0003037 346.9445 145.3381 15.48588378300608",
)
# checked with the space-track encoder
test_pairs = [
(100000, "A0000"),
(123456, "C3456"),
(200000, "L0000"),
(263451, "S3451"),
(314159, "X4159"),
(339999, "Z9999"),
]
for t in test_pairs:
assert _to_alpha5(t[0]) == t[1]
assert int(_alpha5(t[1])) == t[0]
# basically Satrec.__repr__ ... I may do up a PR for this too.
Sgp4Params = namedtuple(
"Sgp4Params",
[
"whichconst",
"opsmode",
"satnum",
"epoch",
"bstar",
"ndot",
"nddot",
"eccentricity",
"argp_r",
"incl_r",
"mean_anom_r",
"no_kozai",
"raan_r",
],
)
# I have compelling evidence that JSpOC uses WGS72, and that it is the gravest
# of errors to use anything else. But just for fun, you can pass in different
# gravity parameters.
def dump_satrec(s: Satrec, whichconst=WGS72) -> Sgp4Params:
seconds_per_day = 86400
sgp4_time_start = datetime.datetime(1949, 12, 31, 0, 0, 0)
sr_year = s.epochyr + (1900 if s.epochyr > 58 else 2000)
sr_datetime = datetime.datetime(sr_year, 1, 1) + datetime.timedelta(seconds=s.epochdays * seconds_per_day)
delta_since_sgp4_time_start = sr_datetime - sgp4_time_start
parsed_epoch = (
delta_since_sgp4_time_start.days
+ (delta_since_sgp4_time_start.seconds + delta_since_sgp4_time_start.microseconds) / seconds_per_day
)
rv = Sgp4Params(
whichconst=whichconst,
opsmode=s.operationmode,
satnum=s.satnum,
epoch=parsed_epoch,
bstar=s.bstar,
ndot=s.ndot,
nddot=s.nddot,
eccentricity=s.ecco,
argp_r=s.argpo,
incl_r=s.inclo,
mean_anom_r=s.mo,
no_kozai=s.no_kozai,
raan_r=s.nodeo,
)
return rv
# And here come the test cases
print(f"TLE round-trip", end="")
constructed = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
constructed_tle = exporter.export_tle(constructed)
assert constructed_tle == original_tle
print(" - OK")
print(f"int classic range", end="")
test_sat = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
target_satnum = 12345
test_sat.satnum = target_satnum
test_sat_args = dump_satrec(test_sat)
modified_tle = exporter.export_tle(test_sat)
modified_obj = Satrec.twoline2rv(modified_tle[0], modified_tle[1], WGS72)
assert modified_obj.satnum == target_satnum
print(" - OK")
print(f"str classic range", end="")
test_sat = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
target_satnum = "12345"
test_sat.satnum = target_satnum
test_sat_args = dump_satrec(test_sat)
modified_tle = exporter.export_tle(test_sat)
modified_obj = Satrec.twoline2rv(modified_tle[0], modified_tle[1], WGS72)
assert modified_obj.satnum == int(target_satnum)
print(" - OK")
print(f"int extended range", end="")
test_sat = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
target_satnum = 263451
test_sat.satnum = target_satnum
test_sat_args = dump_satrec(test_sat)
modified_tle = exporter.export_tle(test_sat)
modified_obj = Satrec.twoline2rv(modified_tle[0], modified_tle[1], WGS72)
assert str(modified_obj.satnum) == str(target_satnum)
print(" - OK")
print(f"str extended range", end="")
test_sat = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
target_satnum = "123456"
test_sat.satnum = target_satnum
test_sat_args = dump_satrec(test_sat)
modified_tle = exporter.export_tle(test_sat)
modified_obj = Satrec.twoline2rv(modified_tle[0], modified_tle[1], WGS72)
assert str(modified_obj.satnum) == target_satnum
print(" - OK")
print(f"Reject int out of range", end="")
test_sat = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
target_satnum = 1234500
try:
test_sat.satnum = target_satnum
assert "We should not get here" == "True"
print("Fail")
except ValueError as e:
print(" - OK")
except Exception as e:
print("FAIL", e)
print(f"Reject str out of range", end="")
test_sat = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
target_satnum = "1234560"
try:
test_sat.satnum = target_satnum
assert "We should not get here" == "True"
print("Fail")
except ValueError as e:
print(" - OK")
except Exception as e:
print("FAIL", e)
print(f"Set satnum from Alpha5", end="")
test_sat = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
target_satnum = "Z3456"
test_sat.satnum = target_satnum
test_sat_args = dump_satrec(test_sat)
modified_tle = exporter.export_tle(test_sat)
print(" - OK")
print(f"Reject invalid Alpha5 (1)", end="")
test_sat = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
target_satnum = "WALDO"
try:
test_sat.satnum = target_satnum
assert "We should not get here" == "True"
print("Fail")
except ValueError as e:
print(" - OK")
except Exception as e:
print("FAIL", e)
print(f"Reject invalid Alpha5 (2)", end="")
test_sat = Satrec.twoline2rv(original_tle[0], original_tle[1], WGS72)
try:
target_satnum = "O0000"
test_sat.satnum = target_satnum
assert "We should not get here" == "True"
print("Fail")
except ValueError as e:
print(" - OK")
except Exception as e:
print("FAIL", e)
print(f"Round-trip ALPHA5", end="")
target_satnum = "A1234"
test_sat.satnum = target_satnum
modified_tle = exporter.export_tle(test_sat)
assert target_satnum in modified_tle[0] and target_satnum in modified_tle[1]
modified_obj = Satrec.twoline2rv(modified_tle[0], modified_tle[1], WGS72)
final_tle = exporter.export_tle(modified_obj)
assert test_sat.satnum == modified_obj.satnum
assert modified_tle == final_tle
print(" - OK")
print(f"Smallest ALPHA5", end="")
modified_tle = (original_tle[0][:-1], original_tle[1][:-1])
test_sat = Satrec.twoline2rv(modified_tle[0], modified_tle[1], WGS72)
test_sat.satnum = 100000
test_tle = exporter.export_tle(test_sat)
assert test_tle[0].startswith("1 A0000U") and test_tle[1].startswith("2 A0000")
print(" - OK")
print(f"Largest ALPHA5", end="")
modified_tle = (original_tle[0][:-1], original_tle[1][:-1])
test_sat = Satrec.twoline2rv(modified_tle[0], modified_tle[1], WGS72)
test_sat.satnum = 339999
test_tle = exporter.export_tle(test_sat)
assert test_tle[0].startswith("1 Z9999U") and test_tle[1].startswith("2 Z9999")
print(" - OK")
print("All tests passed")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment