Example #1
0
    def annual_parallax(self, time_to_treat):
        """Compute the position shift due to the Earth movement. Please have a look on :
        "Resolution of the MACHO-LMC-5 Puzzle: The Jerk-Parallax Microlens Degeneracy"
        Gould, Andrew 2004. http://adsabs.harvard.edu/abs/2004ApJ...606..319G

        :param  time_to_treat: a numpy array containing the time where you want to compute this
        effect.
        :return: the shift induce by the Earth motion around the Sun
        :rtype: array_like

        **WARNING** : this is a geocentric point of view.
                      slalib use MJD time definition, which is MJD = JD-2400000.5
        """

        with solar_system_ephemeris.set('builtin'):
            time_jd_reference = Time(self.to_par, format='jd')
            Earth_position_time_reference = get_body_barycentric_posvel('Earth', time_jd_reference)
            Sun_position_time_reference = -Earth_position_time_reference[0]
            Sun_speed_time_reference = -Earth_position_time_reference[1]

            time_jd = Time(time_to_treat, format='jd')
            Earth_position = get_body_barycentric_posvel('Earth', time_jd)
            Sun_position = -Earth_position[0]

            delta_Sun = Sun_position.xyz.value.T - np.c_[
                time_to_treat - self.to_par] * Sun_speed_time_reference.xyz.value \
                        - Sun_position_time_reference.xyz.value

            delta_Sun_projected = np.array(
                [np.dot(delta_Sun, self.North), np.dot(delta_Sun, self.East)])

            return delta_Sun_projected
Example #2
0
def _targetting(departure_body, target_body, t_launch, t_arrival):
    """This function returns the increment in departure and arrival velocities.

    """

    # Compute departure and arrival positions
    rr_dpt_body, vv_dpt_body = coord.get_body_barycentric_posvel(
        departure_body.name, t_launch)
    rr_arr_body, vv_arr_body = coord.get_body_barycentric_posvel(
        target_body.name, t_arrival)

    # Compute time of flight
    tof = t_arrival - t_launch

    if tof <= 0:
        return None, None, None

    try:
        (v_dpt, v_arr), = lambert(Sun.k, rr_dpt_body.xyz, rr_arr_body.xyz, tof)

        # Compute all the output variables
        dv_dpt = norm(v_dpt - vv_dpt_body.xyz)
        dv_arr = norm(v_arr - vv_arr_body.xyz)
        c3_launch = dv_dpt**2
        c3_arrival = dv_arr**2

        return (
            c3_launch.to(u.km**2 / u.s**2).value,
            c3_arrival.to(u.km**2 / u.s**2).value,
            tof.jd,
        )

    except AssertionError:
        return None, None, None
Example #3
0
def hcrs_to_hgs(hcrscoord, hgsframe):
    """
    Convert from HCRS to Heliographic Stonyhurst (HGS).

    HGS shares the same origin (the Sun) as HCRS, but has its Z axis aligned with the Sun's
    rotation axis and its X axis aligned with the projection of the Sun-Earth vector onto the Sun's
    equatorial plane (i.e., the component of the Sun-Earth vector perpendicular to the Z axis).
    Thus, the transformation matrix is the product of the matrix to align the Z axis (by de-tilting
    the Sun's rotation axis) and the matrix to align the X axis.  The first matrix is independent
    of time and is pre-computed, while the second matrix depends on the time-varying Sun-Earth
    vector.
    """
    if hgsframe.obstime is None:
        raise ValueError("To perform this transformation the coordinate"
                         " Frame needs an obstime Attribute")

    # Check whether differentials are involved on either end
    has_differentials = (
        (hcrscoord._data is not None and hcrscoord.data.differentials)
        or (hgsframe._data is not None and hgsframe.data.differentials))

    # Determine the Sun-Earth vector in ICRS
    # Since HCRS is ICRS with an origin shift, this is also the Sun-Earth vector in HCRS
    # If differentials exist, also obtain Sun and Earth velocities
    if has_differentials:
        sun_pos_icrs, sun_vel = get_body_barycentric_posvel(
            'sun', hgsframe.obstime)
        earth_pos_icrs, earth_vel = get_body_barycentric_posvel(
            'earth', hgsframe.obstime)
    else:
        sun_pos_icrs = get_body_barycentric('sun', hgsframe.obstime)
        earth_pos_icrs = get_body_barycentric('earth', hgsframe.obstime)
    sun_earth = earth_pos_icrs - sun_pos_icrs

    # De-tilt the Sun-Earth vector to the frame with the Sun's rotation axis parallel to the Z axis
    sun_earth_detilt = sun_earth.transform(_SUN_DETILT_MATRIX)

    # Rotate the Sun-Earth vector about the Z axis so that it lies in the XZ plane
    rot_matrix = _rotation_matrix_reprs_to_xz_about_z(sun_earth_detilt)

    total_matrix = rot_matrix @ _SUN_DETILT_MATRIX

    # All of the above is calculated for the HGS observation time
    # If the HCRS observation time is different, calculate the translation in origin
    if not _ignore_sun_motion and np.any(
            hcrscoord.obstime != hgsframe.obstime):
        sun_pos_old_icrs = get_body_barycentric('sun', hcrscoord.obstime)
        offset_icrf = sun_pos_icrs - sun_pos_old_icrs
    else:
        offset_icrf = sun_pos_icrs * 0  # preserves obstime shape

    # Add velocity if needed (at the HGS observation time)
    if has_differentials:
        vel_icrf = (sun_vel - earth_vel).represent_as(CartesianDifferential)
        offset_icrf = offset_icrf.with_differentials(vel_icrf)

    offset = offset_icrf.transform(total_matrix)
    return total_matrix, offset
Example #4
0
def _get_state(body, time):
    """ Computes the position of a body for a given time. """

    solar_system_bodies = [
        Sun,
        Mercury,
        Venus,
        Earth,
        Moon,
        Mars,
        Jupiter,
        Saturn,
        Uranus,
        Neptune,
        Pluto,
    ]

    # We check if body belongs to poliastro.bodies
    if body in solar_system_bodies:
        rr, vv = coord.get_body_barycentric_posvel(body.name, time)
    else:
        rr, vv = body.propagate(time).rv()
        rr = coord.CartesianRepresentation(rr)
        vv = coord.CartesianRepresentation(vv)

    return rr, vv
