Пример #1
0
def test_dump_opm_interplanetary(jplfiles, orbit, ccsds_format, datafile,
                                 helper):
    create_frames("Mars")
    orbit.frame = "Mars"

    txt = dumps(orbit, fmt=ccsds_format)
    helper.assert_string(datafile("opm_interplanetary"), txt)
Пример #2
0
def test_soi(jplfiles):

    opm = ccsds.loads("""CCSDS_OPM_VERS = 2.0
CREATION_DATE = 2019-02-22T23:22:31
ORIGINATOR = N/A

META_START
OBJECT_NAME          = N/A
OBJECT_ID            = N/A
CENTER_NAME          = EARTH
REF_FRAME            = EME2000
TIME_SYSTEM          = UTC
META_STOP

COMMENT  State Vector
EPOCH                = 2018-05-02T00:00:00.000000
X                    =  6678.000000 [km]
Y                    =     0.000000 [km]
Z                    =     0.000000 [km]
X_DOT                =     0.000000 [km/s]
Y_DOT                =     7.088481 [km/s]
Z_DOT                =     3.072802 [km/s]

COMMENT  Keplerian elements
SEMI_MAJOR_AXIS      =  6678.000000 [km]
ECCENTRICITY         =     0.000000
INCLINATION          =    23.436363 [deg]
RA_OF_ASC_NODE       =     0.000000 [deg]
ARG_OF_PERICENTER    =     0.000000 [deg]
TRUE_ANOMALY         =     0.000000 [deg]

COMMENT  Escaping Earth
MAN_EPOCH_IGNITION   = 2018-05-02T00:39:03.955092
MAN_DURATION         = 0.000 [s]
MAN_DELTA_MASS       = 0.000 [kg]
MAN_REF_FRAME        = TNW
MAN_DV_1             = 3.456791 [km/s]
MAN_DV_2             = 0.000000 [km/s]
MAN_DV_3             = 0.000000 [km/s]
""")

    planetary_step = timedelta(seconds=180)
    solar_step = timedelta(hours=12)

    jpl.create_frames()

    central = jpl.get_body('Sun')
    planets = jpl.get_body('Earth')

    opm.propagator = SOIPropagator(solar_step, planetary_step, central, planets)

    frames = set()
    for orb in opm.iter(stop=timedelta(5)):
        frames.add(orb.frame.name)

    assert not frames.symmetric_difference(['Sun', 'EME2000'])

    # Check if the last point is out of Earth sphere of influence
    assert orb.copy(frame='EME2000', form="spherical").r > SOIPropagator.SOI['Earth'].radius
Пример #3
0
def test_soi(jplfiles):

    opm = ccsds.loads("""CCSDS_OPM_VERS = 2.0
CREATION_DATE = 2019-02-22T23:22:31
ORIGINATOR = N/A

META_START
OBJECT_NAME          = N/A
OBJECT_ID            = N/A
CENTER_NAME          = EARTH
REF_FRAME            = EME2000
TIME_SYSTEM          = UTC
META_STOP

COMMENT  State Vector
EPOCH                = 2018-05-02T00:00:00.000000
X                    =  6678.000000 [km]
Y                    =     0.000000 [km]
Z                    =     0.000000 [km]
X_DOT                =     0.000000 [km/s]
Y_DOT                =     7.088481 [km/s]
Z_DOT                =     3.072802 [km/s]

COMMENT  Keplerian elements
SEMI_MAJOR_AXIS      =  6678.000000 [km]
ECCENTRICITY         =     0.000000
INCLINATION          =    23.436363 [deg]
RA_OF_ASC_NODE       =     0.000000 [deg]
ARG_OF_PERICENTER    =     0.000000 [deg]
TRUE_ANOMALY         =     0.000000 [deg]

COMMENT  Escaping Earth
MAN_EPOCH_IGNITION   = 2018-05-02T00:39:03.955092
MAN_DURATION         = 0.000 [s]
MAN_DELTA_MASS       = 0.000 [kg]
MAN_REF_FRAME        = TNW
MAN_DV_1             = 3.456791 [km/s]
MAN_DV_2             = 0.000000 [km/s]
MAN_DV_3             = 0.000000 [km/s]
""")

    planetary_step = timedelta(seconds=180)
    solar_step = timedelta(hours=12)

    jpl.create_frames()

    central = jpl.get_body('Sun')
    planets = jpl.get_body('Earth')

    opm.propagator = SOIPropagator(solar_step, planetary_step, central, planets)

    frames = set()
    for orb in opm.iter(stop=timedelta(5)):
        frames.add(orb.frame.name)

    assert not frames.symmetric_difference(['Sun', 'EME2000'])

    # Check if the last point is out of Earth sphere of influence
    assert orb.copy(frame='EME2000', form="spherical").r > SOIPropagator.SOI['Earth'].radius
