import lox_space as lox
import numpy as np
import numpy.testing as npt
INTELSAT_36_TLE = """INTELSAT 36
1 41747U 16053A 25026.69560333 -.00000008 00000+0 00000+0 0 9995
2 41747 0.0093 36.1594 0001240 298.1404 110.8362 1.00272270 30870
"""
def test_teme_to_icrf_roundtrip():
time = lox.UTC.from_iso("2025-01-27T00:00:00").to_scale("TAI")
state_icrf = lox.Cartesian(
time,
position=[-40755396.0, -10823119.0, 12227.0],
velocity=[789.0, -2971.0, 0.0],
origin=lox.Origin("Earth"),
frame=lox.Frame("ICRF"),
)
state_teme = state_icrf.to_frame(lox.Frame("TEME"))
state_icrf_back = state_teme.to_frame(lox.Frame("ICRF"))
npt.assert_allclose(
state_icrf.position(),
state_icrf_back.position(),
rtol=1e-10,
)
npt.assert_allclose(
state_icrf.velocity(),
state_icrf_back.velocity(),
rtol=1e-10,
atol=1e-12,
)
def test_teme_frame_small_rotation():
time = lox.UTC.from_iso("2025-01-27T00:00:00").to_scale("TAI")
state_icrf = lox.Cartesian(
time,
position=[42164000.0, 0.0, 0.0],
velocity=[0.0, 3075.0, 0.0],
origin=lox.Origin("Earth"),
frame=lox.Frame("ICRF"),
)
state_teme = state_icrf.to_frame(lox.Frame("TEME"))
pos_icrf = state_icrf.position()
pos_teme = state_teme.position()
npt.assert_allclose(np.linalg.norm(pos_icrf), np.linalg.norm(pos_teme), rtol=1e-12)
def test_icrf_teme_orekit():
time = lox.Time("TAI", 2026, 2, 21, 11, 46, 0.0)
state_icrf = lox.Cartesian(
time,
position=[6068279.27, -1692843.94, -2516619.18],
velocity=[-660.415582, 5495.938726, -5303.093233],
origin=lox.Origin("Earth"),
frame=lox.Frame("ICRF"),
)
p_exp = np.array([6084477.559317719, -1657212.1205153512, -2501177.0866586748])
v_exp = np.array([-678.9922540001335, 5492.253713516756, -5304.564805470879])
state_teme = state_icrf.to_frame(lox.Frame("TEME"))
npt.assert_allclose(state_teme.position(), p_exp, rtol=1e-8)
npt.assert_allclose(state_teme.velocity(), v_exp, rtol=1e-8)
def test_sgp4_icrf_against_skyfield():
from skyfield.api import load, EarthSatellite
tle_lines = INTELSAT_36_TLE.strip().splitlines()
ts = load.timescale()
skyfield_sat = EarthSatellite(tle_lines[1], tle_lines[2], tle_lines[0], ts)
t = ts.utc(2025, 1, 27, 0, 0, 0)
expected_pos = skyfield_sat.at(t).position.km
sgp4 = lox.SGP4(INTELSAT_36_TLE)
time = lox.UTC.from_iso("2025-01-27T00:00:00").to_scale("TAI")
state = sgp4.propagate(time).to_frame(lox.Frame("ICRF"))
pos_km = state.position() * 1e-3
npt.assert_allclose(pos_km, expected_pos, rtol=1e-4)
def test_teme_transformation_exists():
time = lox.UTC.from_iso("2025-01-27T00:00:00").to_scale("TAI")
state_icrf = lox.Cartesian(
time,
position=[42164000.0, 0.0, 0.0],
velocity=[0.0, 3075.0, 0.0],
origin=lox.Origin("Earth"),
frame=lox.Frame("ICRF"),
)
state_teme = state_icrf.to_frame(lox.Frame("TEME"))
assert state_teme is not None
state_icrf_back = state_teme.to_frame(lox.Frame("ICRF"))
assert state_icrf_back is not None