Example #5
0
    def from_body_ephem(cls, body, epoch=None):
        """Return osculating `Orbit` of a body at a given time.

        """
        if not epoch:
            epoch = time.Time.now().tdb
        elif epoch.scale != 'tdb':
            epoch = epoch.tdb
            warn(
                "Input time was converted to scale='tdb' with value "
                "{}. Use Time(..., scale='tdb') instead.".format(
                    epoch.tdb.value), TimeScaleWarning)
        r, v = get_body_barycentric_posvel(body.name, epoch)
        if body == Moon:
            moon_icrs = ICRS(x=r.x,
                             y=r.y,
                             z=r.z,
                             v_x=v.x,
                             v_y=v.y,
                             v_z=v.z,
                             representation=CartesianRepresentation,
                             differential_type=CartesianDifferential)
            moon_gcrs = moon_icrs.transform_to(GCRS(obstime=epoch))
            moon_gcrs.representation = CartesianRepresentation
            r = CartesianRepresentation(
                [moon_gcrs.x, moon_gcrs.y, moon_gcrs.z])
            v = CartesianRepresentation(
                [moon_gcrs.v_x, moon_gcrs.v_y, moon_gcrs.v_z])
        return cls.from_vectors(body.parent, r.xyz.to(u.km),
                                v.xyz.to(u.km / u.day), epoch)
Example #6
0
    def from_body_ephem(cls, body, epoch=None):
        """Return osculating `Orbit` of a body at a given time.

        """
        # TODO: https://github.com/poliastro/poliastro/issues/445
        if not epoch:
            epoch = time.Time.now().tdb
        elif epoch.scale != 'tdb':
            epoch = epoch.tdb
            warn(
                "Input time was converted to scale='tdb' with value "
                "{}. Use Time(..., scale='tdb') instead.".format(
                    epoch.tdb.value), TimeScaleWarning)

        r, v = get_body_barycentric_posvel(body.name, epoch)

        if body == Moon:
            # TODO: The attractor is in fact the Earth-Moon Barycenter
            icrs_cart = r.with_differentials(
                v.represent_as(CartesianDifferential))
            gcrs_cart = ICRS(icrs_cart).transform_to(
                GCRS(obstime=epoch)).represent_as(CartesianRepresentation)
            ss = cls.from_vectors(
                Earth, gcrs_cart.xyz.to(u.km),
                gcrs_cart.differentials['s'].d_xyz.to(u.km / u.day), epoch)

        else:
            # TODO: The attractor is not really the Sun, but the Solar System Barycenter
            ss = cls.from_vectors(Sun, r.xyz.to(u.km), v.xyz.to(u.km / u.day),
                                  epoch)
            ss._frame = ICRS()  # Hack!

        return ss
Example #7
0
def test_velocity_hcrs_hgs():
    # Obtain the position/velocity of Earth in ICRS
    obstime = Time(['2019-01-01', '2019-04-01', '2019-07-01', '2019-10-01'])
    pos, vel = get_body_barycentric_posvel('earth', obstime)
    loc = pos.with_differentials(vel.represent_as(CartesianDifferential))
    earth = SkyCoord(loc, frame='icrs', obstime=obstime)

    # The velocity of Earth in HGS should be very close to zero.  The velocity in the HGS Y
    # direction is slightly further away from zero because there is true latitudinal motion.
    new = earth.heliographic_stonyhurst
    assert_quantity_allclose(new.velocity.d_x,
                             0 * u.km / u.s,
                             atol=1e-15 * u.km / u.s)
    assert_quantity_allclose(new.velocity.d_y,
                             0 * u.km / u.s,
                             atol=1e-14 * u.km / u.s)
    assert_quantity_allclose(new.velocity.d_x,
                             0 * u.km / u.s,
                             atol=1e-15 * u.km / u.s)

    # Test the loopback to ICRS
    newer = new.icrs
    assert_quantity_allclose(newer.velocity.d_x, vel.x)
    assert_quantity_allclose(newer.velocity.d_y, vel.y)
    assert_quantity_allclose(newer.velocity.d_z, vel.z)
Example #8
0
def objPosVel_wrt_SSB(objname, t, ephem, path=None, link=None):
    """This function computes a solar system object position and velocity respect
    to solar system barycenter using astropy coordinates get_body_barycentric()
    method.

    The coordinate frame is that of the underlying solar system ephemeris, which
    has been the ICRF (J2000) since the DE4XX series.

    Parameters
    ----------
    objname: str
        Solar system object name. Current support solar system bodies are listed in
        astropy.coordinates.solar_system_ephemeris.bodies attribution.
    t: Astropy.time.Time object
        Observation time in Astropy.time.Time object format.
    ephem: str
        The ephem to for computing solar system object position and velocity
    path : str, optional
        Local path to the ephemeris file.
    link : str, optional
        Location of path on the internet.

    Returns
    -------
    PosVel object with 3-vectors for the position and velocity of the object
    """
    objname = objname.lower()

    load_kernel(ephem, path=path, link=link)
    pos, vel = coor.get_body_barycentric_posvel(objname, t)
    return PosVel(pos.xyz,
                  vel.xyz.to(u.km / u.second),
                  origin='ssb',
                  obj=objname)
Example #9
0
def _get_state(body, time):
    """ Computes the position of a body for a given time. """

    solar_system_bodies = [
        Sun,
        Mercury,
        Venus,
        Earth,
        Moon,
        Mars,
        Jupiter,
        Saturn,
        Uranus,
        Neptune,
        Pluto,
    ]

    # We check if body belongs to poliastro.bodies
    if body in solar_system_bodies:
        rr, vv = coord.get_body_barycentric_posvel(body.name, time)
    else:
        rr, vv = body.propagate(time).rv()
        rr = coord.CartesianRepresentation(rr)
        vv = coord.CartesianRepresentation(vv)

    return rr, vv