Пример #4
0
def jplfiles():
    config.set('env', 'jpl', 'files', [
        str(Path(__file__).parent / "data" / "jpl" / "de403_2000-2020.bsp"),
        str(Path(__file__).parent / "data" / "jpl" / "pck00010.tpc"),
        str(Path(__file__).parent / "data" / "jpl" / "gm_de431.tpc"),
    ])

    jpl.create_frames()
Пример #5
0
def test_load_interplanetary(jplfiles, orbit, datafile, helper):

    create_frames(until="Mars")
    orbit.frame = "Mars"

    data_opm = loads(datafile("opm_interplanetary"))

    helper.assert_orbit(orbit, data_opm)
Пример #6
0
def test_load_oem_interplanetary(jplfiles, ephem, datafile, helper):

    create_frames(until="Mars")

    ephem.frame = "Mars"

    data = loads(datafile("oem_interplanetary"))

    helper.assert_ephem(ephem, data)
Пример #7
0
def test_dump_oem_interplanetary(jplfiles, ephem, ccsds_format, datafile,
                                 helper):

    create_frames("Mars")
    ephem.frame = "Mars"

    ref = datafile("oem_interplanetary")
    txt = dumps(ephem, fmt=ccsds_format)

    helper.assert_string(ref, txt)
Пример #8
0
def test_create_frames(jplfiles):
    create_frames(until='Mars')

    mars = get_frame('Mars')
    assert mars.name == "Mars"

    # The frame for Venus is not yet created, due to the use of the 'until' keyword in the
    # create_frame call
    with raises(UnknownFrameError):
        get_frame("Venus")

    # Create all the frames available in the .bsp files
    create_frames()

    venus = get_frame('Venus')
    assert venus.name == "Venus"
Пример #9
0
def test_soi(jplfiles, method):

    planetary_step = timedelta(seconds=180)
    solar_step = timedelta(hours=12)

    jpl.create_frames()

    central = jpl.get_body('Sun')
    planets = jpl.get_body('Earth')

    if method == "numerical":
        propagator = SoINumerical(solar_step, planetary_step, central, planets)
        txt = opm_with_man
    else:
        propagator = SoIAnalytical(central, planets)
        propagator.step = solar_step
        txt = opm_without_man

    opm = ccsds.loads(txt).as_orbit(propagator)

    # d, r = [], []
    frames = set()
    for orb in opm.iter(stop=timedelta(5)):
        frames.add(orb.frame.name)
    #     r.append(orb.copy(frame="EME2000", form="spherical").r)
    #     d.append(orb.date)

    # import matplotlib.pyplot as plt
    # plt.plot(d, r)
    # plt.show()

    assert not frames.symmetric_difference(['Sun', 'EME2000'])

    # Check if the last point is out of Earth sphere of influence
    assert orb.copy(frame='EME2000',
                    form="spherical").r > SoINumerical.SOIS['Earth'].radius
