Ejemplo n.º 1
0
def generateEphemeris(name, tle1, tle2, time):
    """
    Generate ephemeris for the given satellite at given epoch
    
    Parameters
    ----------
    name : str
        Name of the satellite (line 0 of 3le)
    tle1 : str
        First line of the satellite's tle (line 1 of 3le)
    tle2 : str
        Second line of the satellite's tle (line 2 of 3le)
    date_str : str
        Desired epoch in format YYYY-mm-ddTHH:MM:SS
    
    Returns
    -------
    ra : 
    
    Raises
    ------
    None
    """

    observer = Topos(SITE_LATITUDE, SITE_LONGITUDE, elevation_m=SITE_ELEVATION)

    target = EarthSatellite(tle1, tle2, name)

    ra, dec, distance = (target - observer).at(time).radec()

    return [name, ra.hours, dec.degrees]
Ejemplo n.º 2
0
    def __init__(self, line1, line2, name=None):
        """
        Initiates the TLE
        
        Parameters
        ----------
        line1, line2 : str
            First and second lines of the TLE
        name : str, optional
            Name of the object to which the TLE is attributed
        """
        self.line1 = line1
        self.line2 = line2
        if name is not None:
            self.name = name[2:]
        else:
            self.name = 'UNKNOWN'

        # ephemeris info
        self.obs = TOPOS_LOCATION
        self.obj = EarthSatellite(line1, line2, name)
        self.ts = TS

        # book-keeping
        self.norad_id = int(self.line1[2:7])
        self.yday = float(self.line1[20:32])

        # orbital properties
        self.inclination = float(self.line2[8:16])
        self.eccentricity = float(self.line2[26:33])
        self.raan = float(self.line2[17:25])
        self.argperigree = float(self.line2[34:42])
        self.mean_anomaly = float(self.line2[43:51])
        self.mean_motion = float(self.line2[52:63])
Ejemplo n.º 3
0
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)
    }
Ejemplo n.º 4
0
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 test_appendix_c_satellite():
    lines = appendix_c_example.splitlines()
    sat = EarthSatellite(lines, earth)

    jd_epoch = sat._sgp4_satellite.jdsatepoch
    three_days_later = jd_epoch + 3.0
    offset = JulianDate(tt=three_days_later)._utc_float() - three_days_later
    jd = JulianDate(tt=three_days_later - offset)

    # First, a crucial sanity check (which is, technically, a test of
    # the `sgp4` package and not of Skyfield): are the right coordinates
    # being produced by our Python SGP4 propagator for this satellite?

    rTEME, vTEME, error = sat._position_and_velocity_TEME_km(jd)

    assert abs(-9060.47373569 - rTEME[0]) < 1e-8
    assert abs(4658.70952502 - rTEME[1]) < 1e-8
    assert abs(813.68673153 - rTEME[2]) < 1e-8

    assert abs(-2.232832783 - vTEME[0]) < 1e-9
    assert abs(-4.110453490 - vTEME[1]) < 1e-9
    assert abs(-3.157345433 - vTEME[2]) < 1e-9
def test_appendix_c_satellite():
    lines = appendix_c_example.splitlines()
    sat = EarthSatellite(lines, earth)

    jd_epoch = sat._sgp4_satellite.jdsatepoch
    three_days_later = jd_epoch + 3.0
    jd = JulianDate(tt=three_days_later)
    jd.ut1 = array(three_days_later)

    # First, a crucial sanity check (which is, technically, a test of
    # the `sgp4` package and not of Skyfield): are the right coordinates
    # being produced by our Python SGP4 propagator for this satellite?

    rTEME, vTEME = sat._position_and_velocity_TEME_km(jd)

    assert abs(-9060.47373569 - rTEME[0]) < 1e-8
    assert abs(4658.70952502 - rTEME[1]) < 1e-8
    assert abs(813.68673153 - rTEME[2]) < 1e-8

    assert abs(-2.232832783 - vTEME[0]) < 1e-9
    assert abs(-4.110453490 - vTEME[1]) < 1e-9
    assert abs(-3.157345433 - vTEME[2]) < 1e-9
