def propagate_from_RES(self, nprop=400): """ Initialise SPG4 propagation from a RES statevector, and compare to actually observed trajectory. """ # Extract one statevector for initialization rv = self.tab['SENTINEL-1A'] s1_res = self.resorb ix = 50 svec = s1_res[ix] state_ecef = np.r_[svec.POS, svec.VEL] # SORTS-style SGP4 propagator prp = SGP4(settings=dict(in_frame='ITRS', out_frame='ITRS')) ii = np.arange(nprop) pv_itrf = prp.propagate(10*ii, state_ecef, Time(svec.UTC)) pos = pv_itrf[:3].T vel = pv_itrf[3:].T rpos = s1_res[ix+ii].POS rvel = s1_res[ix+ii].VEL return pos, vel, rpos, rvel
def test_SGP4_propagate_B(self): B = 0.5 * self.params['C_D'] * self.params['A'] / self.params['m'] prop = SGP4(settings=self.settings) t = np.arange(0, 24 * 360, dtype=np.float) * 10.0 ecefs = prop.propagate(t, self.state0, self.epoch0, **self.params) ecefs_B = prop.propagate(t, self.state0, self.epoch0, B=B) assert ecefs.shape == ecefs_B.shape nt.assert_almost_equal(ecefs, ecefs_B)
def test_SGP4_propagate(self): prop = SGP4(settings=self.settings) t = np.arange(0, 24 * 360, dtype=np.float) * 10.0 ecefs = prop.propagate(t, self.state0, self.epoch0, **self.params) assert ecefs.shape == (6, t.size) assert isinstance(ecefs, np.ndarray) ecef = prop.propagate(0, self.state0, self.epoch0, **self.params) assert ecef.shape == (6, ) assert isinstance(ecef, np.ndarray) nt.assert_almost_equal(ecefs[:, 0], ecef)
def test_resorb_init(self): """ See whether SGP4 class in sorts/propagator/pysgp4.py initialised from RES orbit ITRF statevector values is consistent with the above. The propagator uses frames.TEME_to_ECEF to rotate the TEME results into ITRF. Hence, if this test succeeds, then TEME_to_ECEF is reasonably accurate when initialized from a ECEC (ITRS) cartesian statevector rotated to ECI (TEME) using astropy-derived rotation matrix (see above) """ # Extract one statevector for initialization rv = self.tab['SENTINEL-1A'] s1_res = self.resorb rv_ept = Time_from_rv(rv) # Find first statevector past TLE epoch ix = np.where(s1_res.UTC > rv_ept.datetime64)[0][0] svec = s1_res[ix] epoch0 = Time(svec.UTC, scale='utc') state_ecef = np.r_[svec.POS, svec.VEL] # SORTS-style SGP4 propagator prp = SGP4(settings=dict(in_frame='ITRS', out_frame='ITRS')) # Should be Cartesian ITRF coordinates in SI units posvel = prp.propagate(0., state_ecef, epoch0) ppos, pvel = posvel[:3], posvel[3:] assert vnorm2(svec.POS - ppos) < 800.0, 'Inaccurate position' assert vnorm2(svec.VEL - pvel) < 1.0, 'Inaccurate velocity' for ii in range(200): # dt between statevectors is 10.0 seconds svec = s1_res[ix+ii] posvel = prp.propagate(10.0*ii, state_ecef, epoch0) ppos, pvel = posvel[:3], posvel[3:] assert vnorm2(svec.POS - ppos) < 800.0, 'Inaccurate position' assert vnorm2(svec.VEL - pvel) < 1.0, 'Inaccurate velocity'
def test_tle_init(self): """ See whether SGP4 class in sorts/propagator/pysgp4.py initialised from TLE values is consistent with the above. The propagator uses Astropy to rotate the TEME results into ITRS. Hence, if this test succeeds, then the transformation is reasonably accurate when initialized from an ECI (TEME) cartesian statevector. """ # Extract one statevector for initialization rv = self.tab['SENTINEL-1A'] s1_res = self.resorb rv_ept = Time_from_rv(rv) # Find first statevector past TLE epoch ix = np.where(s1_res.UTC > rv_ept.datetime64)[0][0] svec = s1_res[ix] # Extract TEME statevector for initialization of SORTS propagation object pos, vel = _propagate(rv, rv_ept) state_eci = np.array(pos + vel) * 1e3 # SORTS-style SGP4 propagator prp = SGP4(settings=dict(in_frame='TEME', out_frame='ITRS')) # Should be Cartesian ITRF coordinates in SI units posvel = prp.propagate(Time(svec.UTC)-rv_ept, state_eci, rv_ept) ppos, pvel = posvel[:3], posvel[3:] assert vnorm2(svec.POS - ppos) < 800.0, 'Inaccurate position' assert vnorm2(svec.VEL - pvel) < 1.0, 'Inaccurate velocity' for ii in range(200): # dt between statevectors is 10.0 seconds svec = s1_res[ix+ii] posvel = prp.propagate(Time(svec.UTC)-rv_ept, state_eci, rv_ept) ppos, pvel = posvel[:3], posvel[3:] assert vnorm2(svec.POS - ppos) < 800.0, f'Inaccurate position: {ii}' assert vnorm2(svec.VEL - pvel) < 1.0, f'Inaccurate velocity: {ii}'
def test_get_mean_elements(self): prop = SGP4(settings=self.settings) l1 = '1 5U 58002B 20251.29381767 +.00000045 +00000-0 +68424-4 0 9990' l2 = '2 5 034.2510 336.1746 1845948 000.5952 359.6376 10.84867629214144' mean, B, epoch = prop.get_mean_elements(l1, l2) prop.settings['tle_input'] = True t = np.arange(0, 24 * 3600, dtype=np.float) states0 = prop.propagate(t, (l1, l2), epoch) prop.settings['tle_input'] = False states1 = prop.propagate(t, mean, epoch, B=B, SGP4_mean_elements=True) nt.assert_almost_equal(states0, states1, decimal=1)
def test_propagator_sgp4_mjd_invaraiance(self): #make sure that initial MJD does NOT matter when the frame is kept as TEME # Assemble all data that is required for SGP4 propagation # Epoch, mean orbital elements, ballistic coefficient prop = SGP4(settings=self.settings) t = np.arange(0, 24 * 360, dtype=np.float) * 10.0 ecefs = prop.propagate(t, self.state0, self.epoch0, **self.params) mjd = np.linspace(0, 40, num=33) for ind in range(len(mjd)): ecefs1 = prop.propagate( t, self.state0, self.epoch0 + TimeDelta(mjd[ind] * 24 * 3600.0, format='sec'), **self.params) assert ecefs.shape == ecefs1.shape nt.assert_almost_equal(ecefs, ecefs1, decimal=5)
''' import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import pyorb from astropy.utils import iers from astropy.time import Time iers.conf.auto_download = False from sorts.propagator import SGP4 from sorts import frames prop = SGP4() orb = pyorb.Orbit( M0=pyorb.M_earth, direct_update=True, auto_update=True, degrees=True, a=7000e3, e=0, i=69, omega=0, Omega=0, anom=0, ) t = np.linspace(0, 3600 * 24.0, num=5000) mjd0 = Time(53005.0, format='mjd', scale='utc')
''' Interpolation ====================== ''' import numpy as np import matplotlib.pyplot as plt from sorts.profiling import Profiler from sorts.propagator import SGP4 from sorts import interpolation p = Profiler() prop = SGP4( settings=dict(out_frame='TEME', ), profiler=p, ) state0 = np.array( [-7100297.113, -3897715.442, 18568433.707, 86.771, -3407.231, 2961.571]) t = np.arange(0.0, 360.0, 30.0) mjd0 = 53005 states = prop.propagate(t, state0, mjd0, A=1.0, C_R=1.0, C_D=1.0) interpolator = interpolation.Legendre8(states, t) t_f = np.arange(0.0, 360.0, 1.0) finer_states = interpolator.get_state(t_f) fig = plt.figure(figsize=(15, 15))
def test_init(self): prop = SGP4(settings=self.settings)
SGP4 propagator usage ====================================== ''' import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import pyorb from astropy.utils import iers from astropy.time import Time iers.conf.auto_download = False from sorts.propagator import SGP4 from sorts import frames prop = SGP4(settings=dict(out_frame='ITRS', ), ) print(prop) orb = pyorb.Orbit(M0=pyorb.M_earth, direct_update=True, auto_update=True, degrees=True, a=7000e3, e=0, i=69, omega=0, Omega=0, anom=0) print(orb)
============================ ''' import numpy as np import scipy.optimize as sio import matplotlib.pyplot as plt import pyorb from sorts.propagator import SGP4 #reproducibility np.random.seed(324245) prop = SGP4(settings=dict( in_frame='TEME', out_frame='TEME', ), ) std_pos = 1e3 #1km std noise on positions orb = pyorb.Orbit(M0=pyorb.M_earth, direct_update=True, auto_update=True, degrees=True, a=7200e3, e=0.05, i=75, omega=0, Omega=79, anom=72, type='mean') print(orb)
from sgp4.api import Satrec # Uncomment this to see what is actually recovered as mean elements from just one point # def print_args(func): # def pfunc(*args, **kwargs): # #print the arguments, except the "self" # print(args[1:]) # return func(*args, **kwargs) # return pfunc # #hook the sgp4init to print its input elements # Satrec.sgp4init = print_args(Satrec.sgp4init) prop = SGP4(settings=dict( out_frame='ITRS', tle_input=True, ), ) print(prop) l1 = '1 5U 58002B 20251.29381767 +.00000045 +00000-0 +68424-4 0 9990' l2 = '2 5 034.2510 336.1746 1845948 000.5952 359.6376 10.84867629214144' #JD epoch calculated from lines epoch = 2459099.79381767 t = np.linspace(0, 3600 * 24.0, num=5000) states_tle = prop.propagate(t, [l1, l2]) prop.set(