Пример #1
0
def check_orbit(p, e, i, Om, w, v, ts):
    """Checks that the given set of elements are calculated properly by
    elementslib.py

    Converts the given elements to state vectors using ele_to_vec, then uses
    those state vectors to create an OsculatingElements object, and then
    checks that the data in the OsculatingElements object matches the input
    elements.
    """
    length = 1
    for item in p, e, i, Om, w, v:
        if isinstance(item, (list, ndarray)):
            length = len(item)

    mu = 403503.2355022598
    pos_vec, vel_vec = ele_to_vec(p, e, i, Om, w, v, mu)
    time_tt = ts.utc(2018).tt
    time = ts.tt(jd=repeat(time_tt, pos_vec[0].size))
    elements = OsculatingElements(Distance(km=pos_vec),
                                  Velocity(km_per_s=vel_vec), time, mu)
    check_types(elements, length)
    compare(time, elements.time, 1e-9)
    compare(elements.semi_latus_rectum.km, p, 1e-9)
    compare(elements.eccentricity, e, 1e-14)
    compare(elements.inclination.radians, i, 1e-14, mod=True)
    compare(elements.longitude_of_ascending_node.radians, Om, 1e-14, mod=True)
    compare(elements.argument_of_periapsis.radians, w, 1e-14, mod=True)
    compare(elements.true_anomaly.radians, v, 1e-14, mod=True)
Пример #2
0
 def _from_periapsis(
     cls,
     semilatus_rectum_au,
     eccentricity,
     inclination_degrees,
     longitude_of_ascending_node_degrees,
     argument_of_perihelion_degrees,
     t_periapsis,
     gm_km3_s2,
     center=None,
     target=None,
 ):
     """Build a `KeplerOrbit` given its parameters and date of periapsis."""
     gm_au3_d2 = gm_km3_s2 * _CONVERT_GM
     pos, vel = ele_to_vec(
         semilatus_rectum_au,
         eccentricity,
         DEG2RAD * inclination_degrees,
         DEG2RAD * longitude_of_ascending_node_degrees,
         DEG2RAD * argument_of_perihelion_degrees,
         0.0,
         gm_au3_d2,
     )
     return cls(
         Distance(pos),
         Velocity(vel),
         t_periapsis,
         gm_au3_d2,
         center,
         target,
     )
Пример #3
0
def check_orbit(p,
                e,
                i,
                Om,
                w,
                v,
                p_eps=None,
                e_eps=None,
                i_eps=None,
                Om_eps=None,
                w_eps=None,
                v_eps=None):
    pos0, vel0 = ele_to_vec(p, e, i, Om, w, v, mu)

    pos1, vel1 = propagate(pos0, vel0, 0, times, mu)
    ele = OsculatingElements(Distance(km=pos1), Velocity(km_per_s=vel1),
                             dummy_time, mu)

    if p_eps: compare(p, ele.semi_latus_rectum.km, p_eps)
    if e_eps: compare(e, ele.eccentricity, e_eps)
    if i_eps: compare(i, ele.inclination.radians, i_eps, mod=True)
    if Om_eps:
        compare(Om, ele.longitude_of_ascending_node.radians, Om_eps, mod=True)
    if w_eps: compare(w, ele.argument_of_periapsis.radians, w_eps, mod=True)
    if v_eps: compare(v, ele.true_anomaly.radians, v_eps, mod=True)
Пример #4
0
    def from_true_anomaly(cls, p, e, i, Om, w, v,
                          epoch,
                          mu_km_s=None,
                          mu_au_d=None,
                          center=None,
                          target=None,
                          center_name=None,
                          target_name=None,
        ):
        """ Creates a `KeplerOrbit` object from elements using true anomaly

        Parameters
        ----------
        p : Distance
            Semi-Latus Rectum
        e : float
             Eccentricity
        i : Angle
            Inclination
        Om : Angle
            Longitude of Ascending Node
        w : Angle
            Argument of periapsis
        v : Angle
            True anomaly
        epoch : Time
            Time corresponding to `position` and `velocity`
        mu_km_s : float
            Value of mu (G * M) in km^3/s^2
        mu_au_d : float
            Value of mu (G * M) in au^3/d^2
        center : int
            NAIF ID of the primary body, 399 for geocentric orbits, 10 for
            heliocentric orbits
        target : int
            NAIF ID of the secondary body
        """
        if (mu_km_s and mu_au_d) or (not mu_km_s and not mu_au_d):
            raise ValueError('Either mu_km_s or mu_au_d should be used, but not both')

        if mu_au_d:
            mu_km_s = mu_au_d * AU_KM**3 / DAY_S**2

        position, velocity = ele_to_vec(p.km,
                                        e,
                                        i.radians,
                                        Om.radians,
                                        w.radians,
                                        v.radians,
                                        mu_km_s,
        )
        return cls(Distance(km=position),
                   Velocity(km_per_s=velocity),
                   epoch,
                   mu_km_s,
                   center=center,
                   target=target,
                   center_name=center_name,
                   target_name=target_name,
        )