def test_iss_altitude_computed_with_gcrs(iss_transit):
    dt, their_altitude = iss_transit

    cst = timedelta(hours=-6)  #, minutes=1)
    dt = dt - cst
    t = api.load.timescale(delta_t=67.2091).utc(dt)

    lines = iss_tle.splitlines()
    s = EarthSatellite(lines, None)
    lake_zurich = api.Topos(latitude_degrees=42.2, longitude_degrees=-88.1)

    alt, az, d = lake_zurich.at(t).observe(s).altaz()
    print(dt, their_altitude, alt.degrees, their_altitude - alt.degrees)
    assert abs(alt.degrees - their_altitude) < 2.5  # TODO: tighten this up?
def test_appendix_c_satellite():
    lines = appendix_c_example.splitlines()
    sat = EarthSatellite(lines, None)

    ts = api.load.timescale()
    jd_epoch = sat._sgp4_satellite.jdsatepoch
    three_days_later = jd_epoch + 3.0
    offset = ts.tt(jd=three_days_later)._utc_float() - three_days_later
    t = ts.tt(jd=three_days_later - offset)

    # First, a crucial sanity check (which is, technically, a test of
    # the `sgp4` package and not of Skyfield): are the right coordinates
    # being produced by our Python SGP4 propagator for this satellite?

    rTEME, vTEME, error = sat._position_and_velocity_TEME_km(t)

    assert abs(-9060.47373569 - rTEME[0]) < 1e-8
    assert abs(4658.70952502 - rTEME[1]) < 1e-8
    assert abs(813.68673153 - rTEME[2]) < 1e-8

    assert abs(-2.232832783 - vTEME[0]) < 1e-9
    assert abs(-4.110453490 - vTEME[1]) < 1e-9
    assert abs(-3.157345433 - vTEME[2]) < 1e-9
def test_iss_altitude_computed_with_gcrs(iss_transit):
    dt, their_altitude = iss_transit

    cst = timedelta(hours=-6)  #, minutes=1)
    dt = dt - cst
    jd = JulianDate(utc=dt, delta_t=67.2091)

    lines = iss_tle.splitlines()
    s = EarthSatellite(lines, earth)
    lake_zurich = earth.topos(latitude_degrees=42.2, longitude_degrees=-88.1)

    alt, az, d = lake_zurich.gcrs(jd).observe(s).altaz()
    print(dt, their_altitude, alt.degrees, their_altitude - alt.degrees)
    assert abs(alt.degrees - their_altitude) < 2.5  # TODO: tighten this up?
Ejemplo n.º 10
0
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])
Ejemplo n.º 11
0
def test_iss_altitude_computed_with_bcrs(iss_transit):
    dt, their_altitude = iss_transit

    cst = timedelta(hours=-6)  #, minutes=1)
    dt = dt - cst
    jd = Timescale(delta_t=67.2091).utc(dt)

    lines = iss_tle.splitlines()
    s = EarthSatellite(lines, None)
    earth = api.load('de421.bsp')['earth']
    lake_zurich = earth.topos(latitude_degrees=42.2, longitude_degrees=-88.1)

    # Compute using Solar System coordinates:

    alt, az, d = lake_zurich.at(jd).observe(s).altaz()
    print(dt, their_altitude, alt.degrees, their_altitude - alt.degrees)
    assert abs(alt.degrees - their_altitude) < 2.5  # TODO: tighten this up?
Ejemplo n.º 12
0
    def __init__(self, line1, line2, name=None):
        self.line1 = line1
        self.line2 = line2
        if name is not None:
            self.name = name[2:]

        self.obs = TOPOS_LOCATION
        self.obj = EarthSatellite(line1, line2, name)
        self.ts = TS

        self.norad_id = int(self.line1[2:7])
        self.yday = float(self.line1[20:32])

        self.inclination = float(self.line2[8:16])
        self.eccentricity = float(self.line2[26:33])
        self.raan = float(self.line2[17:25])
        self.argperigree = float(self.line2[34:42])
        self.mean_anomaly = float(self.line2[43:51])
        self.mean_motion = float(self.line2[52:63])
