Beispiel #1
0
def test_itrf_vector():
    ts = load.timescale(builtin=True)
    t = ts.utc(2019, 11, 2, 3, 53)
    top = Topos(latitude_degrees=45,
                longitude_degrees=0,
                elevation_m=constants.AU_M - constants.ERAD)
    x, y, z = top.at(t).itrf_xyz().au
    assert abs(x - 0.7071) < 1e-4
    assert abs(y - 0.0) < 1e-14
    assert abs(z - 0.7071) < 1e-4
 def __init__(self, lat, long, t0, t1):
     self.lat = lat
     self.long = long
     self.t0 = t0
     self.t1 = t1
     # self.elev = elev
     # self.topo = Topos(self.lat, self.long, elevation_m=self.elev)
     self.topo = Topos(self.lat, self.long)
     self.loc = e['earth'] + self.topo
     print(self.loc)
Beispiel #3
0
    def get_planet_topos(self) -> Topos:
        if self.observation_planet is None:
            raise TypeError('Observation planet must be set.')

        if self._topos is None:
            self._topos = self.observation_planet + Topos(
                latitude_degrees=self.latitude,
                longitude_degrees=self.longitude)

        return self._topos
def test_moon_from_boston_astrometric():
    e = api.load_file(_data_path('de430-2015-03-02.bsp'))
    t = api.load.timescale(delta_t=67.185390 + 0.5285957).tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8),
                                x=0.003483, y=0.358609)
    a = boston.at(t).observe(e['moon'])
    ra, dec, distance = a.radec()
    compare(ra._degrees, 121.4796470, 0.001 * arcsecond)
    compare(dec.degrees, 14.9108450, 0.001 * arcsecond)
    compare(distance.au, 0.00265828588792, 1.4 * meter)  # TODO: improve this
Beispiel #5
0
 def __init__(self, latlong, tzname):
     lat, long = latlong
     self._latlong = Topos(latitude_degrees=lat, longitude_degrees=long)
     self._timezone = timezone(tzname)
     self._planets = None
     self._ts = None
     self._location = None
     self._winter_data = None
     self._summer_data = None
     self.sun_position = None
def test_moon_from_boston_geometry():
    e = api.load_file(_data_path('de430-2015-03-02.bsp'))
    t = api.load.timescale(delta_t=67.185390 + 0.5285957).tdb(2015, 3, 2)
    boston = e['earth'] + Topos(
        (42, 21, 24.1), (-71, 3, 24.8), x=0.003483, y=0.358609)
    a = (e['moon'] - boston).at(t)
    compare(
        a.position.au,
        [-1.341501206552443E-03, 2.190483327459023E-03, 6.839177007993498E-04],
        1.7 * meter)  # TODO: improve this
Beispiel #7
0
def main(argv):

    # Defaults
    inputFile = 'catalogTest.txt'
    outputFile = 'scheduleTest.txt'
    start = '01012020'
    duration = 1  # one day
    observerLatitude = 0.0
    observerLongitude = 0.0
    passes = True
    trajectory = False

    try:
        opts, args = getopt.getopt(argv, "hi:o:", ["ifile=", "ofile="])
    except getopt.GetoptError:
        print('generateSchedule.py -i <inputFile> -o <outputFile>', \
            ' -start <data> -duration <days>', \
            ' -obslat <observerLatitude> -obslon <observerLongitude>',\
            ' -passes -trajectory')
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print('generateSchedule.py -i <inputFile> -o <outputFile>', \
                ' -start <mmddyyyy> -duration <hours>', \
                ' -obslat <observerLatitude> -obslon <observerLongitude>',\
                ' -passes -trajectory')
            sys.exit()
        elif opt in ("-i", "--ifile"):
            inputFile = arg
        elif opt in ("-o", "--ofile"):
            outputFile = arg
        elif opt in ['-start']:
            start = arg
        elif opt in ['-duration']:
            duration = arg
        elif opt in ['-obslat']:
            observerLatitude = arg
        elif opt in ['-obslon']:
            observerLongitude = arg
        elif opt in ['-passes']:
            passes = True
        elif opt in ['-trajectory']:
            trajectory = True

    groundStation = Topos(observerLatitude, observerLongitude)

    ts = load.timescale()
    times = ts.utc(int(start[4:8]), int(start[0:2]), int(start[2:4]), 0,
                   range(0, 1440 * duration))

    catalog = readTLE(inputFile)
    schedule = computeSchedule(catalog, groundStation, times, passes,
                               trajectory)

    print("Schedule length:", len(schedule))