Example #10
0
def icrs_to_cb_crs(icrs_coord, cb_crs_frame):
    """Conversion from ICRS to Celestial Reference System of a Central Body."""

    if not u.m.is_equivalent(icrs_coord.cartesian.x.unit):
        raise u.UnitsError(
            _NEED_ORIGIN_HINT.format(icrs_coord.__class__.__name__))

    if icrs_coord.data.differentials:
        # Calculate the barycentric position and velocity (of a solar system body).
        # Uses default ephemeris
        r_icrs, v_icrs = get_body_barycentric_posvel(
            cb_crs_frame.body_name,
            cb_crs_frame.obstime,
            ephemeris=cb_crs_frame.ephemeris_type,
        )

        v_icrs = CartesianDifferential.from_cartesian(v_icrs)

        # Prepare final coord vector with velocity
        cb_crs_coord = (-r_icrs).with_differentials(-v_icrs)
    else:
        # Calculate the barycentric position ONLY (of a solar system body).
        # Uses default ephemeris. This is faster than the one above with velocities for
        # JPL ephemerides.
        cb_crs_coord = -get_body_barycentric(
            cb_crs_frame.body_name,
            cb_crs_frame.obstime,
            ephemeris=cb_crs_frame.ephemeris_type,
        )

    # Return transformation matrix (None) and translation vector (with velocities)
    return None, cb_crs_coord
Example #11
0
def get_earth_velocity(mjds, raj, decj):
    """
    Calculates the component of Earth's velocity transverse to the line of
    sight, in RA and DEC
    """

    from astropy.time import Time
    from astropy.coordinates import get_body_barycentric_posvel, SkyCoord
    from astropy import units as u
    from astropy.constants import au

    coord = SkyCoord('{0} {1}'.format(raj, decj), unit=(u.hourangle, u.deg))
    rarad = coord.ra.value * np.pi / 180
    decrad = coord.dec.value * np.pi / 180

    vearth_ra = []
    vearth_dec = []
    for mjd in mjds:
        time = Time(mjd, format='mjd')
        pos_xyz, vel_xyz = get_body_barycentric_posvel('earth', time)

        vx = vel_xyz.x.value
        vy = vel_xyz.y.value
        vz = vel_xyz.z.value

        vearth_ra.append(-vx * np.sin(rarad) + vy * np.cos(rarad))
        vearth_dec.append(-vx * np.sin(decrad) * np.cos(rarad) -
                          vy * np.sin(decrad) * np.sin(rarad) +
                          vz * np.cos(decrad))

    # Convert from AU/d to km/s
    vearth_ra = vearth_ra * au / 1e3 / 86400
    vearth_dec = vearth_dec * au / 1e3 / 86400

    return vearth_ra.value.squeeze(), vearth_dec.value.squeeze()
Example #12
0
    def to_equatorial(fixed_coo, equatorial_frame):
        assert fixed_coo.body == equatorial_frame.body

        r = fixed_coo.data.xyz
        v = fixed_coo.data.differentials["s"].d_xyz

        ra, dec, W = fixed_coo.rot_elements_at_epoch(fixed_coo.obstime)

        r = transform_vector(r, -W, "z")
        v = transform_vector(v, -W, "z")

        r_trans1 = transform_vector(r, -(90 * u.deg - dec), "x")
        r_trans2 = transform_vector(r_trans1, -(90 * u.deg + ra), "z")

        v_trans1 = transform_vector(v, -(90 * u.deg - dec), "x")
        v_trans2 = transform_vector(v_trans1, -(90 * u.deg + ra), "z")

        icrs_frame_pos_coord, icrs_frame_vel_coord = get_body_barycentric_posvel(
            fixed_coo.body.name, time=fixed_coo.obstime)

        r_f = icrs_frame_pos_coord.xyz + r_trans2
        v_f = icrs_frame_vel_coord.xyz + v_trans2

        data = CartesianRepresentation(
            r_f, differentials=CartesianDifferential(v_f))
        return equatorial_frame.realize_frame(data)
Example #13
0
    def from_equatorial(equatorial_coo, fixed_frame):
        assert equatorial_coo.body == fixed_frame.body

        r = equatorial_coo.data.xyz
        v = equatorial_coo.data.differentials["s"].d_xyz

        ra, dec, W = fixed_frame.rot_elements_at_epoch(equatorial_coo.obstime)

        icrs_frame_pos_coord, icrs_frame_vel_coord = get_body_barycentric_posvel(
            equatorial_coo.body.name, time=equatorial_coo.obstime)

        r_trans1 = r - icrs_frame_pos_coord.xyz
        r_trans2 = transform_vector(r_trans1, (90 * u.deg + ra), "z")
        r_f = transform_vector(r_trans2, (90 * u.deg - dec), "x")

        v_trans1 = v - icrs_frame_vel_coord.xyz
        v_trans2 = transform_vector(v_trans1, (90 * u.deg + ra), "z")
        v_f = transform_vector(v_trans2, (90 * u.deg - dec), "x")

        r_f = transform_vector(r_f, W, "z")
        v_f = transform_vector(v_f, W, "z")

        data = CartesianRepresentation(
            r_f, differentials=CartesianDifferential(v_f))
        return fixed_frame.realize_frame(data)
Example #14
0
    def _get_moon_altitudes(self, time, pos):
        # get current moon
        moon_loc, moon_vel = get_body_barycentric_posvel('moon', time)
        moon_loc = SkyCoord(representation_type='cartesian',
                            differential_type=CartesianDifferential,
                            unit='m',
                            frame='icrs',
                            obstime=time,
                            x=moon_loc.x,
                            y=moon_loc.y,
                            z=moon_loc.z,
                            v_x=moon_vel.x,
                            v_y=moon_vel.y,
                            v_z=moon_vel.z)
        moon = moon_loc.transform_to(GCRS(obstime=time))

        # get current receiver
        receiver_loc, receiver_vel = pos.get_gcrs_posvel(time)
        receiver = SkyCoord(representation_type='cartesian',
                            differential_type=CartesianDifferential,
                            unit='m',
                            frame='gcrs',
                            obstime=time,
                            x=receiver_loc.x,
                            y=receiver_loc.y,
                            z=receiver_loc.z,
                            v_x=receiver_vel.x,
                            v_y=receiver_vel.y,
                            v_z=receiver_vel.z)
        moon_altaz = moon.transform_to(AltAz(obstime=time, location=receiver))
        return moon_altaz.alt