Ejemplo n.º 13
0
    def __init__(self, line1, line2, name=None):
        """
        Initiates the TLE
        
        Parameters
        ----------
        line1, line2 : str
            First and second lines of the TLE
        name : str, optional
            Name of the object to which the TLE is attributed
        """
        self.line1 = line1
        self.line2 = line2
        if name is not None:
            self.name = name[2:]
        else:
            self.name = 'UNKNOWN'

        # ephemeris info
        self.obs = TOPOS_LOCATION
        self.obj = EarthSatellite(line1, line2, name)
        self.ts = TS
Ejemplo n.º 14
0
from datetime import datetime
from astropy.table import Table
import numpy as np
import time

from st.site import Site

EPHEM_PATH = '/Users/jblake95/GitHub/tlemcee/ephem_astra_1m_20180618_LaPalma.csv'
TS = load.timescale()

ephem = Table.read(EPHEM_PATH)

line1 = '1 33436U 08057A   18170.03521762  .00000104  00000-0  00000+0 0  9996'
line2 = '2 33436   0.0136 355.3865 0004990 118.0808 185.6030  1.00271245 35197'

obj = EarthSatellite(line1, line2)
site = Site('LaPalma')

# test 1 - without arrays
times = []
for t in ephem['UTC']:
    times.append(datetime.strptime(t, '%Y-%m-%dT%H:%M:%S.%f'))
times = np.array(times)
print('Computing for {} positions'.format(len(times)))

from astropy.coordinates import SkyCoord
from astropy import units as u

t0 = time.time()
ra, dec = np.zeros((2, len(times)))
for t, dt in enumerate(times):
Ejemplo n.º 15
0
def test_epoch_date():
    # Example from https://celestrak.com/columns/v04n03/
    s = appendix_c_example.replace('00179.78495062', '98001.00000000')
    sat = EarthSatellite(s.splitlines(), None)
    assert sat.epoch.utc_jpl() == 'A.D. 1998-Jan-01 00:00:00.0000 UT'
Ejemplo n.º 16
0
def unpackElements(tle):
    """
    Unpack TLE input

    Parameters
    ----------
    tle : st.tle.TLE
        TLE object to unpack

    Returns
    -------
    None
    """
    tle.checksums = []
    # line 1 elements
    if tle.line1 is not None:
        tle.norad_id = Norad_ID(tle.line1)
        tle.designator = Designator(tle.line1)
        tle.epoch = Epoch(tle.line1)
        tle.mmdot = Mmdot(tle.line1)
        tle.mmdot2 = Mmdot2(tle.line1)
        tle.drag = Drag(tle.line1)
        tle.setnumber = SetNumber(tle.line1)
        tle.checksums.append(CheckSum(tle.line1))
    else:
        tle.norad_id = Norad_ID()
        tle.designator = Designator()
        tle.epoch = Epoch()
        tle.mmdot = Mmdot()
        tle.mmdot2 = Mmdot2()
        tle.drag = Drag()
        tle.setnumber = SetNumber()

        tle.line1 = EmptyTLE.line1.format(tle.norad_id.entry,
                                          tle.designator.entry,
                                          tle.epoch.entry, tle.mmdot.entry,
                                          tle.mmdot2.entry, tle.drag.entry,
                                          tle.setnumber.entry)
        # compute checksum
        tle.checksums.append(CheckSum(tle.line1))
        tle.line1 = '{}{}'.format(tle.line1[:-1], tle.checksums[0].entry)

    # line 2 elements
    if tle.line2 is not None:
        tle.inclination = Inclination(tle.line2)
        tle.raan = RAAN(tle.line2)
        tle.eccentricity = Eccentricity(tle.line2)
        tle.argperigee = ArgPerigee(tle.line2)
        tle.meananomaly = MeanAnomaly(tle.line2)
        tle.mm = Mm(tle.line2)
        tle.revnumber = RevNumber(tle.line2)
        tle.checksums.append(CheckSum(tle.line2))
    else:
        tle.inclination = Inclination()
        tle.raan = RAAN()
        tle.eccentricity = Eccentricity()
        tle.argperigee = ArgPerigee()
        tle.meananomaly = MeanAnomaly()
        tle.mm = Mm()
        tle.revnumber = RevNumber()

        tle.line2 = EmptyTLE.line2.format(
            tle.norad_id.entry, tle.inclination.entry, tle.raan.entry,
            tle.eccentricity.entry, tle.argperigee.entry,
            tle.meananomaly.entry, tle.mm.entry, tle.revnumber.entry)
        # compute checksum
        tle.checksums.append(CheckSum(tle.line2))
        tle.line2 = '{}{}'.format(tle.line2[:-1], tle.checksums[1].entry)

    # name
    if tle.name is not None:
        # remove line number if from 3le
        if tle.name[0] == '0':
            tle.name = tle.name[2:]
    else:
        tle.name = 'UNKNOWN'

    tle._object = EarthSatellite(tle.line1, tle.line2, tle.name)
    return None
