def get_orbit_number(self, utc_time, tbus_style=False): """Calculate orbit number at specified time. Optionally use TBUS-style orbit numbering (TLE orbit number + 1) """ utc_time = np.datetime64(utc_time) try: dt = astronomy._days(utc_time - self.orbit_elements.an_time) orbit_period = astronomy._days(self.orbit_elements.an_period) except AttributeError: pos_epoch, vel_epoch = self.get_position(self.tle.epoch, normalize=False) if np.abs(pos_epoch[2]) > 1 or not vel_epoch[2] > 0: # Epoch not at ascending node self.orbit_elements.an_time = self.get_last_an_time( self.tle.epoch) else: # Epoch at ascending node (z < 1 km) and positive v_z self.orbit_elements.an_time = self.tle.epoch self.orbit_elements.an_period = self.orbit_elements.an_time - \ self.get_last_an_time(self.orbit_elements.an_time - np.timedelta64(10, 'm')) dt = astronomy._days(utc_time - self.orbit_elements.an_time) orbit_period = astronomy._days(self.orbit_elements.an_period) orbit = int(self.tle.orbit + dt / orbit_period + self.tle.mean_motion_derivative * dt**2 + self.tle.mean_motion_sec_derivative * dt**3) if tbus_style: orbit += 1 return orbit
def get_orbit_number(self, utc_time, tbus_style=False): """Calculate orbit number at specified time. Optionally use TBUS-style orbit numbering (TLE orbit number + 1) """ dt = astronomy._days(utc_time - self.orbit_elements.an_time) orbit_period = astronomy._days(self.orbit_elements.an_period) orbit = int(self.tle.orbit + dt / orbit_period + self.tle.mean_motion_derivative * dt**2 + self.tle.mean_motion_sec_derivative * dt**3) if tbus_style: orbit += 1 return orbit
def test_aiaa(self): """Do the tests against AIAA test cases. """ path = os.path.dirname(os.path.abspath(__file__)) with open(os.path.join(path, "SGP4-VER.TLE")) as f__: test_line = f__.readline() while(test_line): if test_line.startswith("#"): test_name = test_line if test_line.startswith("1 "): line1 = test_line if test_line.startswith("2 "): line2 = test_line[:69] times = str.split(test_line[69:]) times = np.arange(float(times[0]), float(times[1]) + 1, float(times[2])) if test_name.startswith("# SL-14 DEB"): # FIXME: we have to handle decaying satellites! test_line = f__.readline() continue try: o = LineOrbital("unknown", line1, line2) except NotImplementedError: test_line = f__.readline() continue except ChecksumError: self.assertTrue(test_line.split()[1] in [ "33333", "33334", "33335"]) for delay in times: try: test_time = delay.astype( 'timedelta64[m]') + o.tle.epoch pos, vel = o.get_position(test_time, False) res = get_results( int(o.tle.satnumber), float(delay)) except NotImplementedError: # Skipping deep-space break # except ValueError, e: # from warnings import warn # warn(test_name + ' ' + str(e)) # break delta_pos = 5e-6 # km = 5 mm delta_vel = 5e-9 # km/s = 5 um/s delta_time = 1e-3 # 1 millisecond self.assertTrue(abs(res[0] - pos[0]) < delta_pos) self.assertTrue(abs(res[1] - pos[1]) < delta_pos) self.assertTrue(abs(res[2] - pos[2]) < delta_pos) self.assertTrue(abs(res[3] - vel[0]) < delta_vel) self.assertTrue(abs(res[4] - vel[1]) < delta_vel) self.assertTrue(abs(res[5] - vel[2]) < delta_vel) if res[6] is not None: dt = astronomy._days(res[6] - test_time) * 24 * 60 self.assertTrue(abs(dt) < delta_time) test_line = f__.readline()
def test_aiaa(self): """Do the tests against AIAA test cases. """ path = os.path.dirname(os.path.abspath(__file__)) with open(os.path.join(path, "SGP4-VER.TLE")) as f__: test_line = f__.readline() while (test_line): if test_line.startswith("#"): test_name = test_line if test_line.startswith("1 "): line1 = test_line if test_line.startswith("2 "): line2 = test_line[:69] times = str.split(test_line[69:]) times = np.arange(float(times[0]), float(times[1]) + 1, float(times[2])) if test_name.startswith("# SL-14 DEB"): # FIXME: we have to handle decaying satellites! test_line = f__.readline() continue try: o = LineOrbital("unknown", line1, line2) except NotImplementedError: test_line = f__.readline() continue except ChecksumError: self.assertTrue(test_line.split()[1] in ["33333", "33334", "33335"]) for delay in times: try: test_time = delay.astype( 'timedelta64[m]') + o.tle.epoch pos, vel = o.get_position(test_time, False) res = get_results(int(o.tle.satnumber), float(delay)) except NotImplementedError: # Skipping deep-space break # except ValueError, e: # from warnings import warn # warn(test_name + ' ' + str(e)) # break delta_pos = 5e-6 # km = 5 mm delta_vel = 5e-9 # km/s = 5 um/s delta_time = 1e-3 # 1 millisecond self.assertTrue(abs(res[0] - pos[0]) < delta_pos) self.assertTrue(abs(res[1] - pos[1]) < delta_pos) self.assertTrue(abs(res[2] - pos[2]) < delta_pos) self.assertTrue(abs(res[3] - vel[0]) < delta_vel) self.assertTrue(abs(res[4] - vel[1]) < delta_vel) self.assertTrue(abs(res[5] - vel[2]) < delta_vel) if res[6] is not None: dt = astronomy._days(res[6] - test_time) * 24 * 60 self.assertTrue(abs(dt) < delta_time) test_line = f__.readline()
def test_aiaa(self): """Do the tests against AIAA test cases. """ path = os.path.dirname(os.path.abspath(__file__)) with open(os.path.join(path, "SGP4-VER.TLE")) as f__: test_line = f__.readline() while (test_line): if test_line.startswith("#"): test_name = test_line if test_line.startswith("1 "): line1 = test_line if test_line.startswith("2 "): line2 = test_line[:69] times = str.split(test_line[69:]) times = np.arange(float(times[0]), float(times[1]) + 1, float(times[2])) try: o = LineOrbital("unknown", line1, line2) except Exception, e: # WARNING: skipping deep space computations from warnings import warn warn(test_name + ' ' + str(e)) test_line = f__.readline() continue for delay in times: try: test_time = timedelta(minutes=delay) + o.tle.epoch pos, vel = o.get_position(test_time, False) res = get_results(int(o.tle.satnumber), float(delay)) except (NotImplementedError, ValueError), e: # WARNING: TODO from warnings import warn warn(test_name + ' ' + str(e)) break delta_pos = 5e-6 # km = 5 mm delta_vel = 5e-9 # km/s = 5 um/s delta_time = 1e-3 # 1 milisecond self.assertTrue(abs(res[0] - pos[0]) < delta_pos) self.assertTrue(abs(res[1] - pos[1]) < delta_pos) self.assertTrue(abs(res[2] - pos[2]) < delta_pos) self.assertTrue(abs(res[3] - vel[0]) < delta_vel) self.assertTrue(abs(res[4] - vel[1]) < delta_vel) self.assertTrue(abs(res[5] - vel[2]) < delta_vel) if res[6] is not None: dt = astronomy._days(res[6] - test_time) * 24 * 60 self.assertTrue(abs(dt) < delta_time) test_line = f__.readline()
def propagate(self, utc_time): kep = {} ts = astronomy._days(utc_time - self.t_0) * XMNPDA em = self.eo xinc = self.xincl xmp = self.xmo + self.xmdot * ts xnode = self.xnodeo + ts * (self.xnodot + ts * self.xnodcf) omega = self.omegao + self.omgdot * ts if self.mode == SGDP4_ZERO_ECC: raise NotImplementedError('Mode SGDP4_ZERO_ECC not implemented') elif self.mode == SGDP4_NEAR_SIMP: raise NotImplementedError('Mode "Near-space, simplified equations"' ' not implemented') elif self.mode == SGDP4_NEAR_NORM: delm = self.xmcof * \ ((1.0 + self.eta * np.cos(xmp))**3 - self.delmo) temp0 = ts * self.omgcof + delm xmp += temp0 omega -= temp0 tempa = 1.0 - \ (ts * (self.c1 + ts * (self.d2 + ts * (self.d3 + ts * self.d4)))) tempe = self.bstar * \ (self.c4 * ts + self.c5 * (np.sin(xmp) - self.sinXMO)) templ = ts * ts * \ (self.t2cof + ts * (self.t3cof + ts * (self.t4cof + ts * self.t5cof))) a = self.aodp * tempa**2 e = em - tempe xl = xmp + omega + xnode + self.xnodp * templ else: raise NotImplementedError('Deep space calculations not supported') if np.any(a < 1): raise Exception('Satellite crased at time %s', utc_time) elif np.any(e < ECC_LIMIT_LOW): raise ValueError( 'Satellite modified eccentricity to low: %s < %e' % (str(e[e < ECC_LIMIT_LOW]), ECC_LIMIT_LOW)) e = np.where(e < ECC_EPS, ECC_EPS, e) e = np.where(e > ECC_LIMIT_HIGH, ECC_LIMIT_HIGH, e) beta2 = 1.0 - e**2 # Long period periodics sinOMG = np.sin(omega) cosOMG = np.cos(omega) temp0 = 1.0 / (a * beta2) axn = e * cosOMG ayn = e * sinOMG + temp0 * self.aycof xlt = xl + temp0 * self.xlcof * axn elsq = axn**2 + ayn**2 if np.any(elsq >= 1): raise Exception('e**2 >= 1 at %s', utc_time) kep['ecc'] = np.sqrt(elsq) epw = np.fmod(xlt - xnode, 2 * np.pi) # needs a copy in case of an array capu = np.array(epw) maxnr = kep['ecc'] for i in range(10): sinEPW = np.sin(epw) cosEPW = np.cos(epw) ecosE = axn * cosEPW + ayn * sinEPW esinE = axn * sinEPW - ayn * cosEPW f = capu - epw + esinE if np.all(np.abs(f) < NR_EPS): break df = 1.0 - ecosE # 1st order Newton-Raphson correction. nr = f / df # 2nd order Newton-Raphson correction. nr = np.where(np.logical_and(i == 0, np.abs(nr) > 1.25 * maxnr), np.sign(nr) * maxnr, f / (df + 0.5 * esinE * nr)) epw += nr # Short period preliminary quantities temp0 = 1.0 - elsq betal = np.sqrt(temp0) pl = a * temp0 r = a * (1.0 - ecosE) invR = 1.0 / r temp2 = a * invR temp3 = 1.0 / (1.0 + betal) cosu = temp2 * (cosEPW - axn + ayn * esinE * temp3) sinu = temp2 * (sinEPW - ayn - axn * esinE * temp3) u = np.arctan2(sinu, cosu) sin2u = 2.0 * sinu * cosu cos2u = 2.0 * cosu**2 - 1.0 temp0 = 1.0 / pl temp1 = CK2 * temp0 temp2 = temp1 * temp0 # Update for short term periodics to position terms. rk = r * (1.0 - 1.5 * temp2 * betal * self.x3thm1) + \ 0.5 * temp1 * self.x1mth2 * cos2u uk = u - 0.25 * temp2 * self.x7thm1 * sin2u xnodek = xnode + 1.5 * temp2 * self.cosIO * sin2u xinck = xinc + 1.5 * temp2 * self.cosIO * self.sinIO * cos2u if np.any(rk < 1): raise Exception('Satellite crased at time %s', utc_time) temp0 = np.sqrt(a) temp2 = XKE / (a * temp0) rdotk = ((XKE * temp0 * esinE * invR - temp2 * temp1 * self.x1mth2 * sin2u) * (XKMPER / AE * XMNPDA / 86400.0)) rfdotk = ((XKE * np.sqrt(pl) * invR + temp2 * temp1 * (self.x1mth2 * cos2u + 1.5 * self.x3thm1)) * (XKMPER / AE * XMNPDA / 86400.0)) kep['radius'] = rk * XKMPER / AE kep['theta'] = uk kep['eqinc'] = xinck kep['ascn'] = xnodek kep['argp'] = omega kep['smjaxs'] = a * XKMPER / AE kep['rdotk'] = rdotk kep['rfdotk'] = rfdotk return kep
def propagate(self, utc_time): kep = {} ts = astronomy._days(utc_time - self.t_0) * XMNPDA em = self.eo xinc = self.xincl xmp = self.xmo + self.xmdot * ts xnode = self.xnodeo + ts * (self.xnodot + ts * self.xnodcf) omega = self.omegao + self.omgdot * ts if self.mode == SGDP4_ZERO_ECC: raise NotImplementedError('Mode SGDP4_ZERO_ECC not implemented') elif self.mode == SGDP4_NEAR_SIMP: raise NotImplementedError('Mode "Near-space, simplified equations"' ' not implemented') elif self.mode == SGDP4_NEAR_NORM: delm = self.xmcof * ((1.0 + self.eta * np.cos(xmp))**3 - self.delmo) temp0 = ts * self.omgcof + delm xmp += temp0 omega -= temp0 tempa = 1.0 - (ts * (self.c1 + ts * (self.d2 + ts * (self.d3 + ts * self.d4)))) tempe = self.bstar * (self.c4 * ts + self.c5 * (np.sin(xmp) - self.sinXMO)) templ = ts * ts * (self.t2cof + ts * (self.t3cof + ts * (self.t4cof + ts * self.t5cof))) a = self.aodp * tempa**2 e = em - tempe xl = xmp + omega + xnode + self.xnodp * templ else: raise NotImplementedError('Deep space calculations not supported') if np.any(a < 1): raise Exception('Satellite crased at time %s', utc_time) elif np.any(e < ECC_LIMIT_LOW): raise ValueError('Satellite modified eccentricity to low: %e < %e' % (e, ECC_LIMIT_LOW)) e = np.where(e < ECC_EPS, ECC_EPS, e) e = np.where(e > ECC_LIMIT_HIGH, ECC_LIMIT_HIGH, e) beta2 = 1.0 - e**2 # Long period periodics sinOMG = np.sin(omega) cosOMG = np.cos(omega) temp0 = 1.0 / (a * beta2) axn = e * cosOMG ayn = e * sinOMG + temp0 * self.aycof xlt = xl + temp0 * self.xlcof * axn elsq = axn**2 + ayn**2 if np.any(elsq >= 1): raise Exception('e**2 >= 1 at %s', utc_time) kep['ecc'] = np.sqrt(elsq) epw = np.fmod(xlt - xnode, 2 * np.pi) # needs a copy in case of an array capu = np.array(epw) maxnr = kep['ecc'] for i in range(10): sinEPW = np.sin(epw) cosEPW = np.cos(epw) ecosE = axn * cosEPW + ayn * sinEPW esinE = axn * sinEPW - ayn * cosEPW f = capu - epw + esinE if np.all(np.abs(f) < NR_EPS): break df = 1.0 - ecosE # 1st order Newton-Raphson correction. nr = f / df # 2nd order Newton-Raphson correction. nr = np.where(np.logical_and(i == 0, np.abs(nr) > 1.25 * maxnr), np.sign(nr) * maxnr, f / (df + 0.5*esinE*nr)) epw += nr # Short period preliminary quantities temp0 = 1.0 - elsq betal = np.sqrt(temp0) pl = a * temp0 r = a * (1.0 - ecosE) invR = 1.0 / r temp2 = a * invR temp3 = 1.0 / (1.0 + betal) cosu = temp2 * (cosEPW - axn + ayn * esinE * temp3) sinu = temp2 * (sinEPW - ayn - axn * esinE * temp3) u = np.arctan2(sinu, cosu) sin2u = 2.0 * sinu * cosu cos2u = 2.0 * cosu**2 - 1.0 temp0 = 1.0 / pl temp1 = CK2 * temp0 temp2 = temp1 * temp0 # Update for short term periodics to position terms. rk = r * (1.0 - 1.5 * temp2 * betal * self.x3thm1) + 0.5 * temp1 * self.x1mth2 * cos2u uk = u - 0.25 * temp2 * self.x7thm1 * sin2u xnodek = xnode + 1.5 * temp2 * self.cosIO * sin2u xinck = xinc + 1.5 * temp2 * self.cosIO * self.sinIO * cos2u if np.any(rk < 1): raise Exception('Satellite crased at time %s', utc_time) temp0 = np.sqrt(a) temp2 = XKE / (a * temp0) rdotk = ((XKE * temp0 * esinE * invR -temp2 * temp1 * self.x1mth2 * sin2u) * (XKMPER / AE * XMNPDA / 86400.0)) rfdotk = ((XKE * np.sqrt(pl) * invR + temp2 * temp1 * (self.x1mth2 * cos2u + 1.5 * self.x3thm1)) * (XKMPER / AE * XMNPDA / 86400.0)) kep['radius'] = rk * XKMPER / AE kep['theta'] = uk kep['eqinc'] = xinck kep['ascn'] = xnodek kep['argp'] = omega kep['smjaxs'] = a * XKMPER / AE kep['rdotk'] = rdotk kep['rfdotk'] = rfdotk return kep