def test_vectors():
    ts = load.timescale()
    t = ts.tt(2017, 1, 23, 10, 44)

    planets = load('de421.bsp')
    earth = planets['earth']
    mars = planets['mars']

    v = earth

    assert str(v) == """\
Sum of 2 vectors:
 + Segment 'de421.bsp' 0 SOLAR SYSTEM BARYCENTER -> 3 EARTH BARYCENTER
 + Segment 'de421.bsp' 3 EARTH BARYCENTER -> 399 EARTH"""

    assert repr(v) == "\
<VectorSum of 2 vectors 0 SOLAR SYSTEM BARYCENTER -> 399 EARTH>"

    assert str(v.at(t)) == "\
<Barycentric BCRS position and velocity at date t center=0 target=399>"

    v = earth + Topos('38.9215 N', '77.0669 W', elevation_m=92.0)

    assert str(v) == """\
Sum of 3 vectors:
 + Segment 'de421.bsp' 0 SOLAR SYSTEM BARYCENTER -> 3 EARTH BARYCENTER
 + Segment 'de421.bsp' 3 EARTH BARYCENTER -> 399 EARTH
 + Topos 38deg 55' 17.4" N -77deg 04' 00.8" E"""

    assert repr(v) == """\
<VectorSum of 3 vectors 0 SOLAR SYSTEM BARYCENTER -> Topos 38deg 55' 17.4" N -77deg 04' 00.8" E>"""

    print(str(v.at(t)))
    assert str(v.at(t)) == """\
<Barycentric BCRS position and velocity at date t center=0 \
target=Topos 38deg 55' 17.4" N -77deg 04' 00.8" E>"""

    v = earth - mars

    assert str(v) == """\
Sum of 4 vectors:
 - Segment 'de421.bsp' 4 MARS BARYCENTER -> 499 MARS
 - Segment 'de421.bsp' 0 SOLAR SYSTEM BARYCENTER -> 4 MARS BARYCENTER
 + Segment 'de421.bsp' 0 SOLAR SYSTEM BARYCENTER -> 3 EARTH BARYCENTER
 + Segment 'de421.bsp' 3 EARTH BARYCENTER -> 399 EARTH"""

    assert repr(v) == "\
<VectorSum of 4 vectors 499 MARS -> 399 EARTH>"

    assert str(v.at(t)) == "\
<Geometric ICRS position and velocity at date t center=499 target=399>"

    geocentric = Geocentric([0,0,0])
    assert geocentric.center == 399
Beispiel #9
0
 def __init__(self, lat, lon, name):
     self.topos = Topos(lat, lon)
     self.lat = lat
     self.lon = lon
     self.ephemeris = load('de430.bsp')
     self.location = self.ephemeris['earth'] + self.topos
     self.ts = load.timescale()
     self.name = name
     lat_value, lon_value = ll_string_to_float(lat), ll_string_to_float(lon)
     self.timezone = pytz.timezone(tzwhere.tzwhere().tzNameAt(
         lat_value, lon_value))
Beispiel #10
0
def test_lst():
    ts = load.timescale()
    ts.delta_t_table = [-1e99, 1e99], [69.363285] * 2  # from finals2000A.all
    t = ts.utc(2020, 11, 27, 15, 34)
    top = Topos(latitude_degrees=0, longitude_degrees=0)
    expected = 20.0336663100  # see "authorities/horizons-lst"
    actual = top.lst_hours_at(t)
    difference_mas = (actual - expected) * 3600 * 15 * 1e3
    horizons_ra_offset_mas = 51.25
    difference_mas -= horizons_ra_offset_mas
    assert abs(difference_mas) < 1.0
def test_moon_from_boston_geometry():
    e = api.load_file(_data_path('de430-2015-03-02.bsp'))
    ts = api.load.timescale(delta_t=67.185390 + 0.5285957)
    ts.polar_motion_table = [0.0], [0.003483], [0.358609]
    t = ts.tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8))
    a = (e['moon'] - boston).at(t)
    compare(
        a.position.au,
        [-1.341501206552443E-03, 2.190483327459023E-03, 6.839177007993498E-04],
        1.1 * meter)
