def get_lonlatalt(self, utc_time): """Calculate sublon, sublat and altitude of satellite. http://celestrak.com/columns/v02n03/ """ (pos_x, pos_y, pos_z), (vel_x, vel_y, vel_z) = self.get_position( utc_time, normalize=True) lon = ((np.arctan2(pos_y * XKMPER, pos_x * XKMPER) - astronomy.gmst(utc_time)) % (2 * np.pi)) lon = np.where(lon > np.pi, lon - np.pi * 2, lon) lon = np.where(lon <= -np.pi, lon + np.pi * 2, lon) r = np.sqrt(pos_x ** 2 + pos_y ** 2) lat = np.arctan2(pos_z, r) e2 = F * (2 - F) while True: lat2 = lat c = 1 / (np.sqrt(1 - e2 * (np.sin(lat2) ** 2))) lat = np.arctan2(pos_z + c * e2 * np.sin(lat2), r) if np.all(abs(lat - lat2) < 1e-10): break alt = r / np.cos(lat) - c alt *= A return np.rad2deg(lon), np.rad2deg(lat), alt
def __init__(self, tle): self.epoch = tle.epoch self.excentricity = tle.excentricity self.inclination = np.deg2rad(tle.inclination) self.right_ascension = np.deg2rad(tle.right_ascension) self.arg_perigee = np.deg2rad(tle.arg_perigee) self.mean_anomaly = np.deg2rad(tle.mean_anomaly) self.mean_motion = tle.mean_motion * (np.pi * 2 / XMNPDA) self.mean_motion_derivative = tle.mean_motion_derivative * \ np.pi * 2 / XMNPDA ** 2 self.mean_motion_sec_derivative = tle.mean_motion_sec_derivative * \ np.pi * 2 / XMNPDA ** 3 self.bstar = tle.bstar * AE n_0 = self.mean_motion k_e = XKE k_2 = CK2 i_0 = self.inclination e_0 = self.excentricity a_1 = (k_e / n_0) ** (2.0 / 3) delta_1 = ((3 / 2.0) * (k_2 / a_1**2) * ((3 * np.cos(i_0)**2 - 1) / (1 - e_0**2)**(2.0 / 3))) a_0 = a_1 * (1 - delta_1 / 3 - delta_1**2 - (134.0 / 81) * delta_1**3) delta_0 = ((3 / 2.0) * (k_2 / a_0**2) * ((3 * np.cos(i_0)**2 - 1) / (1 - e_0**2)**(2.0 / 3))) # original mean motion n_0pp = n_0 / (1 + delta_0) self.original_mean_motion = n_0pp # semi major axis a_0pp = a_0 / (1 - delta_0) self.semi_major_axis = a_0pp self.period = np.pi * 2 / n_0pp self.perigee = (a_0pp * (1 - e_0) / AE - AE) * XKMPER self.right_ascension_lon = (self.right_ascension - astronomy.gmst(self.epoch)) if self.right_ascension_lon > np.pi: self.right_ascension_lon -= 2 * np.pi
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 lat: Latitude of observer position on ground alt: Altitude above sea-level (geoid) of observer position on ground Return: (Azimuth, Elevation) """ (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_)