Пример #5
0
def test_helpful_exceptions():
    distance = Distance(1.234)
    expect = '''\
to use this Distance, ask for its value in a particular unit:

    distance.au
    distance.km
    distance.m'''

    with assert_raises(UnpackingError) as a:
        x, y, z = distance
    assert str(a.exception) == expect

    with assert_raises(UnpackingError) as a:
        distance[0]
    assert str(a.exception) == expect

    velocity = Velocity(1.234)
    expect = '''\
to use this Velocity, ask for its value in a particular unit:

    velocity.au_per_d
    velocity.km_per_s
    velocity.m_per_s'''

    with assert_raises(UnpackingError) as a:
        x, y, z = velocity
    assert str(a.exception) == expect

    with assert_raises(UnpackingError) as a:
        velocity[0]
    assert str(a.exception) == expect

    angle = Angle(radians=1.234)
    expect = '''\
to use this Angle, ask for its value in a particular unit:

    angle.degrees
    angle.hours
    angle.radians'''

    with assert_raises(UnpackingError) as a:
        x, y, z = angle
    assert str(a.exception) == expect

    with assert_raises(UnpackingError) as a:
        angle[0]
    assert str(a.exception) == expect
Пример #6
0
def write_PV_to_file(tle_obj_vec: list[dict],
                     t0: datetime,
                     tf: datetime,
                     timestep: float,
                     filepath: str = "sats-TLE-example.json") -> None:
    import json
    from collections import OrderedDict

    import numpy as np
    from sgp4.api import Satrec, SatrecArray, jday
    from skyfield.api import load
    from skyfield.sgp4lib import TEME
    from skyfield.units import Velocity, Distance
    from skyfield.framelib import ecliptic_J2000_frame
    from skyfield.positionlib import ICRF

    json_posveldata = OrderedDict()
    # all TLEs (w/ diff epochs) will be propagated to current time.

    epoch_error_flag = False
    time_vec = [t0]
    t = t0
    while t < tf:
        t += datetime.timedelta(seconds=timestep)
        time_vec.append(t)

    years, months, days, hours, minutes, seconds = zip(*[(t.year, t.month,
                                                          t.day, t.hour,
                                                          t.minute, t.second)
                                                         for t in time_vec])

    years, months, days, hours, minutes, seconds = np.array(years), np.array(
        months), np.array(days), np.array(hours), np.array(minutes), np.array(
            seconds)

    jds, frs = jday(years, months, days, hours, minutes, seconds)

    satrecs_vec = []
    for item in tle_obj_vec:
        sat_name = item["NORAD_CAT_ID"]
        epoch = datetime.datetime.fromisoformat(item["EPOCH"])

        if (tf > (epoch + datetime.timedelta(days=5))) or (
                tf < (epoch - datetime.timedelta(days=5))):
            # raise TypeError(f" Final propagation date  {tf} is more than 5 days away from latest TLE epoch ({epoch}), for satellite {sat_name}} ")
            epoch_error_flag = True

        sat = Satrec.twoline2rv(item["TLE_LINE1"], item["TLE_LINE2"])
        satrecs_vec.append(sat)
        json_posveldata[sat_name] = {"P": [], "V": []}

    satrecs = SatrecArray(satrecs_vec)

    errors, rs, vs = satrecs.sgp4(jds, frs)  # r,v in TEME frame

    ts = load.timescale()
    for idxsat, satdata in enumerate(json_posveldata.values()):

        for idxtime, (jdi, fri) in enumerate(zip(jds, frs)):

            # convert to J2000
            ttime = ts.ut1_jd(jdi + fri)

            rvicrf = ICRF.from_time_and_frame_vectors(
                t=ttime,
                frame=TEME,
                distance=Distance(km=rs[idxsat][idxtime]),
                velocity=Velocity(km_per_s=vs[idxsat][idxtime]))
            # rvj2000 = rvicrf.frame_xyz_and_velocity(ecliptic_J2000_frame)
            # pos_timestep_j2000, vel_timestep_j2000 = rvj2000[0].m, rvj2000[1].m_per_s

            pos_timestep_j2000, vel_timestep_j2000 = rvicrf.position.m, rvicrf.velocity.m_per_s

            satdata["P"].append(pos_timestep_j2000.tolist())
            satdata["V"].append(vel_timestep_j2000.tolist())

        # satdata["P"] = rs[idxsat].tolist() #TEME
        # satdata["V"] = vs[idxsat].tolist() #TEME

    if errors.any():
        print("SGP4 errors found.")  # check errror type.
    if epoch_error_flag:
        print(
            f"Warning: Results obtained might be inaccurate. Final propagation date  {tf} is more than 5 days away from latest TLE epoch ({epoch}), for satellite {sat_name} "
        )

    with open(filepath, "w") as file:
        json.dump(json_posveldata, file, indent=6)

    print(f"PV File written successfully at {filepath}.")