def test_boston_geometry():
    e = api.load_file(_data_path('jup310-2015-03-02.bsp'))
    ts = api.load.timescale(delta_t=67.185390 + 0.5285957)
    ts.polar_motion_table = [0.0], [0.003483], [0.358609]
    t = ts.tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8))
    a = (e['earth'] - boston).at(t)
    meter = 1e-3
    compare(a.position.km, [
        -1.764697476371664E+02, -4.717131288041386E+03, -4.274926422016179E+03
    ], 0.7 * meter)
Beispiel #13
0
def predict_passes(lat, lon, cache):
    # get observer location
    location = Topos(lat + ' N', lon + 'E')

    # build time range for predictions
    t0 = ts.now()
    end = list(t0.utc)
    end[2] += 1  # forecast 1 day forward
    t1 = ts.utc(*end)

    return get_upcoming_passes(location, t0, t1, cache, tle_file=None)
Beispiel #14
0
def test_from_altaz_parameters(ts):
    e = api.load('de421.bsp')
    usno = e['earth'] + Topos('38.9215 N', '77.0669 W', elevation_m=92.0)
    t = ts.tt(jd=api.T0)
    p = usno.at(t)
    a = api.Angle(degrees=10.0)
    with assert_raises(ValueError, 'the alt= parameter with an Angle'):
        p.from_altaz(alt='Bad value', alt_degrees=0, az_degrees=0)
    with assert_raises(ValueError, 'the az= parameter with an Angle'):
        p.from_altaz(az='Bad value', alt_degrees=0, az_degrees=0)
    p.from_altaz(alt=a, alt_degrees='bad', az_degrees=0)
    p.from_altaz(az=a, alt_degrees=0, az_degrees='bad')
Beispiel #15
0
    def distance(self, node):
        if self.cartesian is True:
            sx, sy, sz = self.coords
            x, y, z = node.coords
            return np.sqrt((x - sx) ** 2 + (y - sy) ** 2 + (z - sz) ** 2)

        else:
            node_location = Topos(float(node.coords[0]), float(node.coords[1]))
            difference = self.satellite - node_location
            topocentric = difference.at(self.t_new)
            alt, az, distMagnitude = topocentric.altaz()
            return int(distMagnitude.km / 1000)
def test_negation():
    ts = load.timescale()
    t = ts.utc(2020, 8, 30, 16, 5)
    usno = Topos('38.9215 N', '77.0669 W', elevation_m=92.0)
    neg = -usno
    p1 = usno.at(t)
    p2 = neg.at(t)
    assert (p1.position.au == -p2.position.au).all()
    assert (p1.velocity.au_per_d == -p2.velocity.au_per_d).all()

    # A second negation should return the unwrapped original.
    neg = -neg
    assert neg is usno
def lcn_Earths_surface():
    # specific to your location on the Earth’s surface:
    planets = load('de421.bsp')
    earth,mars = planets['earth'], planets['mars']
    boston = earth + Topos('17.9689 N', '79.5941 E') #warangla long abd lati
    ts = load.timescale()
    t = ts.now()
    astrometric = boston.at(t).observe(mars)
    alt, az, distance = astrometric.apparent().altaz()
    response = []
    details = {"ra":str(alt),"dec":str(az),"distance":str(distance.AU*149597870)}
    response.append(details)
    return jsonify(response)
Beispiel #18
0
 def parse_tle(cls, coords: Tuple[LatLong, LatLong], sat_name: str,
               tle_data: Dict) -> 'SatelliteObserver':
     """
     Parse TLE data into a SatelliteObserver object
     :param coords: latitude and longitude of the observer
     :param sat_name: satellite key to get from the TLE list
     :param tle_data: iterable list of TLE data
     :return: SatelliteObserver object
     """
     place = Topos(*coords)
     _satellites = {sat.name: sat for sat in tle_data}
     closest_sat_name, _ = process.extractOne(sat_name, _satellites.keys())
     return cls(place, _satellites[closest_sat_name])
