def predict_doppler_from_tle(tle1, tle2, start_time, gs, base_freq): end_time = ts.tt_jd(start_time.tt + 1) #predict for 1 day in future tle_sat = EarthSatellite(tle1, tle2) times, events = tle_sat.find_events(gs, start_time, end_time, altitude_degrees=0.0) #Find events where the satellite sets below 10 degrees, and use this to split the times array up into individual passes sat_passes = [] start = -1 end = -1 for i, event in enumerate(events): if (event == 0): start = i if (event == 2) and (start > end): end = i sat_passes.append([times[start], times[end]]) for sat_pass in sat_passes: p_start = sat_pass[0] p_end = sat_pass[-1] #Split pass timeframe into 1000 time_points = ts.tt_jd(np.linspace(p_start.tt, p_end.tt, 1000)) sat_range_rate = tle_sat.at(time_points).velocity.km_per_s - gs.at( time_points).velocity.km_per_s sat_range = tle_sat.at(time_points).position.km - gs.at( time_points).position.km #Take the range rate's component in the direction of the range radial_velocity = np.array([np.dot([a[b] for a in sat_range], [a[b] for a in sat_range_rate]) \ / np.linalg.norm([a[b] for a in sat_range]) for b in range(1000)]) shifted_freqs = base_freq / (1 + radial_velocity / c) plt.plot(time_points.tt, shifted_freqs, markersize=1) plt.xlabel("Time (Julian Days)") plt.ylabel("Shifted frequency (Hz)") plt.show()
def generate_ephemeris(name, tle1, tle2, date_str): date = datetime.datetime.strptime(date_str, '%Y-%m-%dT%H:%M:%S') date = date.replace(tzinfo=utc) lst = Time(date, scale='utc', location=SITE_LOCATION).sidereal_time('apparent') print('name', name) print('tle1', tle1) print('tle2', tle2) print('date', date) observer = Topos( latitude_degrees=SITE_LOCATION.lat.to(u.deg).value, longitude_degrees=SITE_LOCATION.lon.to(u.deg).value, elevation_m=SITE_LOCATION.height.to(u.m).value) time = load.timescale().utc(date) target = EarthSatellite(tle1, tle2, name) ra, dec, distance = (target - observer).at(time).radec() alt, az, distance = (target - observer).at(time).altaz() subpos = target.at(time).subpoint() lat = subpos.latitude.degrees lon = subpos.longitude.degrees if lon > 180: lon -= 360 field = SkyCoord(ra.hours, dec.degrees, unit=(u.hourangle, u.deg)) time2 = load.timescale().utc(date + datetime.timedelta(seconds=5)) ra2, dec2, distance2 = (target - observer).at(time2).radec() dra = (ra2._degrees - ra._degrees) * 3600 / 5 ddec = (dec2.degrees - dec.degrees) * 3600 / 5 return { 'name': name, 'date': date.strftime('%Y-%m-%dT%H:%M:%S'), 'ra': Angle(ra.to(u.deg)).to_string(unit=u.hourangle, sep=':'), 'ha': (lst - field.icrs.ra).wrap_at(12 * u.hourangle).to_string(sep=':', unit=u.hourangle, precision=2), 'dec': Angle(dec.to(u.deg)).to_string(unit=u.deg, sep=':'), 'dra': round(dra, 3), 'ddec': round(ddec, 3), 'alt': round(alt.degrees, 6), 'az': round(az.degrees, 6), 'latitude': round(lat, 3), 'longitude': round(lon, 3) }
def create_ground_track(out_path, sat, tle=None, start=None, delta_min=1, num_steps=1440, min_sun=None, sensor_angle=None, check_swath=False): """ Compute the ground track and sensor swatch for Globals and then write to GeoJSON """ # get globals tles from Celestrak if TLE not passed in if tle is None: tle = get_globals_tle(sat) timescale = load.timescale(builtin=True) times_dt = generate_time_array(start, delta_min, num_steps) times = timescale.utc(times_dt) sat_obj = EarthSatellite(line1=tle[0], line2=tle[1]) subsat = sat_obj.at(times).subpoint() lat = subsat.latitude.degrees lon = subsat.longitude.degrees track = np.concatenate([lon.reshape(-1, 1), lat.reshape(-1, 1)], axis=1) track_list = filter_sun_elevation(track, times_dt, min_sun) track_list = correct_rollover(track_list) properties = {"sat": sat, "start_time": str(times_dt[0]), "stop_time": str(times_dt[-1]), "time_step_minutes": delta_min} write_track_geojson(out_path, track_list, properties) if sensor_angle is not None: swath_list = get_sensor_swath(track_list, sensor_angle, GLOBALS_ALTITUDE_KM[sat]) swath_out_path = os.path.splitext(out_path)[0] + "_swath" + os.path.splitext(out_path)[1] write_track_geojson(swath_out_path, swath_list, properties) if check_swath: swath_check_out_path = os.path.splitext(out_path)[0] + "_swath_test" + os.path.splitext(out_path)[1] check_swath(swath_check_out_path, track_list, sensor_angle, 1000*GLOBALS_ALTITUDE_KM[sat])