Пример #10
0
def space_phase(*argv):
    """Compute the phase of the moon or other solar system bodies

    Usage:
        space-phase <body> [<date>] [--graph] [--frame <frame>] [-a] [--file <file>]

    Options:
        <body>            Body
        <date>            Date to compute the moon phase at [default: now]
                          (format %Y-%m-%dT%H:%M:%S)
        -g, --graph       Display the moon phase
        -a, --analytical  Use analytical model instead of JPL files
        --file <file>     File
    """
    import sys
    from .clock import Date
    from .utils import docopt, parse_date
    from .station import StationDb

    args = docopt(space_phase.__doc__)

    if args["<date>"] is None:
        args["<date>"] = "now"

    try:
        date = parse_date(args["<date>"])
    except ValueError as e:
        print(e, file=sys.stderr)
        sys.exit(1)

    StationDb.list()

    body = args["<body>"]

    if body == "Moon":
        center = "EME2000"
        second = "Sun"
    else:
        center = body
        body = "Sun"
        second = "Earth"

    if args["--analytical"] and body.lower() == "moon":
        first = solar.get_body(body).propagate(date)
        second = solar.get_body(second).propagate(first.date)
        src = "analytical"
    else:
        src = "JPL"
        if args["--analytical"]:
            log.warning(
                "No analytical model available for '{}'. Switching to JPL source"
                .format(body))
        jpl.create_frames()
        first = jpl.get_orbit(body, date)
        second = jpl.get_orbit(second, first.date)

    if body == "Moon":
        phase = compute_phase(first, second, center)
    else:
        phase = np.pi - compute_phase(first, second, center)
        body = center

    illumin = illumination(phase)

    log.debug("Computing {} phase using source '{}'".format(body, src))
    log.info("{} at {:%Y-%m-%dT%H:%M:%S} : {:0.2f}%".format(
        body, date, illumin * 100))

    if args["--graph"] or args["--file"]:
        draw_phase(date, phase, body=args["<body>"], filepath=args["--file"])
