Exemplo n.º 1
0
def test_raan_from_ltan_sentinel5p():
    # SENTINEL-5P LTAN: 13:30
    # LTAN from https://sentinels.copernicus.eu/web/sentinel/missions/sentinel-5p/geographical-coverage
    # 1 42969U 17064A   20049.78099017 -.00000032  00000-0  54746-5 0  9991
    # 2 42969  98.7249 350.5997 0001077  82.0109 278.1189 14.19549365121775

    ltan = (13 + (30 / 60)) * u.hourangle
    epoch = astropy.time.Time(
        astropy.time.Time("2020-01-01 00:00").to_value("mjd") + 49.78099017 - 1,
        format="mjd",
    )
    expected_raan = 350.5997 * u.deg
    raan = angles.raan_from_ltan(epoch, ltan)
    assert_allclose(raan.wrap_at(360 * u.deg).to(u.deg), expected_raan, atol=0.3)
Exemplo n.º 2
0
def test_raan_from_ltan_metopb():
    # MetOp-B LTAN: 21:31:45
    # LTAN from https://www.ospo.noaa.gov/Operations/METOP/status.html
    # METOP-B
    # 1 38771U 12049A   20049.95408566 -.00000014  00000-0  13607-4 0  9997
    # 2 38771  98.7092 110.9899 0001263  48.5458 295.8781 14.21485930385043

    ltan = (21 + ((31 + 45 / 60) / 60)) * u.hourangle
    epoch = astropy.time.Time(
        astropy.time.Time("2020-01-01 00:00").to_value("mjd") + 49.95408566 - 1,
        format="mjd",
    )
    expected_raan = 110.9899 * u.deg
    raan = angles.raan_from_ltan(epoch, ltan)
    assert_allclose(raan.wrap_at(360 * u.deg).to(u.deg), expected_raan, atol=0.3)
Exemplo n.º 3
0
    def heliosynchronous(
        cls,
        attractor,
        a=None,
        ecc=None,
        inc=None,
        ltan=10.0 * u.hourangle,
        argp=0 * u.deg,
        nu=0 * u.deg,
        epoch=J2000,
        plane=Planes.EARTH_EQUATOR,
    ):
        r""" Solves for a Sun-Synchronous orbit. These orbits make use of the J2
        perturbation to precess in order to be always towards Sun. At least
        two parameters of the set {a, ecc, inc} are needed in order to solve
        for these kind of orbits. Relationships among them are given by:

        .. math::
            \begin{align}
                a &= \left (\frac{-3R_{\bigoplus}J_{2}\sqrt{\mu}\cos(i)}{2\dot{\Omega}(1-e^2)^2}  \right ) ^ {\frac{2}{7}}\\
                e &= \sqrt{1 - \sqrt{\frac{-3R_{\bigoplus}J_{2}\sqrt{\mu}cos(i)}{2a^{\frac{7}{2}}\dot{\Omega}}}}\\
                i &= \arccos{\left ( \frac{-2a^{\frac{7}{2}}\dot{\Omega}(1-e^2)^2}{3R_{\bigoplus}J_{2}\sqrt{\mu}} \right )}\\
            \end{align}

        Parameters
        ----------
        a: ~astropy.units.Quantity
            Semi-major axis.
        ecc: ~astropy.units.Quantity
            Eccentricity.
        inc: ~astropy.units.Quantity
            Inclination.
        ltan: ~astropy.units.Quantity
            Local time of the ascending node which will be translated to the Right ascension of the ascending node.
        argp : ~astropy.units.Quantity
            Argument of the pericenter.
        nu : ~astropy.units.Quantity
            True anomaly.
        epoch : ~astropy.time.Time, optional
            Epoch, default to J2000.
        plane : ~poliastro.frames.Planes
            Fundamental plane of the frame.
        """
        mean_elements = get_mean_elements(attractor)

        n_sunsync = (
            np.sqrt(mean_elements.attractor.k / abs(mean_elements.a**3)) *
            u.one).decompose()
        R_SSO = attractor.R
        k_SSO = attractor.k
        J2_SSO = attractor.J2

        try:
            with np.errstate(invalid="raise"):
                if (a is None) and (ecc is None) and (inc is None):
                    # We check sufficient number of parameters
                    raise ValueError(
                        "At least two parameters of the set {a, ecc, inc} are required."
                    )
                elif a is None and (ecc is not None) and (inc is not None):
                    # Semi-major axis is the unknown variable
                    a = (-3 * R_SSO**2 * J2_SSO * np.sqrt(k_SSO) /
                         (2 * n_sunsync * (1 - ecc**2)**2) * np.cos(inc))**(2 /
                                                                            7)
                elif ecc is None and (a is not None) and (inc is not None):
                    # Eccentricity is the unknown variable
                    _ecc_0 = np.sqrt(-3 * R_SSO**2 * J2_SSO * np.sqrt(k_SSO) *
                                     np.cos(inc.to(u.rad)) /
                                     (2 * a**(7 / 2) * n_sunsync))
                    ecc = np.sqrt(1 - _ecc_0)
                elif inc is None and (ecc is not None) and (a is not None):
                    # Inclination is the unknown variable
                    inc = np.arccos(-2 * a**(7 / 2) * n_sunsync *
                                    (1 - ecc**2)**2 /
                                    (3 * R_SSO**2 * J2_SSO * np.sqrt(k_SSO)))
        except FloatingPointError:
            raise ValueError(
                "No SSO orbit with given parameters can be found.")

        # Temporary fix: raan_from_ltan works only for Earth
        if attractor.name.lower() != "earth":
            raise NotImplementedError(
                "Attractors other than Earth not supported yet")

        raan = raan_from_ltan(epoch, ltan)
        ss = cls.from_classical(attractor,
                                a,
                                ecc,
                                inc,
                                raan,
                                argp,
                                nu,
                                epoch=epoch.tdb,
                                plane=plane)

        return ss