def from_tle(cls, sate_id, source, date=None): """Returns approximate keplerian elements from TLE. The conversion between mean elements in the TEME reference frame to osculating elements in any standard reference frame is not well defined in literature (see Vallado 3rd edition, pp 236 to 240) """ # Get latest TLE, or the one corresponding to a specified date if date is None: date = datetime.datetime.utcnow() tle = source.get_tle(sate_id, date) # Retrieve TLE epoch and corresponding position epoch = twoline2rv(tle.lines[0], tle.lines[1], wgs84).epoch pos = TLEPredictor(sate_id, source).get_position(epoch) # Convert position from ECEF to ECI gmst = gstime_from_datetime(epoch) position_eci = coordinate_systems.ecef_to_eci(pos.position_ecef, gmst) velocity_eci = coordinate_systems.ecef_to_eci(pos.velocity_ecef, gmst) # Convert position to Keplerian osculating elements p, ecc, inc, raan, argp, ta = rv2coe(wgs84.mu, np.array(position_eci), np.array(velocity_eci)) sma = p / (1 - ecc**2) return cls(sma, ecc, degrees(inc), degrees(raan), degrees(argp), degrees(ta), epoch)
def test_convert_rv_to_coe(self): # Data from Vallado, example 2.5 position = np.array([6524.384, 6862.875, 6448.296]) velocity = np.array([4.901327, 5.533756, -1.976341]) expected_p = 11067.79 expected_ecc = 0.832853 expected_inc = radians(87.870) expected_raan = radians(227.89) expected_argp = radians(53.38) expected_ta = radians(92.335) p, ecc, inc, raan, argp, ta = rv2coe(MU_E, position, velocity) self.assertAlmostEqual(p, expected_p, places=0) self.assertAlmostEqual(ecc, expected_ecc, places=4) self.assertAlmostEqual(inc, expected_inc, places=4) self.assertAlmostEqual(raan, expected_raan, places=3) self.assertAlmostEqual(argp, expected_argp, places=3) self.assertAlmostEqual(ta, expected_ta, places=5)
def osculating_elements(self): """Osculating Keplerian orbital elements. Semimajor axis (km), eccentricity, inclination (deg), right ascension of the ascending node or RAAN (deg), argument of perigee (deg), true anomaly (deg). """ gmst = gstime_from_datetime(self.when_utc) position_eci = coordinate_systems.ecef_to_eci(self.position_ecef, gmst) velocity_eci = coordinate_systems.ecef_to_eci(self.velocity_ecef, gmst) # Convert position to Keplerian osculating elements p, ecc, inc, raan, argp, ta = rv2coe(MU_E, np.array(position_eci), np.array(velocity_eci)) # Transform to more familiar semimajor axis sma = p / (1 - ecc**2) return sma, ecc, degrees(inc), degrees(raan), degrees(argp), degrees( ta)
def osculating_elements(self): """Osculating Keplerian orbital elements. Semimajor axis (km), eccentricity, inclination (deg), right ascension of the ascending node or RAAN (deg), argument of perigee (deg), true anomaly (deg). """ gmst = gstime_from_datetime(self.when_utc) position_eci = coordinate_systems.ecef_to_eci(self.position_ecef, gmst) velocity_eci = coordinate_systems.ecef_to_eci(self.velocity_ecef, gmst) # Convert position to Keplerian osculating elements p, ecc, inc, raan, argp, ta = rv2coe(MU_E, np.array(position_eci), np.array(velocity_eci)) # Transform to more familiar semimajor axis sma = p / (1 - ecc**2) # NOTE: rv2coe already does % (2 * np.pi) # but under some circumstances this might require another pass, # see https://github.com/satellogic/orbit-predictor/pull/106#issuecomment-730177598 return sma, ecc, degrees(inc), degrees(raan), degrees( argp), degrees(ta) % 360