Example #15
0
    def from_body_ephem(cls, body, epoch=None):
        """Return osculating `Orbit` of a body at a given time.

        """
        # TODO: https://github.com/poliastro/poliastro/issues/445
        if not epoch:
            epoch = time.Time.now().tdb
        elif epoch.scale != 'tdb':
            epoch = epoch.tdb
            warn("Input time was converted to scale='tdb' with value "
                 "{}. Use Time(..., scale='tdb') instead."
                 .format(epoch.tdb.value), TimeScaleWarning)

        r, v = get_body_barycentric_posvel(body.name, epoch)

        if body == Moon:
            # TODO: The attractor is in fact the Earth-Moon Barycenter
            icrs_cart = r.with_differentials(v.represent_as(CartesianDifferential))
            gcrs_cart = ICRS(icrs_cart).transform_to(GCRS(obstime=epoch)).represent_as(CartesianRepresentation)
            ss = cls.from_vectors(
                Earth,
                gcrs_cart.xyz.to(u.km),
                gcrs_cart.differentials['s'].d_xyz.to(u.km / u.day),
                epoch
            )

        else:
            # TODO: The attractor is not really the Sun, but the Solar System Barycenter
            ss = cls.from_vectors(Sun, r.xyz.to(u.km), v.xyz.to(u.km / u.day), epoch)
            ss._frame = ICRS()  # Hack!

        return ss
Example #16
0
def objPosVel_wrt_SSB(objname, t, ephem, path=None, link=None):
    """This function computes a solar system object position and velocity respect
    to solar system barycenter using astropy coordinates get_body_barycentric()
    method.

    The coordinate frame is that of the underlying solar system ephemeris, which
    has been the ICRF (J2000) since the DE4XX series.

    Parameters
    ----------
    objname: str
        Solar system object name. Current support solar system bodies are listed in
        astropy.coordinates.solar_system_ephemeris.bodies attribution.
    t: Astropy.time.Time object
        Observation time in Astropy.time.Time object format.
    ephem: str
        The ephem to for computing solar system object position and velocity
    path: str optional
        The data directory point to a local ephemeris.
    link: str optional
        The link where to download the ephemeris.

    Returns
    -------
    PosVel object with 3-vectors for the position and velocity of the object

    Note
    ----
    If both path and link are provided. Path will be first to try.
    """
    ephem = ephem.lower()
    objname = objname.lower()
    # Use astropy to compute postion.
    # If a local path is provided, the local search will be considered first.
    # If the path is not provided, try link first, then local data file.
    if path is None:
        if link is None:
            link_str = ''
        else:
            link_str = link
        is_load = _load_kernel_link(ephem, link=link_str)
        if not is_load:  # Link does not Try to load from data path.
            path_str = ''
            is_load = _load_kernel_local(ephem, path=path_str)
        if not is_load:
            raise ValueError("Can not load the ephemeris file '%s.bsp'. " %
                             ephem)
    else:
        path_str = path
        is_load = _load_kernel_local(ephem, path=path_str)
        if not is_load:
            raise ValueError(
                "Can not load the ephemeris file '%s.bsp' from the"
                " local directory %s." % (ephem, path_str))
    pos, vel = coor.get_body_barycentric_posvel(objname, t)
    return PosVel(pos.xyz,
                  vel.xyz.to(u.km / u.second),
                  origin='ssb',
                  obj=objname)
Example #17
0
 def get_barycentric_vel(self, t, t0=None, tformat=None):
     if tformat is None:
         tformat = self.unitc.tname
     if tformat == 'jd' and t0 is None:
         t0 = 2451545  # jan 1 2000 in jd
     t_ = Time(t + t0, format=tformat)
     vel = get_body_barycentric_posvel(self.name, t_)[1].xyz.to(
         self.unitc.vname).to_value()
     return vel
Example #18
0
def get_body(times, body, savefile=False):
    tab = Table()
    t= Table(names=['utc', 'jd', 'x', 'y', 'z', 'd', 'vx', 'vy', 'vz', 'v'], dtype=['S32', 'f16', 'f16', 'f16', 'f16', 'f16', 'f16', 'f16', 'f16', 'f16'])
    for time in times:
        pos, vel = get_body_barycentric_posvel(body, time, ephemeris='de430')
        t.add_row([time.value, time.jd, pos.x.value, pos.y.value, pos.z.value, pos.norm().value, vel.x.value/(u.day.to(u.second)), vel.y.value/(u.day.to(u.second)), vel.z.value/(u.day.to(u.second)), vel.norm().value/(u.day.to(u.second))]) 
    if savefile==True:
        t.write('/home/akash/results/{b}_Ephemeride.txt'.format(b=body), format='ascii', delimiter='\t', overwrite=True)
    return t
Example #19
0
    def __call__(self, t, u_, k):
        # Solve for primary and secondary bodies position w.r.t. solar system
        # barycenter at a particular epoch.
        (r_primary_wrt_ssb, _), (r_secondary_wrt_ssb, _) = [
            get_body_barycentric_posvel(body.name, self._epoch + t * u.s)
            for body in (self._primary_body, self._secondary_body)
        ]
        r_sec = ((r_secondary_wrt_ssb - r_primary_wrt_ssb).xyz << u.km).value

        return r_sec