Beispiel #19
0
def find_night_events(aos, los, location, time_zone, window):
    """
    Reduce events in the form of aos and los to events which occur at night

        Parameters:
            aos: array of aos for each satellite
            los: arrau of los for each satellite
            location: coordinates for observing
            time_zone: time_zone name
            window: observation window
        Returns:
            dark_aos: array of aos for events which occur at night
            dark_los: array of los for events which occur at night
    """

    # this is all required to find astronomical events
    midday = dt.datetime(window[0][0], window[0][1], int(np.floor(window[0][2])),
                         12, tzinfo = timezone(time_zone))
    next_midday = midday + dt.timedelta(days=1)

    ts = load.timescale()
    t0 = ts.from_datetime(midday)
    t1 = ts.from_datetime(next_midday)
    eph = load('de421.bsp')
    sight = Topos(location[0].strip('-') + 'S', location[1] + 'E')

    # load night conditions
    f = almanac.dark_twilight_day(eph, sight)
    # find dawn/dusk events
    astro_t, astro_events = almanac.find_discrete(t0, t1, f)

    astro_dusk = astro_t[2]
    astro_dawn = astro_t[4]

    dark_aos = []
    dark_los = []

    # find events which fall within dawn/dusk
    for satellite_aos, satellite_los in zip(aos, los):
        dark_start = []
        dark_end = []
        for start, end in zip(satellite_aos, satellite_los):
            if (astro_dusk.tt <= start <= astro_dawn.tt) \
            and (astro_dusk.tt <= end <= astro_dawn.tt):
                dark_start.append(start)
                dark_end.append(end)
        dark_aos.append(dark_start)
        dark_los.append(dark_end)

    return dark_aos, dark_los
Beispiel #20
0
def test_from_altaz_parameters(ts):
    usno = Topos('38.9215 N', '77.0669 W', elevation_m=92.0)
    t = ts.tt(jd=api.T0)
    p = usno.at(t)
    a = api.Angle(degrees=10.0)
    d = api.Distance(au=0.234)
    with assert_raises(ValueError, 'the alt= parameter with an Angle'):
        p.from_altaz(alt='Bad value', alt_degrees=0, az_degrees=0)
    with assert_raises(ValueError, 'the az= parameter with an Angle'):
        p.from_altaz(az='Bad value', alt_degrees=0, az_degrees=0)
    p.from_altaz(alt=a, alt_degrees='bad', az_degrees=0)
    p.from_altaz(az=a, alt_degrees=0, az_degrees='bad')
    assert str(p.from_altaz(alt=a, az=a).distance()) == '0.1 au'
    assert str(p.from_altaz(alt=a, az=a, distance=d).distance()) == '0.234 au'
Beispiel #21
0
def calc_comet(comet_df, obstime, earthcoords, numdays=0, alt_table=False):
    # Generating a position.
    cometvec = sun + mpc.comet_orbit(comet_df, ts, GM_SUN)

    cometpos = earth.at(obstime).observe(cometvec)
    ra, dec, distance = cometpos.radec()
    print("RA", ra, "   DEC", dec, "   Distance", distance)

    if earthcoords:
        if len(earthcoords) > 2:
            elev = earthcoords[2]
        else:
            elev = 0
        obstopos = Topos(latitude_degrees=earthcoords[0],
                         longitude_degrees=earthcoords[1],
                         elevation_m=elev)
        print("\nObserver at", obstopos.latitude, "N  ", obstopos.longitude,
              "E  ", "Elevation", obstopos.elevation.m, "m")
        obsvec = earth + obstopos

        alt, az, distance = \
            obsvec.at(obstime).observe(cometvec).apparent().altaz()
        print("Altitude", alt, "     Azumuth", az, distance)

        alm_twilights = almanac.dark_twilight_day(eph, obstopos)
        # dawn, dusk = find_twilights(obstime, alm_twilights)
        # print(WHICH_TWILIGHT, ": Dawn", svt2str(dawn), "Dusk", svt2str(dusk))

        if numdays:
            print("\nRises and sets over", numdays, "days:")
            datetime1 = obstime.utc_datetime() - timedelta(hours=2)
            t0 = ts.utc(datetime1)
            t1 = ts.utc(datetime1 + timedelta(days=numdays))

            alm = almanac.risings_and_settings(eph, cometvec, obstopos)
            t, y = almanac.find_discrete(t0, t1, alm)

            print_rises_sets(obsvec, cometvec, alm, t0, t1)

        if alt_table:
            print()
            oneday = timedelta(days=1)
            while True:
                print_alt_table(obstime, cometvec, obsvec, alm_twilights)
                numdays -= 1
                if numdays <= 0:
                    break
                # Add a day: there doesn't seem to be a way to do this
                # while staying within skyview's Time object.
                obstime = ts.utc(obstime.utc_datetime() + oneday)
