Planetary Ephemeris

To compute Sun, Moon, and planet positions relative to any observer, you need to initialize the planetary ephemeris. This is required for:

  • Accessing .sun and .moon attributes on any ephemeris object

  • Using get_body() and get_body_pv() methods

  • Evaluating constraints (SunConstraint, MoonConstraint, etc.)

The planetary ephemeris uses NASA JPL’s DE440S kernel, which provides high-precision positions for the Sun, Moon, and planets from 1849-2150.

Setup Functions

ensure_planetary_ephemeris(py_path=None, download_if_missing=True, spk_url=None)

Download (if needed) and initialize the planetary SPK. If no path is provided, uses the default cache location for de440s.bsp. This is the recommended function for most users.

init_planetary_ephemeris(py_path)

Initialize an already-downloaded planetary SPK file. Use this if you have a custom SPK file or want to avoid automatic downloads.

download_planetary_ephemeris(url, dest)

Explicitly download a planetary SPK file from a URL to a destination path.

is_planetary_ephemeris_initialized()

Check if the planetary ephemeris is initialized and ready. Returns bool.

Basic Usage

import rust_ephem as re
from datetime import datetime, timezone

# Initialize planetary ephemeris (downloads DE440S on first use)
re.ensure_planetary_ephemeris()

# Create any ephemeris type
begin = datetime(2024, 1, 1, tzinfo=timezone.utc)
end = datetime(2024, 1, 2, tzinfo=timezone.utc)

ephem = re.TLEEphemeris(
    norad_id=25544,  # ISS
    begin=begin,
    end=end,
    step_size=60
)

# Now Sun and Moon positions are available
sun_positions = ephem.sun    # SkyCoord of Sun from observer
moon_positions = ephem.moon  # SkyCoord of Moon from observer

Using get_body()

The get_body() and get_body_pv() methods work with any ephemeris type:

import rust_ephem as re
from datetime import datetime, timezone

re.ensure_planetary_ephemeris()

begin = datetime(2024, 1, 1, tzinfo=timezone.utc)
end = datetime(2024, 1, 2, tzinfo=timezone.utc)

# Works with TLEEphemeris
tle_ephem = re.TLEEphemeris(norad_id=25544, begin=begin, end=end)
mars_from_iss = tle_ephem.get_body("mars")

# Works with GroundEphemeris
ground = re.GroundEphemeris(
    lon=-122.0, lat=37.0, alt=0.0,
    begin=begin, end=end, step_size=60
)
jupiter_from_ground = ground.get_body("jupiter")

# Works with SPICEEphemeris
spice_ephem = re.SPICEEphemeris(
    spk_path="spacecraft.bsp",
    naif_id=-12345,
    begin=begin, end=end
)
saturn_from_spacecraft = spice_ephem.get_body("saturn")

Supported Bodies

The following body names are supported with get_body():

  • "sun" — The Sun

  • "moon" — Earth’s Moon

  • "mercury" — Mercury

  • "venus" — Venus

  • "earth" — Earth (useful for non-Earth-centered observers)

  • "mars" — Mars

  • "jupiter" — Jupiter

  • "saturn" — Saturn

  • "uranus" — Uranus

  • "neptune" — Neptune

NAIF ID Reference

Solar system body NAIF IDs (for advanced use):

  • 10: Sun

  • 301: Moon

  • 199: Mercury

  • 299: Venus

  • 399: Earth

  • 499: Mars

  • 599: Jupiter

  • 699: Saturn

  • 799: Uranus

  • 899: Neptune

Planetary SPK Files

The default DE440S kernel is recommended for most applications:

  • de440s.bsp — Compact planetary ephemeris (1849-2150), ~32 MB

  • de440.bsp — Full planetary ephemeris (1550-2650), ~114 MB

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

Custom SPK File

To use a different planetary SPK file:

import rust_ephem as re

# Use a specific SPK file
re.init_planetary_ephemeris("/path/to/de440.bsp")

# Or download from a custom URL
re.download_planetary_ephemeris(
    url="https://example.com/custom.bsp",
    dest="/path/to/custom.bsp"
)
re.init_planetary_ephemeris("/path/to/custom.bsp")

Error Handling

import rust_ephem as re
from datetime import datetime, timezone

begin = datetime(2024, 1, 1, tzinfo=timezone.utc)
end = datetime(2024, 1, 2, tzinfo=timezone.utc)

# Check if already initialized
if not re.is_planetary_ephemeris_initialized():
    try:
        re.ensure_planetary_ephemeris()
    except Exception as e:
        print(f"Failed to initialize planetary ephemeris: {e}")

# Accessing Sun/Moon without initialization raises an error
ephem = re.TLEEphemeris(norad_id=25544, begin=begin, end=end)

if re.is_planetary_ephemeris_initialized():
    sun = ephem.sun  # Works
else:
    print("Initialize planetary ephemeris first!")

Performance Notes

  • Planetary ephemeris is loaded once and cached in memory

  • Sun/Moon positions are computed during ephemeris object creation

  • The get_body() method is efficient for batch queries

  • DE440S is optimized for size while maintaining high accuracy

See also: Using get_body for Celestial Bodies for detailed examples of querying body positions.