Example #20
0
def objPosVel_wrt_SSB(objname, t, ephem, path=None, link=None):
    """This function computes a solar system object position and velocity respect
    to solar system barycenter using astropy coordinates get_body_barycentric()
    method.

    The coordinate frame is that of the underlying solar system ephemeris, which
    has been the ICRF (J2000) since the DE4XX series.

    Parameters
    ----------
    objname: str
        Solar system object name. Current support solar system bodies are listed in
        astropy.coordinates.solar_system_ephemeris.bodies attribution.
    t: Astropy.time.Time object
        Observation time in Astropy.time.Time object format.
    ephem: str
        The ephem to for computing solar system object position and velocity
    path: str optional
        The data directory point to a local ephemeris.
    link: str optional
        The link where to download the ephemeris.

    Returns
    -------
    PosVel object with 3-vectors for the position and velocity of the object

    Note
    ----
    If both path and link are provided. Path will be first to try.
    """
    ephem = ephem.lower()
    objname = objname.lower()
    # Use astropy to compute postion.
    # If a local path is provided, the local search will be considered first.
    # If the path is not provided, try link first, then local data file.
    if path is None:
        if link is None:
            link_str = ''
        else:
            link_str = link
        is_load = _load_kernel_link(ephem, link=link_str)
        if not is_load: # Link does not Try to load from data path.
            path_str = ''
            is_load = _load_kernel_local(ephem, path=path_str)
        if not is_load:
            raise ValueError("Can not load the ephemeris file '%s.bsp'. " % ephem)
    else:
        path_str = path
        is_load = _load_kernel_local(ephem, path=path_str)
        if not is_load:
            raise ValueError("Can not load the ephemeris file '%s.bsp' from the"
                             " local directory %s." % (ephem, path_str))
    pos, vel = coor.get_body_barycentric_posvel(objname, t)
    return PosVel(pos.xyz, vel.xyz.to(u.km/u.second), origin='ssb', obj=objname)
Example #21
0
    def get_coord_list(self, time_list, velocity=False, ephemeris="builtin"):
        """
        Computes the set of positions (and velocities, if requested) of the Celestial
        Body in the `ICRS` frame. Any further frame transformations can then be carried
        out.

        Default ephemeris is `builtin`, though it cannot compute the velocity for
        the Moon. Ephemeris can also be `jpl`, where the default implementation in
        Astropy is used. Be warned that the first time this is called, a large file
        has to be downloaded.

        Parameters
        ----------
        time_list : `~astropy.time.Time`
            List of times where position output is requested
        velocity : bool
            True if velocities are of the celestial body is also requested
        ephemeris : str, optional
            Ephemeris to use.  By default, use the one set with
            ``astropy.coordinates.solar_system_ephemeris.set``

        Returns
        -------
        SkyCoord
            Set of cartesian positions (and velocities) in a `SkyCoord` object

        """
        if velocity:
            r, v = get_body_barycentric_posvel(self.name,
                                               time_list,
                                               ephemeris=ephemeris)
            v_body = CartesianDifferential(v.xyz)
            r_body = r.with_differentials(v_body)

            coord_list = SkyCoord(
                r_body.with_differentials(v_body),
                obstime=time_list,
                frame="icrs",
                representation_type="cartesian",
                differential_type="cartesian",
            )

        else:
            coord_list = SkyCoord(
                get_body_barycentric(self.name, time_list,
                                     ephemeris=ephemeris),
                obstime=time_list,
                frame="icrs",
                representation_type="cartesian",
                differential_type="cartesian",
            )

        return coord_list
Example #22
0
    def from_body_ephem(cls, body, epoch=None):
        """Return osculating `Orbit` of a body at a given time.

        """
        from poliastro.bodies import Earth, Moon, Sun

        warn(
            "Orbit.from_body_ephem is deprecated and will be removed in a future release, "
            "see https://github.com/poliastro/poliastro/issues/445 for discussion.",
            DeprecationWarning,
            stacklevel=2,
        )

        if not epoch:
            epoch = time.Time.now().tdb
        elif epoch.scale != "tdb":
            epoch = epoch.tdb
            warn(
                "Input time was converted to scale='tdb' with value "
                f"{epoch.tdb.value}. Use Time(..., scale='tdb') instead.",
                TimeScaleWarning,
                stacklevel=2,
            )
        try:
            r, v = get_body_barycentric_posvel(body.name, epoch)
        except KeyError as exc:
            raise RuntimeError(
                """To compute the position and velocity of the Moon and Pluto use the JPL ephemeris:

>>> from astropy.coordinates import solar_system_ephemeris
>>> solar_system_ephemeris.set('jpl')
""") from exc
        if body == Moon:
            # TODO: The attractor is in fact the Earth-Moon Barycenter
            icrs_cart = r.with_differentials(
                v.represent_as(CartesianDifferential))
            gcrs_cart = (ICRS(icrs_cart).transform_to(
                GCRS(obstime=epoch)).represent_as(CartesianRepresentation))
            ss = cls.from_vectors(
                Earth,
                gcrs_cart.xyz.to(u.km),
                gcrs_cart.differentials["s"].d_xyz.to(u.km / u.day),
                epoch,
            )

        else:
            # TODO: The attractor is not really the Sun, but the Solar System
            # Barycenter
            ss = cls.from_vectors(Sun, r.xyz.to(u.km), v.xyz.to(u.km / u.day),
                                  epoch)
            ss._frame = ICRS()  # Hack!

        return ss
Example #23
0
def transit(date, date_arrival, planet1, planet2):
    #czas trwania misji
    tof = date_arrival - date
    N = 50
    tof.to(u.h)
    times_vector = time_range(date, end=date_arrival, periods=N)

    # okreslenie pozycji planet w przedziale czasu: od startu do końca misji
    rr_planet1, vv_planet1 = get_body_barycentric_posvel(planet1, times_vector)
    rr_planet2, vv_planet2 = get_body_barycentric_posvel(planet2, times_vector)

    r0 = rr_planet1[0].xyz  #wektor pozycji Ziemi w momencie startu
    v0 = vv_planet1[0].xyz  #wektor predkosci Ziemi w momencie startu
    rf = rr_planet2[
        -1].xyz  #wektor pozycji planety docelowej w momencie końca misji
    vf = vv_planet2[
        -1].xyz  #wektor predkosci planety docelowej w momencie końca misji

    # rozwiazanie problemu Lamberta
    (va, vb), = iod.lambert(Sun.k, r0, rf, tof, numiter=1000)

    return (r0, v0, rf, vf, va, vb, rr_planet1, rr_planet2, times_vector)
Example #24
0
    def from_body_ephem(cls, body, epoch=None):
        """Return osculating `Orbit` of a body at a given time.

        """
        if not epoch:
            epoch = time.Time.now().tdb
        elif epoch.scale != 'tdb':
            epoch = epoch.tdb
            warn("Input time was converted to scale='tdb' with value "
                 "{}. Use Time(..., scale='tdb') instead."
                 .format(epoch.tdb.value), TimeScaleWarning)

        r, v = get_body_barycentric_posvel(body.name, epoch)
        return cls.from_vectors(body.parent, r.xyz.to(u.km), v.xyz.to(u.km / u.day), epoch)