Ejemplo n.º 17
0
def modifyElements(tle, checksum, norad_id, designator, epoch, mmdot, mmdot2,
                   drag, setnumber, inclination, raan, eccentricity,
                   argperigee, meananomaly, mm, revnumber):
    """
    Modify elements of a TLE object

    Parameters
    ----------
    tle : st.tle.TLE
        TLE object in need of modification
    checksum : bool
        Toggle to recalculate checksum

    See descriptions above for suitable inputs for args
    (set to None for no modification)

    Returns
    -------
    None
    """
    if norad_id is not None:
        tle.norad_id = Norad_ID(norad_id)
        tle.line1 = '{}{}{}'.format(tle.line1[:2], tle.norad_id.entry,
                                    tle.line1[7:])
        tle.line2 = '{}{}{}'.format(tle.line2[:2], tle.norad_id.entry,
                                    tle.line2[7:])

    if designator is not None:
        tle.designator = Designator(designator)
        tle.line1 = '{}{}{}'.format(tle.line1[:9], tle.designator.entry,
                                    tle.line1[17:])

    if epoch is not None:
        tle.epoch = Epoch(epoch)
        tle.line1 = '{}{}{}'.format(tle.line1[:18], tle.epoch.entry,
                                    tle.line1[32:])

    if mmdot is not None:
        tle.mmdot = Mmdot(mmdot)
        tle.line1 = '{}{}{}'.format(tle.line1[:33], tle.mmdot.entry,
                                    tle.line1[43:])

    if mmdot2 is not None:
        tle.mmdot2 = Mmdot2(mmdot2)
        tle.line1 = '{}{}{}'.format(tle.line1[:44], tle.mmdot2.entry,
                                    tle.line1[52:])

    if drag is not None:
        tle.drag = Drag(drag)
        tle.line1 = '{}{}{}'.format(tle.line1[:53], tle.drag.entry,
                                    tle.line1[61:])

    if setnumber is not None:
        tle.setnumber = SetNumber(setnumber)
        tle.line1 = '{}{}{}'.format(tle.line1[:64], tle.setnumber.entry,
                                    tle.line1[68:])

    if inclination is not None:
        tle.inclination = Inclination(inclination)
        tle.line2 = '{}{}{}'.format(tle.line2[:8], tle.inclination.entry,
                                    tle.line2[16:])

    if raan is not None:
        tle.raan = RAAN(raan)
        tle.line2 = '{}{}{}'.format(tle.line2[:17], tle.raan.entry,
                                    tle.line2[25:])

    if eccentricity is not None:
        tle.eccentricity = Eccentricity(eccentricity)
        tle.line2 = '{}{}{}'.format(tle.line2[:26], tle.eccentricity.entry,
                                    tle.line2[33:])

    if argperigee is not None:
        tle.argperigee = ArgPerigee(argperigee)
        tle.line2 = '{}{}{}'.format(tle.line2[:34], tle.argperigee.entry,
                                    tle.line2[42:])

    if meananomaly is not None:
        tle.meananomaly = MeanAnomaly(meananomaly)
        tle.line2 = '{}{}{}'.format(tle.line2[:43], tle.meananomaly.entry,
                                    tle.line2[51:])

    if mm is not None:
        tle.mm = Mm(mm)
        tle.line2 = '{}{}{}'.format(tle.line2[:52], tle.mm.entry,
                                    tle.line2[63:])

    if revnumber is not None:
        tle.revnumber = RevNumber(revnumber)
        tle.line2 = '{}{}{}'.format(tle.line2[:63], tle.revnumber.entry,
                                    tle.line2[68:])

    if checksum:
        calculateCheckSums(tle)

    tle._object = EarthSatellite(tle.line1, tle.line2, tle.name)
    return None