Created
September 20, 2021 01:00
-
-
Save ckuethe/eb37e8a99d9f7fd5842d2e54212e62ad to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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