Example #25
0
def test_velocity_hcrs_hgs():
    # Obtain the position/velocity of Earth in ICRS
    obstime = Time(['2019-01-01', '2019-04-01', '2019-07-01', '2019-10-01'])
    pos, vel = get_body_barycentric_posvel('earth', obstime)
    loc = pos.with_differentials(vel.represent_as(CartesianDifferential))
    earth = SkyCoord(loc, frame='icrs', obstime=obstime)

    # The velocity of Earth in HGS Y should be very close to zero because the XZ plane tracks
    # the Earth.
    new = earth.heliographic_stonyhurst
    assert_quantity_allclose(new.velocity.d_y, 0*u.km/u.s, atol=1e-5*u.km/u.s)

    # Test the loopback to ICRS
    newer = new.icrs
    assert_quantity_allclose(newer.velocity.d_xyz, vel.xyz)
Example #26
0
def body_centered_to_icrs(r,
                          v,
                          source_body,
                          epoch=J2000,
                          rotate_meridian=False):
    """Converts position and velocity body-centered frame to ICRS.

    Parameters
    ----------
    r : ~astropy.units.Quantity
        Position vector in a body-centered reference frame.
    v : ~astropy.units.Quantity
        Velocity vector in a body-centered reference frame.
    source_body : Body
        Source body.
    epoch : ~astropy.time.Time, optional
        Epoch, default to J2000.
    rotate_meridian : bool, optional
        Whether to apply the rotation of the meridian too, default to False.

    Returns
    -------
    r, v : tuple (~astropy.units.Quantity)
        Position and velocity vectors in ICRS.


    """

    ra, dec, W = source_body.rot_elements_at_epoch(epoch)
    if rotate_meridian:
        r = transform(r, -W, 'z')
        v = transform(v, -W, 'z')

    r_trans1 = transform(r, -(90 * u.deg - dec), 'x')
    r_trans2 = transform(r_trans1, -(90 * u.deg + ra), 'z')

    v_trans1 = transform(v, -(90 * u.deg - dec), 'x')
    v_trans2 = transform(v_trans1, -(90 * u.deg + ra), 'z')

    icrs_frame_pos_coord, icrs_frame_vel_coord = get_body_barycentric_posvel(
        source_body.name, time=epoch)

    r_f = icrs_frame_pos_coord.xyz + r_trans2
    v_f = icrs_frame_vel_coord.xyz + v_trans2

    return r_f.to(r.unit), v_f.to(v.unit)
Example #27
0
def icrs_to_body_centered(r,
                          v,
                          target_body,
                          epoch=J2000,
                          rotate_meridian=False):
    """Converts position and velocity in ICRS to body-centered frame.

    Parameters
    ----------
    r : ~astropy.units.Quantity
        Position vector in ICRS.
    v : ~astropy.units.Quantity
        Velocity vector in ICRS.
    target_body : Body
        Target body.
    epoch : ~astropy.time.Time, optional
        Epoch, default to J2000.
    rotate_meridian : bool, optional
        Whether to apply the rotation of the meridian too, default to False.

    Returns
    -------
    r, v : tuple (~astropy.units.Quantity)
        Position and velocity vectors in a body-centered reference frame.

    """

    ra, dec, W = target_body.rot_elements_at_epoch(epoch)

    icrs_frame_pos_coord, icrs_frame_vel_coord = get_body_barycentric_posvel(
        target_body.name, time=epoch)

    r_trans1 = r - icrs_frame_pos_coord.xyz
    r_trans2 = transform(r_trans1, (90 * u.deg + ra), 'z')
    r_f = transform(r_trans2, (90 * u.deg - dec), 'x')

    v_trans1 = v - icrs_frame_vel_coord.xyz
    v_trans2 = transform(v_trans1, (90 * u.deg + ra), 'z')
    v_f = transform(v_trans2, (90 * u.deg - dec), 'x')

    if rotate_meridian:
        r_f = transform(r_f, W, 'z')
        v_f = transform(v_f, W, 'z')

    return r_f.to(r.unit), v_f.to(v.unit)
Example #28
0
    def from_body(cls,
                  body,
                  epochs,
                  *,
                  attractor=None,
                  plane=Planes.EARTH_EQUATOR):
        """Return `Ephem` for a `SolarSystemPlanet` at certain epochs.

        Parameters
        ----------
        body: ~poliastro.bodies.SolarSystemPlanet
            Body.
        epochs: ~astropy.time.Time
            Epochs to sample the body positions.
        attractor : ~poliastro.bodies.SolarSystemPlanet, optional
            Body to use as central location,
            if not given the Solar System Barycenter will be used.
        plane : ~poliastro.frames.Planes, optional
            Fundamental plane of the frame, default to Earth Equator.

        """
        if epochs.isscalar:
            epochs = epochs.reshape(1)

        if epochs.scale != "tdb":
            epochs = epochs.tdb
            warn(
                "Input time was converted to scale='tdb' with value "
                f"{epochs.tdb.value}. Use Time(..., scale='tdb') instead.",
                TimeScaleWarning,
                stacklevel=2,
            )

        r, v = get_body_barycentric_posvel(body.name, epochs)
        coordinates = r.with_differentials(
            v.represent_as(CartesianDifferential))

        destination_frame = _get_destination_frame(attractor, plane, epochs)

        if destination_frame is not None:
            coordinates = (
                ICRS(coordinates).transform_to(destination_frame).represent_as(
                    CartesianRepresentation, CartesianDifferential))

        return cls(coordinates, epochs, plane)
