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)
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
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()
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)
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)
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)
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"
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
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"])
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)
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