Exemple #1
0
def get_mean_elements(body, epoch=J2000):
    """Get ecliptic mean elements of body.

    Parameters
    ----------
    body : ~poliastro.bodies.SolarSystemPlanet
        Body.
    epoch : astropy.time.Time
        Epoch.

    """
    # Internally, erfa.plan94 has a table of classical elements,
    # which are then converted to position and velocity...
    # So we are reverting the conversion in the last line
    # This way at least we avoid copy pasting the values
    try:
        name = body.name.lower()

        if name == "earth":
            name = "earth-moon-barycenter"

        body_index = PLAN94_BODY_NAME_TO_PLANET_INDEX[name]
        body_pv_helio = erfa.plan94(epoch.jd1, epoch.jd2, body_index)

        r = body_pv_helio["p"] * u.au
        v = body_pv_helio["v"] * u.au / u.day

    except KeyError as e:
        raise ValueError(
            f"No available mean elements for {body}. It must be an instance of `poliastro.bodies.SolarSystemPlanet`"
        ) from e

    return RVState(body.parent, r, v, plane=Planes.EARTH_ECLIPTIC).to_classical()
Exemple #2
0
    def __init__(self, utc, longitude, latitude, altitude):
        try:
            super().__init__(utc, longitude, latitude, altitude)
        except TypeError:
            super(Ephem, self).__init__(utc, longitude, latitude, altitude)
        # julian centuries at the given UTC
        self.jc = (self.tdb1+self.tdb2-erfa.DJ00)/erfa.DJC
        # heliocentric position of major bodies
        self.p94 = [erfa.plan94(self.tdb1, self.tdb2, i) for i in range(1,9)]
        # Earth heliocentric position and velocity
        self.eph, self.epb = erfa.epv00(self.tdb1, self.tdb2)

        self.distances_from_earth = {}
        self.RA_DEC = {}

##        # precession angles
##        eps0,psia,oma,bpa,bqa,pia,bpia,epsa,chia,za,zetaa,thetaa,pa,gam,phi,psi = erfa.p06e(self.tt1, self.tt2)
##
##        # Fundamental argument of major bodies
##        mer = erfa.fame03(self.jc))
        self.sun()
        self.planets()
Exemple #3
0
def _get_body_barycentric_posvel(body,
                                 time,
                                 ephemeris=None,
                                 get_velocity=True):
    """Calculate the barycentric position (and velocity) of a solar system body.

    Parameters
    ----------
    body : str or other
        The solar system body for which to calculate positions.  Can also be a
        kernel specifier (list of 2-tuples) if the ``ephemeris`` is a JPL
        kernel.
    time : `~astropy.time.Time`
        Time of observation.
    ephemeris : str, optional
        Ephemeris to use.  By default, use the one set with
        ``astropy.coordinates.solar_system_ephemeris.set``
    get_velocity : bool, optional
        Whether or not to calculate the velocity as well as the position.

    Returns
    -------
    position : `~astropy.coordinates.CartesianRepresentation` or tuple
        Barycentric (ICRS) position or tuple of position and velocity.

    Notes
    -----
    No velocity can be calculated with the built-in ephemeris for the Moon.

    Whether or not velocities are calculated makes little difference for the
    built-in ephemerides, but for most JPL ephemeris files, the execution time
    roughly doubles.
    """

    if ephemeris is None:
        ephemeris = solar_system_ephemeris.get()
        if ephemeris is None:
            raise ValueError(_EPHEMERIS_NOTE)
        kernel = solar_system_ephemeris.kernel
    else:
        kernel = _get_kernel(ephemeris)

    jd1, jd2 = get_jd12(time, 'tdb')
    if kernel is None:
        body = body.lower()
        earth_pv_helio, earth_pv_bary = erfa.epv00(jd1, jd2)
        if body == 'earth':
            body_pv_bary = earth_pv_bary

        elif body == 'moon':
            if get_velocity:
                raise KeyError("the Moon's velocity cannot be calculated with "
                               "the '{}' ephemeris.".format(ephemeris))
            return calc_moon(time).cartesian

        else:
            sun_pv_bary = erfa.pvmpv(earth_pv_bary, earth_pv_helio)
            if body == 'sun':
                body_pv_bary = sun_pv_bary
            else:
                try:
                    body_index = PLAN94_BODY_NAME_TO_PLANET_INDEX[body]
                except KeyError:
                    raise KeyError(
                        "{}'s position and velocity cannot be "
                        "calculated with the '{}' ephemeris.".format(
                            body, ephemeris))
                body_pv_helio = erfa.plan94(jd1, jd2, body_index)
                body_pv_bary = erfa.pvppv(body_pv_helio, sun_pv_bary)

        body_pos_bary = CartesianRepresentation(body_pv_bary['p'],
                                                unit=u.au,
                                                xyz_axis=-1,
                                                copy=False)
        if get_velocity:
            body_vel_bary = CartesianRepresentation(body_pv_bary['v'],
                                                    unit=u.au / u.day,
                                                    xyz_axis=-1,
                                                    copy=False)

    else:
        if isinstance(body, str):
            # Look up kernel chain for JPL ephemeris, based on name
            try:
                kernel_spec = BODY_NAME_TO_KERNEL_SPEC[body.lower()]
            except KeyError:
                raise KeyError("{}'s position cannot be calculated with "
                               "the {} ephemeris.".format(body, ephemeris))
        else:
            # otherwise, assume the user knows what their doing and intentionally
            # passed in a kernel chain
            kernel_spec = body

        # jplephem cannot handle multi-D arrays, so convert to 1D here.
        jd1_shape = getattr(jd1, 'shape', ())
        if len(jd1_shape) > 1:
            jd1, jd2 = jd1.ravel(), jd2.ravel()
        # Note that we use the new jd1.shape here to create a 1D result array.
        # It is reshaped below.
        body_posvel_bary = np.zeros((2 if get_velocity else 1, 3) +
                                    getattr(jd1, 'shape', ()))
        for pair in kernel_spec:
            spk = kernel[pair]
            if spk.data_type == 3:
                # Type 3 kernels contain both position and velocity.
                posvel = spk.compute(jd1, jd2)
                if get_velocity:
                    body_posvel_bary += posvel.reshape(body_posvel_bary.shape)
                else:
                    body_posvel_bary[0] += posvel[:4]
            else:
                # spk.generate first yields the position and then the
                # derivative. If no velocities are desired, body_posvel_bary
                # has only one element and thus the loop ends after a single
                # iteration, avoiding the velocity calculation.
                for body_p_or_v, p_or_v in zip(body_posvel_bary,
                                               spk.generate(jd1, jd2)):
                    body_p_or_v += p_or_v

        body_posvel_bary.shape = body_posvel_bary.shape[:2] + jd1_shape
        body_pos_bary = CartesianRepresentation(body_posvel_bary[0],
                                                unit=u.km,
                                                copy=False)
        if get_velocity:
            body_vel_bary = CartesianRepresentation(body_posvel_bary[1],
                                                    unit=u.km / u.day,
                                                    copy=False)

    return (body_pos_bary, body_vel_bary) if get_velocity else body_pos_bary