Пример #7
0
def test_converting_velocity_with_astropy():
    velocity = Velocity(au_per_d=1.234)
    value1 = velocity.km_per_s
    value2 = velocity.to(u.km / u.s)
    epsilon = 1e-6
    assert abs(value1 - value2.value) < epsilon
Пример #8
0
def test_constructors_accept_plain_lists():
    Distance(au=[1, 2, 3])
    Distance(km=[1, 2, 3])
    Distance(m=[1, 2, 3])
    Velocity(au_per_d=[1, 2, 3])
    Velocity(km_per_s=[1, 2, 3])
Пример #9
0
def test_velocity_input_units():
    v1 = Velocity(au_per_d=2.0)
    v2 = Velocity(km_per_s=3462.9137)
    assert abs(v1.au_per_d - v2.au_per_d) < 1e-7
Пример #10
0
    def _from_mean_anomaly(
        cls,
        semilatus_rectum_au,
        eccentricity,
        inclination_degrees,
        longitude_of_ascending_node_degrees,
        argument_of_perihelion_degrees,
        mean_anomaly_degrees,
        epoch,
        gm_km3_s2,
        center=None,
        target=None,
    ):
        """ Creates a `KeplerOrbit` object from elements using mean anomaly

        Parameters
        ----------
        p : Distance
            Semi-Latus Rectum
        e : float
             Eccentricity
        i : Angle
            Inclination
        Om : Angle
            Longitude of Ascending Node
        w : Angle
            Argument of periapsis
        M : Angle
            Mean anomaly
        epoch : Time
            Time corresponding to `position` and `velocity`
        mu_km_s : float
            Value of mu (G * M) in km^3/s^2
        mu_au3_d2 : float
            Value of mu (G * M) in au^3/d^2
        center : int
            NAIF ID of the primary body, 399 for geocentric orbits, 10 for
            heliocentric orbits
        target : int
            NAIF ID of the secondary body
        """
        M = DEG2RAD * mean_anomaly_degrees
        gm_au3_d2 = gm_km3_s2 * _CONVERT_GM
        if eccentricity < 1.0:
            E = eccentric_anomaly(eccentricity, M)
            v = true_anomaly_closed(eccentricity, E)
        elif eccentricity > 1.0:
            E = eccentric_anomaly(eccentricity, M)
            v = true_anomaly_hyperbolic(eccentricity, E)
        else:
            v = true_anomaly_parabolic(semilatus_rectum_au, gm_au3_d2, M)

        pos, vel = ele_to_vec(
            semilatus_rectum_au,
            eccentricity,
            DEG2RAD * inclination_degrees,
            DEG2RAD * longitude_of_ascending_node_degrees,
            DEG2RAD * argument_of_perihelion_degrees,
            v,
            gm_au3_d2,
        )
        return cls(
            Distance(pos),
            Velocity(vel),
            epoch,
            gm_au3_d2,
            center,
            target,
        )
        "Jupiter",
        "Saturn",
        "Uranus",
        "Neptune",
        "Pluto",
):
    planet = planet_name + " Barycenter"
    position = (planets[planet] - sun).at(t)

    # This is broken, see
    # https://github.com/skyfielders/python-skyfield/issues/655#issuecomment-960377889
    # osculating_elements_of(position, ecliptic_frame)

    # So we have to do things manually
    elems = OsculatingElements(
        Distance(np.einsum("mnr,nr->mr", ecliptic_frame,
                           position.position.au)),  # type: ignore
        Velocity(
            np.einsum("mnr,nr->mr", ecliptic_frame,
                      position.velocity.au_per_d)),  # type: ignore
        position.t,
        GM_dict[position.center] + GM_dict[position.target],
    )
    c_object = CelestialObject(position.target, planet_name, elems)
    c_object.glue()

position = (planets["Moon"] - planets["Earth"]).at(t)
elems = osculating_elements_of(position)
c_object = CelestialObject(position.target, "Moon", elems)
c_object.glue()
def test_iterating_over_raw_velocity():
    velocity = Velocity(au_per_d=1.234)
    with assert_raises(UnpackingError) as a:
        x, y, z = velocity
    assert str(a.exception) == '''\