def test_spectral_coord_jupiter():
    """
    Checks radial velocity between Earth and Jupiter
    """
    obstime = time.Time('2018-12-13 9:00')
    obs = get_greenwich_earthlocation().get_gcrs(obstime)

    pos, vel = get_body_barycentric_posvel('jupiter', obstime)
    jupiter = SkyCoord(pos.with_differentials(CartesianDifferential(vel.xyz)),
                       obstime=obstime)

    spc = SpectralCoord([100, 200, 300] * u.nm, observer=obs, target=jupiter)

    # The velocity should be less than ~43 + a bit extra, which is the
    # maximum possible earth-jupiter relative velocity. We check the exact
    # value here (determined from SpectralCoord, so this serves as a test to
    # check that this value doesn't change - the value is not a ground truth)
    assert_quantity_allclose(spc.radial_velocity, -7.35219854 * u.km / u.s)
Example #30
0
    def to_icrs(planet_coo, _):
        # this is just an origin translation so without a distance it cannot go ahead
        if isinstance(planet_coo.data, UnitSphericalRepresentation):
            raise u.UnitsError(
                _NEED_ORIGIN_HINT.format(planet_coo.__class__.__name__))

        if planet_coo.data.differentials:
            bary_sun_pos, bary_sun_vel = get_body_barycentric_posvel(
                planet_coo.body.name, planet_coo.obstime)
            bary_sun_pos = bary_sun_pos.with_differentials(
                bary_sun_vel.represent_as(CartesianDifferential))

        else:
            bary_sun_pos = get_body_barycentric(planet_coo.body.name,
                                                planet_coo.obstime)
            bary_sun_vel = None

        return None, bary_sun_pos
Example #31
0
def R(time, vel=False):
    # R is the position vector of Earth
    # requires an astropy Time object
    # returns R, a three component array describing the position vector of Earth
    # in au
    _R, _Rdot = get_body_barycentric_posvel('earth', time, ephemeris='jpl')
    c = vector(
        _R.x.to(u.AU) / u.AU,
        _R.y.to(u.AU) / u.AU,
        _R.z.to(u.AU) / u.AU)
    if vel:
        d = vector(
            _Rdot.x.to(u.AU / u.d) / (u.AU / u.d),
            _Rdot.y.to(u.AU / u.d) / (u.AU / u.d),
            _Rdot.z.to(u.AU / u.d) / (u.AU / u.d))
        return c, d
    else:
        return c
Example #32
0
def compute_l2_pos_and_vel(time0: astropy.time.Time,
                           earth_l2_distance_km: float = EARTH_L2_DISTANCE_KM):
    """
    Compute the position and velocity of the L2 Sun-Earth point at a given time.

    The L2 point is not calculated using Lagrange's equations; instead, its
    distance from the Earth must be provided as the parameter `earth_l2_distance_km`.
    The default value is a reasonable estimate. The L2 point is assumed to lie along
    the line that connects the Solar System Barycenter with the Earth's gravitational
    center.

    The return value is a 2-tuple containing two NumPy arrays:

    1. A 3D array containing the XYZ components of the vector specifying the position
       of the L2 point, in km
    2. A 3D array containing the XYZ components of the velocity vector of the L2 point,
       in km/s

    The two vectors are always roughly perpendicular, but they are not exactly due to
    the irregular motion of the Earth (caused by gravitational interactions with other
    Solar System bodies, like the Moon and Jupiter).
    """
    # Use
    #
    #    solar_system_ephemeris.set("builtin")
    #
    # to make AstroPy use the built-in ephemeris table

    earth_pos, earth_vel = get_body_barycentric_posvel("earth", time0)
    earth_pos = ICRS(earth_pos).transform_to(
        DEFAULT_COORDINATE_SYSTEM).cartesian
    earth_vel = ICRS(earth_vel).transform_to(
        DEFAULT_COORDINATE_SYSTEM).cartesian

    fudge_factor = earth_l2_distance_km / earth_pos.norm().to("km").value

    # Move from Earth to L2
    l2_pos = earth_pos * (1.0 + fudge_factor)
    l2_vel = earth_vel * (1.0 + fudge_factor)

    return (
        l2_pos.xyz.to("km").value.transpose(),
        l2_vel.xyz.to("km/s").value.transpose(),
    )
Example #33
0
    def from_icrs(icrs_coo, planet_frame):
        # this is just an origin translation so without a distance it cannot go ahead
        if isinstance(icrs_coo.data, UnitSphericalRepresentation):
            raise u.UnitsError(
                _NEED_ORIGIN_HINT.format(icrs_coo.__class__.__name__))

        if icrs_coo.data.differentials:
            bary_sun_pos, bary_sun_vel = get_body_barycentric_posvel(
                planet_frame.body.name, planet_frame.obstime)
            # Beware! Negation operation is not supported for differentials
            bary_sun_pos = (-bary_sun_pos).with_differentials(
                -bary_sun_vel.represent_as(CartesianDifferential))

        else:
            bary_sun_pos = -get_body_barycentric(planet_frame.body.name,
                                                 planet_frame.obstime)
            bary_sun_vel = None

        return None, bary_sun_pos
Example #34
0
    def from_body_ephem(cls, body, epoch=None):
        """Return osculating `Orbit` of a body at a given time.

        """
        # TODO: https://github.com/poliastro/poliastro/issues/445
        if not epoch:
            epoch = time.Time.now().tdb
        elif epoch.scale != "tdb":
            epoch = epoch.tdb
            warn(
                "Input time was converted to scale='tdb' with value "
                "{}. Use Time(..., scale='tdb') instead.".format(epoch.tdb.value),
                TimeScaleWarning,
            )
        try:
            r, v = get_body_barycentric_posvel(body.name, epoch)
        except KeyError:
            raise RuntimeError(
                "To compute the position and velocity of the Moon and Pluto use the JPL ephemeris:\n>>>from astropy.coordinates import solar_system_ephemeris\n>>>solar_system_ephemeris.set('jpl')"
            )
        if body == Moon:
            # TODO: The attractor is in fact the Earth-Moon Barycenter
            icrs_cart = r.with_differentials(v.represent_as(CartesianDifferential))
            gcrs_cart = (
                ICRS(icrs_cart)
                .transform_to(GCRS(obstime=epoch))
                .represent_as(CartesianRepresentation)
            )
            ss = cls.from_vectors(
                Earth,
                gcrs_cart.xyz.to(u.km),
                gcrs_cart.differentials["s"].d_xyz.to(u.km / u.day),
                epoch,
            )

        else:
            # TODO: The attractor is not really the Sun, but the Solar System
            # Barycenter
            ss = cls.from_vectors(Sun, r.xyz.to(u.km), v.xyz.to(u.km / u.day), epoch)
            ss._frame = ICRS()  # Hack!

        return ss
