def get_lonlatalt(pos, utc_time): """Calculate sublon, sublat and altitude of satellite, considering the earth an ellipsoid. http://celestrak.com/columns/v02n03/ """ (pos_x, pos_y, pos_z) = pos / XKMPER 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 get_observer_look(sat_lon, sat_lat, sat_alt, 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) """ (pos_x, pos_y, pos_z), (vel_x, vel_y, vel_z) = astronomy.observer_position( utc_time, sat_lon, sat_lat, sat_alt) (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) if has_xarray and isinstance(az_, xr.DataArray): az_data = az_.data else: az_data = az_ if has_dask and isinstance(az_data, da.Array): az_data = da.where(top_s > 0, az_data + np.pi, az_data) az_data = da.where(az_data < 0, az_data + 2 * np.pi, az_data) else: az_data[np.where(top_s > 0)] += np.pi az_data[np.where(az_data < 0)] += 2 * np.pi if has_xarray and isinstance(az_, xr.DataArray): az_.data = az_data else: az_ = az_data 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(sat_lon, sat_lat, sat_alt, 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) """ (pos_x, pos_y, pos_z), (vel_x, vel_y, vel_z) = astronomy.observer_position( utc_time, sat_lon, sat_lat, sat_alt) (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) if has_xarray and isinstance(az_, xr.DataArray): az_data = az_.data else: az_data = az_ if has_dask and isinstance(az_data, da.Array): az_data = da.where(top_s > 0, az_data + np.pi, az_data) az_data = da.where(az_data < 0, az_data + 2 * np.pi, az_data) else: az_data[np.where(top_s > 0)] += np.pi az_data[np.where(az_data < 0)] += 2 * np.pi if has_xarray and isinstance(az_, xr.DataArray): az_.data = az_data else: az_ = az_data rg_ = np.sqrt(rx * rx + ry * ry + rz * rz) el_ = np.arcsin(top_z / rg_) return np.rad2deg(az_), np.rad2deg(el_)
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 get_lonlatalt(pos, utc_time): """Calculate sublon, sublat and altitude of satellite, considering the earth an ellipsoid. http://celestrak.com/columns/v02n03/ """ (pos_x, pos_y, pos_z) = pos / XKMPER 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 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 get_observer_look(self, time, lon, lat, alt): """Calculate observers look angle to a satellite. http://celestrak.com/columns/v02n02/ 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(time, normalize=False) (opos_x, opos_y, opos_z), (ovel_x, ovel_y, ovel_z) = \ astronomy.observer_position(time, lon, lat, alt) lon = np.deg2rad(lon) lat = np.deg2rad(lat) theta = (astronomy.gmst(time) + lon) % (2 * np.pi) rx = pos_x - opos_x ry = pos_y - opos_y rz = pos_z - opos_z rvx = vel_x - ovel_x rvy = vel_y - ovel_y rvz = vel_z - ovel_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) if top_s > 0: az = az + np.pi if az < 0: az = az + 2 * np.pi rg = np.sqrt(rx * rx + ry * ry + rz * rz) el = np.arcsin(top_z / rg) w = (rx * rvx + ry * rvy + rz * rvz) / 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 ECEF2ECI(xyz, utc_times): """ Convert ECEF (Earth Centered Earth Fixed) positions to ECI (Earth Centered Inertial) positions Parameters ---------- xyz : numpy.array of floats XYZ are cartesian positions in ECEF. Should have shape (N,3) utc_times : numpy.array of floats UTC_times are UTC timestamps, as datetime objects. Sould have shape (N) Returns ------- eci : numpy.array of floats Earth Centered Inertial coordinates. will have shape (N,3) Note ---- Requires pyorbital module Theory ------ [X] [C -S 0][X] [Y] = [S C 0][Y] [Z]eci [0 0 1][Z]ecf C and S are cos() and sin() of gmst (Greenwich Meridian Sideral Time) Source ------ http://ccar.colorado.edu/ASEN5070/handouts/coordsys.doc Inspired from satellite-js (https://github.com/shashwatak/satellite-js) """ # XYZ and utc_time must have the same shape #if not xyz.shape[:-1] == utc_times.shape: # raise ValueError("shape mismatch for XYZ and utc_times (got {} and {})".format(xyz.shape[:-1],utc_times.shape)) # gmst = -1 * astronomy.gmst(utc_times) # EDIT 180430 : Why this -1 ??? removed because wrong ! ... gmst = 1 * astronomy.gmst(utc_times) eci = xyz.copy() eci[:, 0] = xyz[:, 0] * np.cos(gmst) - xyz[:, 1] * np.sin(gmst) eci[:, 1] = xyz[:, 0] * np.sin(gmst) + xyz[:, 1] * np.cos(gmst) return eci
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 __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 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_twilight_poly(utctime): """Return a polygon enclosing the sunlit part of the globe at *utctime*.""" from pyorbital import astronomy ra, dec = astronomy.sun_ra_dec(utctime) lon = modpi(ra - astronomy.gmst(utctime)) lat = dec vertices = np.zeros((4, 2)) vertices[0, :] = modpi(lon - np.pi / 2), 0 if lat <= 0: vertices[1, :] = lon, np.pi / 2 + lat vertices[3, :] = modpi(lon + np.pi), -(np.pi / 2 + lat) else: vertices[1, :] = modpi(lon + np.pi), np.pi / 2 - lat vertices[3, :] = lon, -(np.pi / 2 - lat) vertices[2, :] = modpi(lon + np.pi / 2), 0 return SphPolygon(vertices)
def get_twilight_poly(utctime): """Return a polygon enclosing the sunlit part of the globe at *utctime*. """ from pyorbital import astronomy ra, dec = astronomy.sun_ra_dec(utctime) lon = modpi(ra - astronomy.gmst(utctime)) lat = dec vertices = np.zeros((4, 2)) vertices[0, :] = modpi(lon - np.pi / 2), 0 if lat <= 0: vertices[1, :] = lon, np.pi / 2 + lat vertices[3, :] = modpi(lon + np.pi), -(np.pi / 2 + lat) else: vertices[1, :] = modpi(lon + np.pi), np.pi / 2 - lat vertices[3, :] = lon, -(np.pi / 2 - lat) vertices[2, :] = modpi(lon + np.pi / 2), 0 return SphPolygon(vertices)
def get_alt(self, utc_time): (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 alt
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]
def ECI2ECEF(xyz, utc_times): """ Convert ECI (Earth Centered Inertial) positions to ECEF (Earth Centered Earth Fixed) positions Parameters ---------- xyz : numpy.array of floats XYZ are cartesian positions in Earth Centered Inertial. Should have shape (N,3) utc_times : numpy.array of floats UTC_times are UTC timestamps, as datetime objects. Sould have shape (N) Returns ------- ecef : numpy.array of floats Earth Centered Earth Fixed coordinates. will have shape (N,3) Note ---- Requires pyorbital module Theory ------ [X] ([C -S 0])[X] [Y] = inv([S C 0])[Y] [Z]ecef ([0 0 1])[Z]eci Empirically: [X] [ C S 0][X] [Y] = [-S C 0][Y] [Z]ecef [ 0 0 -1][Z]eci C and S are cos() and sin() of gmst (Greenwich Meridian Sideral Time) Source ------ http://ccar.colorado.edu/ASEN5070/handouts/coordsys.doc Inspired from satellite-js (https://github.com/shashwatak/satellite-js) Note ---- Quick mode of the reverse fct, can be improved """ from pyorbital import astronomy # XYZ and utc_time must have the same shape #if not xyz.shape[:-1] == utc_times.shape: # raise ValueError("shape mismatch for XYZ and utc_times (got {} and {})".format(xyz.shape[:-1],utc_times.shape)) # gmst = -1 * astronomy.gmst(utc_times) # EDIT 180430 : Why this -1 ??? removed because wrong ! ... gmst = 1 * astronomy.gmst(utc_times) ecef = xyz.copy() ecef[:, 0] = +xyz[:, 0] * np.cos(gmst) + xyz[:, 1] * np.sin(gmst) ecef[:, 1] = -xyz[:, 0] * np.sin(gmst) + xyz[:, 1] * np.cos(gmst) # ecef[:,2] = + xyz[:,2] # eci = xyz.copy() # # print(xyz) # # ecef_stk = [] # for xyz_epoc,gmst_epoc in zip(xyz,gmst): # M = np.array([[np.cos(gmst_epoc),-np.sin(gmst_epoc),0], # [np.sin(gmst_epoc), np.cos(gmst_epoc),0], # [ 0, 0,1]]) # Minv = np.linalg.inv(M) # # print(Minv) # ecef_epoc = Minv.dot(xyz.T) # ecef_stk.append(ecef_epoc) # # ecef = np.vstack(ecef_stk) return ecef