Beispiel #22
0
    def on_pushButtonSetLocation_clicked(self):
        """Slot triggered when the button is clicked.
            """
        global home

        self.settings.setValue('mylatitude', self.my_latitude.text())
        self.settings.setValue('mylongitude', self.my_longitude.text())
        self.settings.setValue('myelevation', float(self.my_elevation.text()))

        home = Topos(self.my_latitude.text(),
                     self.my_longitude.text(),
                     elevation_m=float(self.my_elevation.text()))

        self.on_checkboxes_changed(0)
    def __init__(self, tle, location, start_time, duration, N=25):
        self.tle = tle
        self.location = location
        t0 = start_time.timestamp()
        t1 = (start_time + datetime.timedelta(seconds=duration)).timestamp()
        self.t = np.linspace(t0, t1, N)

        self.location = Topos(
            latitude_degrees=location['lat'],
            longitude_degrees=location['lon'],
            elevation_m=location['elv']
        )
        self.sat = EarthSatellite(self.tle[1], self.tle[2], self.tle[0], ts)
        self.diff = self.sat - self.location
Beispiel #24
0
def angle_2d(lat, lon, y, m, d, h):
    # given surface lat lon and time, calculate the its angles involving satellite and Sun

    # information about satellites (chose GOES 16)
    sats = api.load.tle('https://celestrak.com/NORAD/elements/goes.txt')
    satellite = sats['GOES 16 [+]']

    # planets
    planets = load('de421.bsp')
    sun = planets['sun']
    earth = planets['earth']

    # create array to hold angles
    angles = np.zeros((len(lat), len(lon), 5))

    for i in range(len(lat)):
        for j in range(len(lon)):
            #time
            ts = api.load.timescale()
            tm = ts.tt(y, m, d, h, 0, 0)

            # call the surface station "boston"
            boston = Topos(str(lat[i]) + ' N',
                           str(lon[j]) + ' W',
                           elevation_m=0.0)

            # the angle between the two vectors: earth center to satellite and earth center to observer
            theta = satellite.at(tm).separation_from(boston.at(tm))

            # geometry
            difference = satellite - boston
            geometry = difference.at(tm).altaz()

            # angles involving satellite
            scan = np.round(180 - (90 + geometry[0].degrees + theta.degrees),
                            2)
            zenith = np.round(geometry[0].degrees, 2)
            azimuth = np.round(geometry[1].degrees, 2)
            angles[i, j, 0] = zenith
            angles[i, j, 1] = azimuth
            angles[i, j, 2] = scan

            # angles involving the Sun
            observer = earth + boston
            geo2 = observer.at(tm).observe(sun).apparent().altaz()
            zenithsun = np.round(geo2[0].degrees, 2)
            azimuthsun = np.round(geo2[1].degrees, 2)
            angles[i, j, 3] = zenithsun
            angles[i, j, 4] = azimuthsun
    return angles
Beispiel #25
0
    def start(self):
        """
		Dev: K4YT3X IZAYOI
		Date Created: Jan 15, 2018
		Last Modified: Jan 16, 2018

		Dev: Reimannsum
		Last Modified: Aug 27, 2019

		This method is the main ISS pointer controller
		it runs infinitively until Ctrl^C is pressed.
		"""
        ts = load.timescale()
        stations_url = 'http://celestrak.com/NORAD/elements/stations.txt'
        satellites = load.tle(stations_url)
        satellite = satellites['ISS (ZARYA)']
        observer = Topos('42.5337N', '83.7384W')
        while True:
            t = ts.now()
            days = t - satellite.epoch
            if abs(days) > 14:
                satellites = load.tle(stations_url, reload=True)
                satellite = satellites['ISS (ZARYA)']
            self.pointer.check_gravity()
            difference = satellite - observer
            topocentric = difference.at(t)
            alt, az, distance = topocentric.altaz()

            self.pointer.elevation_set(alt.degrees)
            self.pointer.azimuth_set(az.degrees)
            self.display.set_pointing(az.degrees, alt.degrees)
            self.display.set_north(self.pointer.declination)
            g = self.pointer.compass.gravity
            self.display.set_gravity(g[0], g[1], g[2])

            Avalon.info("ISS Position Update:")
            #print(self.pointer.azimuth)
            #print(self.pointer)
            print(
                'Elevation :{0:6.3f}\tAzimuth :{1:6.3f}\nArm Correction:{3:6.3f}\tBase Correction:{2:6.3f}'
                .format(alt.degrees, az.degrees,
                        float(self.pointer.base_correction),
                        float(self.pointer.arm_correction)))
            print("Elev: {1:6.3f}\tAz: {0:6.3f}".format(
                float(self.pointer.azimuth), float(self.pointer.elevation)))
            print(self.pointer.compass)
            self.motor_base.set_azimuth(float(self.pointer.azimuth))
            self.motor_arm.set_azimuth(float(self.pointer.elevation))
            time.sleep(2.5)