Пример #11
0
def space_planet(*args):
    """Compute position of a planet of the solar system and its major moons

    Usage:
        space-planet
        space-planet fetch
        space-planet <planet>... [options]

    Options:
        fetch                Retrieve .bsp file
        <planet>             Names of the planet to compute the ephemeris of. If
                             absent, list all bodies available
        -f, --frame <frame>  Frame in which to display the ephemeris to
                             [default: EME2000]
        -d, --date <date>    Start date of the ephem (%Y-%m-%d) [default: midnight]
        -r, --range <days>   Duration of extrapolation [default: 3d]
        -s, --step <step>    Step size of the ephemeris. [default: 60m]
        -a, --analytical     Force analytical model instead of .bsp files

    Example:
        space-planet Mars  # Position of Mars in EME2000
        space-planet Moon -f Phobos  # Position of the moon as seen from Phobos

    This command relies on .bsp files, parsed by the incredible jplephem lib.
    Bsp file can be retrieved at

        https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/

    Files examples:

        de432s.bsp     Moon, Sun, Mercury, Venus and main bodies barycentre
        mar097.bsp     Mars, Phobos and Deimos
        jup310.bsp     Jupiter and its major moons
        sat360xl.bsp   Saturn and its major moons

    The 'beyond.env.jpl' config variable must be set to a list of bsp files
    paths. See beyond documentation about JPL files:

        http://beyond.readthedocs.io/en/latest/api/env.html#module-beyond.env.jpl

    If no .bsp file is provided, the command falls back to analytical methods
    for Moon and Sun. Other bodies are not provided.
    """

    import requests

    from logging import getLogger

    log = getLogger(__name__)

    args = docopt(space_planet.__doc__)

    if args["fetch"]:

        folder = ws.folder / "jpl"

        if not folder.exists():
            folder.mkdir()

        naif = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/"
        baseurl = {
            "de403_2000-2020.bsp":
            naif + "spk/planets/a_old_versions/",  # Data until 2020-01-01
            "de430.bsp": naif + "spk/planets/",
            "de432s.bsp": naif + "spk/planets/",
            "de435.bsp": naif + "spk/planets/",
            "jup310.bsp": naif + "spk/satellites/",
            "sat360xl.bsp": naif + "spk/satellites/",
            "mar097.bsp": naif + "spk/satellites/",
            "pck00010.tpc": naif + "pck/",
            "gm_de431.tpc": naif + "pck/",
        }

        success = []

        filelist = ws.config.get("beyond",
                                 "env",
                                 "jpl",
                                 fallback="de403_2000-2020.bsp")
        if not isinstance(filelist, list):
            filelist = [filelist]

        for filepath in filelist:

            filepath = Path(filepath)
            if not filepath.is_absolute():
                filepath = folder / filepath

            if not filepath.exists():

                url = baseurl.get(filepath.name, "") + str(filepath.name)
                log.info("Fetching {}".format(filepath.name))
                log.debug(url)

                try:
                    r = requests.get(url, stream=True)
                except requests.exceptions.ConnectionError as e:
                    log.error(e)
                else:
                    try:
                        r.raise_for_status()
                    except requests.exceptions.HTTPError as e:
                        log.error("{} {}".format(filepath.name, e))
                    else:
                        total = int(r.headers.get("content-length", 0))
                        size = 0
                        with filepath.open("bw") as fp:
                            for chunk in r.iter_content(chunk_size=1024):
                                fp.write(chunk)
                                if total:
                                    size += len(chunk)
                                    print(
                                        "\r> {:6.2f} %   {} / {}".format(
                                            100 * size / total,
                                            humanize(size),
                                            humanize(total),
                                        ),
                                        end="",
                                    )
                        if total:
                            print("\r", " " * 40, end="\r")
                        success.append(str(filepath.absolute()))
                        log.debug("Adding {} to the list of jpl files".format(
                            filepath.name))
            else:
                success.append(str(filepath.absolute()))
                log.info("File {} already downloaded".format(filepath.name))

        # Adding the file to the list and saving the new state of configuration
        if success:
            ws.config.set("beyond", "env", "jpl", success)

        ws.config.save()

    elif args["<planet>"]:

        try:
            date = parse_date(args["--date"], fmt="date")
            stop = parse_timedelta(args["--range"])
            step = parse_timedelta(args["--step"])
        except ValueError as e:
            print(e, file=sys.stderr)
            sys.exit(1)

        if not args["--analytical"]:
            # Create all frames from .bsp files, if they are available
            try:
                jpl.create_frames()
            except jpl.JplError:
                jpl_error = True
            else:
                jpl_error = False

        # Create all frames from stations database
        StationDb.list()

        try:
            frame = get_frame(args["--frame"])
        except UnknownFrameError as e:
            print(e, file=sys.stderr)
            sys.exit(1)

        # Computation
        ephems = []

        for body_name in args["<planet>"]:
            try:
                if args["--analytical"] or jpl_error:
                    body = solar.get_body(body_name).propagate(date)
                else:
                    body = jpl.get_orbit(body_name, date)
            except UnknownBodyError as e:
                print(e, file=sys.stderr)
                sys.exit(1)

            ephem = body.ephem(start=date, stop=stop, step=step)
            ephem.frame = frame
            ephem.name = body_name
            ephems.append(ephem)
        else:
            print(ccsds.dumps(ephems))
    else:
        print("List of all available bodies")
        try:
            jpl.create_frames()
            txt = recurse(jpl.get_frame("Earth").center.node, set())
        except jpl.JplError as e:
            print(" Sun")
            print(" Moon")
        else:
            print(txt)
Пример #12
0
import matplotlib.pyplot as plt

from beyond.dates import Date
from beyond.env import jpl
from beyond.frames import create_station
from beyond.config import config

# Load the ".bsp" file
config.update({"env": {"jpl": ["/home/jules/.space/jpl/jup310.bsp"]}})

date = Date.now()

# Definition of the location of observation
station = create_station('TLS', (43.428889, 1.497778, 178.0))

jpl.create_frames()

# Retrieve Jupiter and its moons state-vectors
jupiter = jpl.get_orbit('Jupiter', date)
io = jpl.get_orbit('Io', date)
europa = jpl.get_orbit('Europa', date)
ganymede = jpl.get_orbit('Ganymede', date)
callisto = jpl.get_orbit('Callisto', date)

# Convert them to the observer frame
jupiter.frame = station
io.frame = station
europa.frame = station
ganymede.frame = station
callisto.frame = station