Example #35
0
    def to_icrs(planet_coo, _):
        # this is just an origin translation so without a distance it cannot go ahead
        if isinstance(planet_coo.data, UnitSphericalRepresentation):
            raise u.UnitsError(_NEED_ORIGIN_HINT.format(planet_coo.__class__.__name__))

        if planet_coo.data.differentials:
            bary_sun_pos, bary_sun_vel = get_body_barycentric_posvel(
                planet_coo.body.name, planet_coo.obstime
            )
            bary_sun_pos = bary_sun_pos.with_differentials(
                bary_sun_vel.represent_as(CartesianDifferential)
            )

        else:
            bary_sun_pos = get_body_barycentric(
                planet_coo.body.name, planet_coo.obstime
            )
            bary_sun_vel = None

        return None, bary_sun_pos
Example #36
0
def body_centered_to_icrs(r, v, source_body, epoch=J2000, rotate_meridian=False):
    """Converts position and velocity body-centered frame to ICRS.

    Parameters
    ----------
    r : ~astropy.units.Quantity
        Position vector in a body-centered reference frame.
    v : ~astropy.units.Quantity
        Velocity vector in a body-centered reference frame.
    source_body : Body
        Source body.
    epoch : ~astropy.time.Time, optional
        Epoch, default to J2000.
    rotate_meridian : bool, optional
        Whether to apply the rotation of the meridian too, default to False.

    Returns
    -------
    r, v : tuple (~astropy.units.Quantity)
        Position and velocity vectors in ICRS.


    """

    ra, dec, W = source_body.rot_elements_at_epoch(epoch)
    if rotate_meridian:
        r = transform_vector(r, -W, 'z')
        v = transform_vector(v, -W, 'z')

    r_trans1 = transform_vector(r, -(90 * u.deg - dec), 'x')
    r_trans2 = transform_vector(r_trans1, -(90 * u.deg + ra), 'z')

    v_trans1 = transform_vector(v, -(90 * u.deg - dec), 'x')
    v_trans2 = transform_vector(v_trans1, -(90 * u.deg + ra), 'z')

    icrs_frame_pos_coord, icrs_frame_vel_coord = get_body_barycentric_posvel(source_body.name, time=epoch)

    r_f = icrs_frame_pos_coord.xyz + r_trans2
    v_f = icrs_frame_vel_coord.xyz + v_trans2

    return r_f.to(r.unit), v_f.to(v.unit)
Example #37
0
    def from_icrs(icrs_coo, planet_frame):
        # this is just an origin translation so without a distance it cannot go ahead
        if isinstance(icrs_coo.data, UnitSphericalRepresentation):
            raise u.UnitsError(_NEED_ORIGIN_HINT.format(icrs_coo.__class__.__name__))

        if icrs_coo.data.differentials:
            bary_sun_pos, bary_sun_vel = get_body_barycentric_posvel(
                planet_frame.body.name, planet_frame.obstime
            )
            # Beware! Negation operation is not supported for differentials
            bary_sun_pos = (-bary_sun_pos).with_differentials(
                -bary_sun_vel.represent_as(CartesianDifferential)
            )

        else:
            bary_sun_pos = -get_body_barycentric(
                planet_frame.body.name, planet_frame.obstime
            )
            bary_sun_vel = None

        return None, bary_sun_pos
Example #38
0
def icrs_to_body_centered(r, v, target_body, epoch=J2000, rotate_meridian=False):
    """Converts position and velocity in ICRS to body-centered frame.

    Parameters
    ----------
    r : ~astropy.units.Quantity
        Position vector in ICRS.
    v : ~astropy.units.Quantity
        Velocity vector in ICRS.
    target_body : Body
        Target body.
    epoch : ~astropy.time.Time, optional
        Epoch, default to J2000.
    rotate_meridian : bool, optional
        Whether to apply the rotation of the meridian too, default to False.

    Returns
    -------
    r, v : tuple (~astropy.units.Quantity)
        Position and velocity vectors in a body-centered reference frame.

    """

    ra, dec, W = target_body.rot_elements_at_epoch(epoch)

    icrs_frame_pos_coord, icrs_frame_vel_coord = get_body_barycentric_posvel(target_body.name, time=epoch)

    r_trans1 = r - icrs_frame_pos_coord.xyz
    r_trans2 = transform_vector(r_trans1, (90 * u.deg + ra), 'z')
    r_f = transform_vector(r_trans2, (90 * u.deg - dec), 'x')

    v_trans1 = v - icrs_frame_vel_coord.xyz
    v_trans2 = transform_vector(v_trans1, (90 * u.deg + ra), 'z')
    v_f = transform_vector(v_trans2, (90 * u.deg - dec), 'x')

    if rotate_meridian:
        r_f = transform_vector(r_f, W, 'z')
        v_f = transform_vector(v_f, W, 'z')

    return r_f.to(r.unit), v_f.to(v.unit)
        Exception("Could not parse time interval: {}".format(args.interval))

    # set the end time
    try:
        endtime = Time(starttime.decimalyear + args.nyears, format='decimalyear', scale='utc') + dt
    except ValueError:
        Exception("Could not parse total timespan")

    pos = []
    vel = []
    acc = []

    # get positions, velocities and accelerations
    curtime = starttime
    while curtime <= endtime:
        tpos, tvel = get_body_barycentric_posvel(body, curtime)

        # convert positions to light seconds
        pos.append(tpos.xyz.to('m')/const.c)

        # convert velocities to light seconds per second
        vel.append(tvel.xyz.to('m/s')/const.c)

        # calculate accelerations (using velocities +/- dt/2 around the current time)
        ctminus = curtime - dt/2.
        _, mvel = get_body_barycentric_posvel(body, ctminus)
        ctplus = curtime + dt/2.
        _, pvel = get_body_barycentric_posvel(body, ctplus)    
        acc.append(((pvel.xyz.to('m/s')-mvel.xyz.to('m/s'))/const.c)/dt.to('s'))

        curtime += dt