def get_observer_look(self, utc_time, lon, lat, alt): """Calculate observers look angle to a satellite. http://celestrak.com/columns/v02n02/ utc_time: Observation time (datetime object) lon: Longitude of observer position on ground in degrees east lat: Latitude of observer position on ground in degrees north alt: Altitude above sea-level (geoid) of observer position on ground in km Return: (Azimuth, Elevation) """ utc_time = dt2np(utc_time) (pos_x, pos_y, pos_z), (vel_x, vel_y, vel_z) = self.get_position(utc_time, normalize=False) (opos_x, opos_y, opos_z), (ovel_x, ovel_y, ovel_z) = \ astronomy.observer_position(utc_time, lon, lat, alt) lon = np.deg2rad(lon) lat = np.deg2rad(lat) theta = (astronomy.gmst(utc_time) + lon) % (2 * np.pi) rx = pos_x - opos_x ry = pos_y - opos_y rz = pos_z - opos_z sin_lat = np.sin(lat) cos_lat = np.cos(lat) sin_theta = np.sin(theta) cos_theta = np.cos(theta) top_s = sin_lat * cos_theta * rx + \ sin_lat * sin_theta * ry - cos_lat * rz top_e = -sin_theta * rx + cos_theta * ry top_z = cos_lat * cos_theta * rx + \ cos_lat * sin_theta * ry + sin_lat * rz az_ = np.arctan(-top_e / top_s) az_ = np.where(top_s > 0, az_ + np.pi, az_) az_ = np.where(az_ < 0, az_ + 2 * np.pi, az_) rg_ = np.sqrt(rx * rx + ry * ry + rz * rz) el_ = np.arcsin(top_z / rg_) return np.rad2deg(az_), np.rad2deg(el_)
def get_observer_look(self, utc_time, lon, lat, alt): """Calculate observers look angle to a satellite. http://celestrak.com/columns/v02n02/ utc_time: Observation time (datetime object) lon: Longitude of observer position on ground in degrees east lat: Latitude of observer position on ground in degrees north alt: Altitude above sea-level (geoid) of observer position on ground in km Return: (Azimuth, Elevation) """ utc_time = dt2np(utc_time) (pos_x, pos_y, pos_z), (vel_x, vel_y, vel_z) = self.get_position( utc_time, normalize=False) (opos_x, opos_y, opos_z), (ovel_x, ovel_y, ovel_z) = \ astronomy.observer_position(utc_time, lon, lat, alt) lon = np.deg2rad(lon) lat = np.deg2rad(lat) theta = (astronomy.gmst(utc_time) + lon) % (2 * np.pi) rx = pos_x - opos_x ry = pos_y - opos_y rz = pos_z - opos_z sin_lat = np.sin(lat) cos_lat = np.cos(lat) sin_theta = np.sin(theta) cos_theta = np.cos(theta) top_s = sin_lat * cos_theta * rx + \ sin_lat * sin_theta * ry - cos_lat * rz top_e = -sin_theta * rx + cos_theta * ry top_z = cos_lat * cos_theta * rx + \ cos_lat * sin_theta * ry + sin_lat * rz az_ = np.arctan(-top_e / top_s) az_ = np.where(top_s > 0, az_ + np.pi, az_) az_ = np.where(az_ < 0, az_ + 2 * np.pi, az_) rg_ = np.sqrt(rx * rx + ry * ry + rz * rz) el_ = np.arcsin(top_z / rg_) return np.rad2deg(az_), np.rad2deg(el_)
def propagate(self, utc_time): kep = {} # get the time delta in minutes # ts = astronomy._days(utc_time - self.t_0) * XMNPDA # print utc_time.shape # print self.t_0 utc_time = dt2np(utc_time) ts = (utc_time - self.t_0) / np.timedelta64(1, 'm') 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 crashed at time %s', utc_time) elif np.any(e < ECC_LIMIT_LOW): raise ValueError( 'Satellite modified eccentricity too 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 crashed 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 jdays2000(utc_time): """Get the days since year 2000. """ return _days(dt2np(utc_time) - np.datetime64('2000-01-01T12:00'))
def propagate(self, utc_time): kep = {} # get the time delta in minutes # ts = astronomy._days(utc_time - self.t_0) * XMNPDA # print utc_time.shape # print self.t_0 utc_time = dt2np(utc_time) ts = (utc_time - self.t_0) / np.timedelta64(1, 'm') 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 crashed 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 days_since_2000(utc_time): """Returns the days since year 2000. """ return days_from_dt(dt2np(utc_time) - np.datetime64('2000-01-01T12:00'))
def findtask(norad_id, observation_time, LAT, LONG, ALT): id = norad_id id = id.rjust(5) counter = 0 with open('3le.txt', 'r') as TLEs: for line in TLEs: if line[2:7] == id and counter == 0: # print(line) line1 = line counter = 1 elif line[2:7] == id and counter == 1: line2 = line # print(line) break R_site_ECI, V_site_ECI = observer_position(observation_time, LONG, LAT, ALT) sat = satellite.get_sat(line1, line2) R_sat_ECI, V_sat_ECI = sat.propagate(observation_time.year, observation_time.month, observation_time.day, observation_time.hour, observation_time.minute, (observation_time.second + observation_time.microsecond * 10 ** (-6))) delta_R = np.array([[R_sat_ECI[0] - R_site_ECI[0]], [R_sat_ECI[1] - R_site_ECI[1]], [R_sat_ECI[2] - R_site_ECI[2]]]) delta_V = np.array([[V_sat_ECI[0] - V_site_ECI[0]], [V_sat_ECI[1] - V_site_ECI[1]], [V_sat_ECI[2] - V_site_ECI[2]]]) utc_time = dt2np(observation_time) lon = np.deg2rad(LONG) lat = np.deg2rad(LAT) theta = (astronomy.gmst(utc_time) + lon) % (2 * np.pi) sin_lat = np.sin(lat) cos_lat = np.cos(lat) sin_theta = np.sin(theta) cos_theta = np.cos(theta) top_s = sin_lat * cos_theta * delta_R[0] + \ sin_lat * sin_theta * delta_R[1] - cos_lat * delta_R[2] top_e = -sin_theta * delta_R[0] + cos_theta * delta_R[1] top_z = cos_lat * cos_theta * delta_R[0] + \ cos_lat * sin_theta * delta_R[1] + sin_lat * delta_R[2] az_ = np.arctan(-top_e / top_s) az_ = np.where(top_s > 0, az_ + np.pi, az_) az_ = np.where(az_ < 0, az_ + 2 * np.pi, az_) rg_ = np.sqrt(top_s * top_s + top_e * top_e + top_z * top_z) el_ = np.arcsin(top_z / rg_) AZ = np.rad2deg(az_) EL = np.rad2deg(el_) mag_delta_R = math.sqrt(delta_R[0] ** 2 + delta_R[1] ** 2 + delta_R[2] ** 2) unit_delta_R = np.array([delta_R[0] / mag_delta_R, delta_R[1] / mag_delta_R, delta_R[2] / mag_delta_R]) V_orth_R_ECI = logical_cross(logical_cross(unit_delta_R, delta_V), unit_delta_R) total_look_angular_rate = (math.sqrt(V_orth_R_ECI[0] ** 2 + V_orth_R_ECI[1] ** 2 + V_orth_R_ECI[2] ** 2) / \ math.sqrt(delta_R[0] ** 2 + delta_R[1] ** 2 + delta_R[2] ** 2)) * (180.0 / math.pi) exposure_time = 0.955/total_look_angular_rate if exposure_time > 10: exposure_time = 10 return [AZ[0], EL[0], total_look_angular_rate, exposure_time]