Beispiel #26
0
def test_velocity():
    # It looks like this is a sweet spot for accuracy: presumably a
    # short enough fraction of a second that the vector does not time to
    # change direction much, but long enough that the direction does not
    # get lost down in the noise.
    factor = 300.0

    ts = load.timescale()
    t = ts.utc(2019, 11, 2, 3, 53, [0, 1.0 / factor])
    jacob = Topos(latitude_degrees=36.7138, longitude_degrees=-112.2169)
    p = jacob.at(t)
    velocity1 = p.position.km[:,1] - p.position.km[:,0]
    velocity2 = p.velocity.km_per_s[:,0]
    print(length_of(velocity2 - factor * velocity1))
    assert length_of(velocity2 - factor * velocity1) < 0.0007
def test_frame_rotation():
    # Does a frame's rotation and twist get applied in the right
    # directions?  Let's test whether the position and velocity of an
    # ITRS vector (ERAD,0,0) are restored to the proper orientation.
    top = Topos(latitude_degrees=0, longitude_degrees=0)
    ts = load.timescale()
    t = ts.utc(2020, 11, 27, 15, 34)  # Arbitrary time; LST ~= 20.03.
    p = top.at(t)

    r = p.frame_xyz(itrs)
    assert max(abs(r.m - [ERAD, 0, 0])) < 4e-8 # meters

    r, v = p.frame_xyz_and_velocity(itrs)
    assert max(abs(r.m - [ERAD, 0, 0])) < 4e-8 # meters
    assert max(abs(v.km_per_s)) < 3e-15 # km/s
Beispiel #28
0
def test_beneath(ts, angle):
    t = ts.utc(2018, 1, 19, 14, 37, 55)
    # An elevation of 0 is more difficult for the routine's accuracy
    # than a very large elevation.
    top = Topos(latitude_degrees=angle, longitude_degrees=angle, elevation_m=0)
    p = top.at(t)
    b = p.subpoint()

    error_degrees = abs(b.latitude.degrees - angle)
    error_mas = 60.0 * 60.0 * 1000.0 * error_degrees
    assert error_mas < 0.1

    error_degrees = abs(b.longitude.degrees - angle)
    error_mas = 60.0 * 60.0 * 1000.0 * error_degrees
    assert error_mas < 0.1
Beispiel #29
0
    def _set_location(self):
        """
        Set site location
        """
        self.longitude = SITES[self.name][0]
        self.latitude = SITES[self.name][1]
        self.elevation = SITES[self.name][2]

        self.geodetic = EarthLocation(lon=self.longitude,
                                      lat=self.latitude,
                                      height=self.elevation)

        self.topocentric = Topos(longitude_degrees=self.longitude,
                                 latitude_degrees=self.latitude,
                                 elevation_m=self.elevation)
Beispiel #30
0
def test_itrf_vector():
    top = Topos(latitude_degrees=45, longitude_degrees=0,
                elevation_m=constants.AU_M - constants.ERAD)

    x, y, z = top.itrs_position.au
    assert abs(x - sqrt(0.5)) < 2e-7
    assert abs(y - 0.0) < 1e-14
    assert abs(z - sqrt(0.5)) < 2e-7

    ts = load.timescale()
    t = ts.utc(2019, 11, 2, 3, 53)
    x, y, z = top.at(t).itrf_xyz().au
    assert abs(x - sqrt(0.5)) < 1e-4
    assert abs(y - 0.0) < 1e-14
    assert abs(z - sqrt(0.5)) < 1e-4