def test_teme_loopback(): from_coo = TEME(1 * u.AU, 2 * u.AU, 3 * u.AU, obstime='2001-01-01') to_frame = TEME(obstime='2001-06-30') explicit_coo = from_coo.transform_to(ICRS()).transform_to(to_frame) implicit_coo = from_coo.transform_to(to_frame) # Confirm that the explicit transformation changes the coordinate assert not allclose( explicit_coo.cartesian.xyz, from_coo.cartesian.xyz, rtol=1e-10) # Confirm that the loopback matches the explicit transformation assert_allclose(explicit_coo.cartesian.xyz, implicit_coo.cartesian.xyz, rtol=1e-10)
def convert(t, states, in_frame, out_frame, logger=None, profiler=None, **kwargs): '''Perform predefined coordinate transformations. Always returns a copy of the array. ''' if logger is not None: logger.info( f'frames:convert: in_frame={in_frame}, out_frame={out_frame}') if profiler is not None: profiler.start(f'frames:convert:{in_frame}->{out_frame}') in_frame = in_frame.upper() out_frame = out_frame.upper() if in_frame == out_frame: return states.copy() if in_frame == 'TEME': astropy_states = _convert_to_astropy(states, TEME, obstime=t) elif in_frame in ['ITRS', 'ITRF']: #Reference System VS Reference Frame astropy_states = _convert_to_astropy(states, ITRS, obstime=t) elif in_frame in ['ICRS', 'ICRF']: astropy_states = _convert_to_astropy(states, ICRS) elif in_frame in ['GCRS', 'GCRF']: astropy_states = _convert_to_astropy(states, GCRS, obstime=t) else: raise ValueError( f'In frame "{in_frame}" not recognized, please perform manual transformation' ) if out_frame in ['ITRS', 'ITRF']: out_states = astropy_states.transform_to(ITRS(obstime=t)) elif out_frame == 'TEME': out_states = astropy_states.transform_to(TEME(obstime=t)) elif out_frame in ['ICRS', 'ICRF']: out_states = astropy_states.transform_to(ICRS()) elif out_frame in ['GCRS', 'GCRF']: out_states = astropy_states.transform_to(GCRS(obstime=t)) else: raise ValueError( f'Out frame "{out_frame}" not recognized, please perform manual transformation' ) rets = states.copy() rets[:3, ...] = out_states.cartesian.xyz.to(units.m).value rets[3:, ...] = out_states.velocity.d_xyz.to(units.m / units.s).value if logger is not None: logger.info('frames:convert:completed') if profiler is not None: profiler.stop(f'frames:convert:{in_frame}->{out_frame}') return rets
def gen_trajectory(self, tle, interval, **kwargs): """ Generates the trajectory (time and coordinate information) for the given interval with the internal stepsize. Parameters ---------- tle : TLE Two-Line-Element initial orbit information (TEME mean orbital elements) interval : TimeInterval Time interval for which the ephemeris will be generated kwargs No keywords defined Returns ------- Trajectory The output trajectory (in `GCRS`) """ # ****** Generate the pos, vel vectors for each time instant ****** # generate the output timelist time_list = self._generate_time_list(interval) # Run the propagation and init pos and vel vectors in TEME e, r_list, v_list = tle.satrec.sgp4_array(time_list.jd1, time_list.jd2) # Load the time, pos, vel info into astropy objects (shallow copied) rv_list_teme = CartesianRepresentation( r_list, unit=u.km, xyz_axis=1 ).with_differentials(CartesianDifferential(v_list, unit=u.km / u.s, xyz_axis=1)) rv_list_gcrs = TEME( rv_list_teme, obstime=time_list, representation_type="cartesian", differential_type="cartesian", ).transform_to(GCRS(obstime=time_list)) # trajectory in astropy traj_astropy = SkyCoord( rv_list_gcrs, obstime=time_list, frame="gcrs", representation_type="cartesian", differential_type="cartesian", ) # Init trajectory in Trajectory object trajectory = Trajectory(traj_astropy) return trajectory
def el2rv(inc, raan, ecc, argp, mean_anomaly, mean_motion, epoch): """ Converts mean orbital elements to state vector """ time_tle = epoch.jd - 2433281.5 sat = Satrec() sat.sgp4init( WGS84, "i", 0, time_tle, 0.0, 0.0, 0.0, ecc, argp, inc, mean_anomaly, mean_motion, raan, ) errorCode, rTEME, vTEME = sat.sgp4(epoch.jd1, epoch.jd2) if errorCode != 0: raise RuntimeError(SGP4_ERRORS[errorCode]) pTEME = coord.CartesianRepresentation(rTEME * u.km) vTEME = coord.CartesianDifferential(vTEME * u.km / u.s) svTEME = TEME(pTEME.with_differentials(vTEME), obstime=epoch) svITRS = svTEME.transform_to(coord.ITRS(obstime=epoch)) orb = Orbit.from_coords(Earth, svITRS) return orb.r, orb.v
def test_itrs_to_teme(): """Check the coordinate transform accuracy.""" # test_frame = "TEME" allowable_pos_diff = 300 * u.mm allowable_vel_diff = 0.23 * u.mm / u.s rv_teme = rv_itrs_true.transform_to(TEME(obstime=time)) r_diff = pos_err(rv_teme, rv_teme_true) v_diff = vel_err(rv_teme, rv_teme_true) # print(f"r {rv_teme.name} diff : {r_diff}") # print(f"v {rv_teme.name} diff : {v_diff}") assert r_diff < allowable_pos_diff assert v_diff < allowable_vel_diff
def test_teme_itrf(): """ Test case transform from TEME to ITRF. Test case derives from example on appendix C of Vallado, Crawford, Hujsak & Kelso (2006). See https://celestrak.com/publications/AIAA/2006-6753/AIAA-2006-6753-Rev2.pdf """ v_itrf = CartesianDifferential(-3.225636520, -2.872451450, 5.531924446, unit=u.km / u.s) p_itrf = CartesianRepresentation(-1033.479383, 7901.2952740, 6380.35659580, unit=u.km, differentials={'s': v_itrf}) t = Time("2004-04-06T07:51:28.386") teme = ITRS(p_itrf, obstime=t).transform_to(TEME(obstime=t)) v_teme = CartesianDifferential(-4.746131487, 0.785818041, 5.531931288, unit=u.km / u.s) p_teme = CartesianRepresentation(5094.18016210, 6127.64465050, 6380.34453270, unit=u.km, differentials={'s': v_teme}) assert_allclose(teme.cartesian.without_differentials().xyz, p_teme.without_differentials().xyz, atol=30 * u.cm) assert_allclose(teme.cartesian.differentials['s'].d_xyz, p_teme.differentials['s'].d_xyz, atol=1.0 * u.cm / u.s) # test round trip itrf = teme.transform_to(ITRS(obstime=t)) assert_allclose(itrf.cartesian.without_differentials().xyz, p_itrf.without_differentials().xyz, atol=100 * u.cm) assert_allclose(itrf.cartesian.differentials['s'].d_xyz, p_itrf.differentials['s'].d_xyz, atol=1 * u.cm / u.s)
def test_itrs_roundtrip(): """Check whether transforming to a coord and then transforming back yields the same output.""" # test_frame = "ITRS" allowable_pos_diff = 1.5e-6 * u.mm allowable_vel_diff = 2.8e-6 * u.mm / u.s rv_teme = rv_itrs_true.transform_to(TEME(obstime=time)) rv_itrs_from_teme = rv_teme.transform_to(ITRS(obstime=time)) r_diff = pos_err(rv_itrs_from_teme, rv_itrs_true) v_diff = vel_err(rv_itrs_from_teme, rv_itrs_true) # print(f"r {rv_itrs_true.name} diff : {r_diff}") # print(f"v {rv_itrs_true.name} diff : {v_diff}") assert r_diff < allowable_pos_diff assert v_diff < allowable_vel_diff
def propagate(tle, time): """ Computes the coordinates at the target `time` using the source `TLE` mean orbital elements. Parameters ---------- tle : TLE Mean orbital elements (Two-Line-Element) time : Time Target time for propagation Returns ------- coords : SkyCoord Coordinates at target time (in `GCRS`) Raises ------ SGP4GeneralError Errors in SGP4 propagation SGP4SatDecayedError Satellite coordinates at required coordinates are below decay altitude. """ # compute coords at time e, r, v = tle.satrec.sgp4(time.utc.jd1, time.utc.jd2) # check error code SGP4Propagator.__handle_err_code(e) v_teme = CartesianDifferential(np.asarray(v), unit=u.km / u.s) r_teme = CartesianRepresentation(np.asarray(r), unit=u.km) rv_gcrs = TEME(r_teme.with_differentials(v_teme), obstime=time).transform_to( GCRS(obstime=time) ) return SkyCoord( rv_gcrs, representation_type="cartesian", differential_type="cartesian" )
def test_teme_to_tirs_no_vel(): """Check whether coord transform without velocity is possible.""" rv_teme_no_vel = TEME(r_teme_true, obstime=time, representation_type="cartesian") rv_teme_no_vel.transform_to(TIRS(obstime=time))
[-1033.47503120, 7901.30558560, 6380.34453270], unit=u.km) rv_tirs_true = TIRS( r_tirs_true.with_differentials(v_tirs_true), obstime=time, representation_type="cartesian", differential_type="cartesian", ) # Vallado IAU 2000 - Table 3-6 TEME v_teme_true = CartesianDifferential( [-4.7461314870, 0.7858180410, 5.5319312880], unit=u.km / u.s) r_teme_true = CartesianRepresentation( [5094.18016210, 6127.64465950, 6380.34453270], unit=u.km) rv_teme_true = TEME( r_teme_true.with_differentials(v_teme_true), obstime=time, representation_type="cartesian", differential_type="cartesian", ) def _init_orbit_mars(): """Initialises the test orbit in a Martian orbit.""" obstime = Time("2020-01-10T11:30:00.0003", scale="tdb") v_mars = CartesianDifferential( [3.057934230169251e-01, -3.068219328642159e00, -1.397389382391015e00], unit=u.km / u.s, ) r_mars = CartesianRepresentation( [1.786125452441044e03, -1.191541086863880e03, 3.003639539248147e03], unit=u.km)
0.0, 0.0, ecc, argp, inc, m_ano, m_mot, raan, ) errorCode, rTEME, vTEME = sat.sgp4(epoch.jd1, epoch.jd2) if errorCode != 0: raise RuntimeError(SGP4_ERRORS[errorCode]) # Convert state vector from TEME (True Equator Mean Equinox) to ITRS pTEME = coord.CartesianRepresentation(rTEME * u.km) vTEME = coord.CartesianDifferential(vTEME * u.km / u.s) svTEME = TEME(pTEME.with_differentials(vTEME), obstime=iss.epoch) svITRS = svTEME.transform_to(coord.ITRS(obstime=iss.epoch)) sv = Orbit.from_coords(Earth, svITRS) # Display results print("State vector [rv2el]") print(f" r = {sv.r}") print(f" v = {sv.v}") print() print("State vector differences [poliastro - rv2el]") print(f" dr = {iss.r - sv.r}") print(f" dv = {iss.v - sv.v}") print()
t = lines[6] url = re.findall(url_regex, lines[8])[0][0] satellite = Satrec.twoline2rv(s, t) # Epoch March 26th, 2020, at 21:52:56 t = Time('2020-03-26T21:52:56.0', format='isot', scale='utc') error_code, teme_p, teme_v = satellite.sgp4(t.jd1, t.jd2) # in km and km/s if error_code != 0: raise RuntimeError(SGP4_ERRORS[error_code]) # Convert SGP4 TEME to Astropy native TEME teme_p = CartesianRepresentation(teme_p*u.km) teme_v = CartesianDifferential(teme_v*u.km/u.s) teme = TEME(teme_p.with_differentials(teme_v), obstime=t) ''' itrs = teme.transform_to(ITRS(obstime=t)) location = itrs.earth_location print(location.geodetic) ''' # Lat/Lon/Alt of the Washington Monumnet monumentLat = 38.889484 monumentLon = -77.035278 monumnetAlt = 169 # meters # get the locations into similar coordinate system objects #satellilteEarthLocation = ?.from_geocentric(xSat,ySat,zSat) monumentEarthLocation = EarthLocation.from_geodetic(monumentLon,monumentLat,monumnetAlt)