Computes the apparent geocentric positions of the Moon and the Sun from a JPL DE440s (or compatible) SPK binary ephemeris kernel.
The SPK file provides positions in ICRF/J2000 Cartesian coordinates (km). This module chains the available segments to produce each body's position relative to the Earth's centre, then applies IAU 1980 precession and nutation to yield apparent geocentric right ascension, declination and distance in the true equator and equinox of date.
Segment chaining (DE440s)
de440s.bsp supplies, among others:
body 301, the Moon, relative to body 3, the Earth-Moon barycentre (EMB).
body 399, the Earth, relative to body 3.
The Moon relative to the Earth is then Moon/EMB − Earth/EMB.
The compact ephemeris bundled with the library omits body 399, which
Astro.Ephemeris.Kernel reconstructs from body 301 — the two are exact
scalar multiples of one another. Chaining is unaffected.
Setup
The kernel is loaded when the application starts, from the path that
Astro.Ephemeris.Downloader.ephemeris_path/0 resolves, and the position
functions read it from there:
{:ok, {right_ascension, declination, distance}} =
Astro.Ephemeris.moon_position(~U[2024-06-21 12:00:00Z])Accuracy
Position accuracy is limited by the ephemeris itself: DE440 achieves sub-centimetre accuracy for the Moon relative to current-epoch laser ranging data. The dominant remaining error sources for rise and set timing are:
the atmospheric refraction model, about 1 arcminute or 2 seconds of time near the horizon.
topocentric correction residuals at high solar-altitude latitudes.
This is a 10–100× improvement over the truncated Chapront series used in Meeus that was the core of the Astro 1.x library.
Summary
Functions
Returns the equatorial horizontal parallax for a given geocentric distance.
Computes the apparent geocentric position of the Moon for the given datetime.
Computes the apparent geocentric position of the Moon for the given dynamical time.
Computes the apparent geocentric position of the Sun for the given datetime.
Computes the apparent geocentric position of the Sun for the given dynamical time.
Functions
Returns the equatorial horizontal parallax for a given geocentric distance.
Computed as asin(R_earth / distance) using the WGS-84
equatorial radius of 6378.137 km.
Arguments
distance_kmis the geocentric distance in kilometers.
Returns
- The equatorial horizontal parallax in degrees.
Examples
iex> Astro.Ephemeris.equatorial_horizontal_parallax(384_400.0) |> Float.round(6)
0.950721
@spec moon_position(DateTime.t()) :: {:ok, {right_ascension :: Astro.angle(), float(), float()}} | {:error, term()}
Computes the apparent geocentric position of the Moon for the given datetime.
Chains the Moon/EMB and Earth/EMB segments from the loaded JPL ephemeris, then applies IAU 1980 precession and nutation to produce coordinates in the true equator and equinox of date.
Arguments
date_timeis aDateTimein any time zone (converted internally to a moment and then to dynamical time).
Returns
{:ok, {ra_deg, dec_deg, distance_km}}where right ascension is in degrees in the range [0, 360), declination is in degrees in the range [-90, 90], and distance is in kilometers.{:error, reason}if a required ephemeris segment is not found.
Examples
iex> {:ok, {right_ascension, declination, distance}} =
...> Astro.Ephemeris.moon_position(~U[2024-06-21 12:00:00Z])
iex> {Float.round(right_ascension, 4), Float.round(declination, 4), round(distance)}
{262.9343, -28.0371, 382267}
Computes the apparent geocentric position of the Moon for the given dynamical time.
Arguments
dynamical_timeis TDB seconds past J2000.0.
Returns
{:ok, {ra_deg, dec_deg, distance_km}}where right ascension is in degrees in the range [0, 360), declination is in degrees in the range [-90, 90], and distance is in kilometers.{:error, reason}if a required ephemeris segment is not found.
Examples
iex> {:ok, {right_ascension, declination, distance}} = Astro.Ephemeris.moon_position_dt(0.0)
iex> {Float.round(right_ascension, 4), Float.round(declination, 4), round(distance)}
{222.4504, -10.9001, 402449}
@spec sun_position(DateTime.t()) :: {:ok, {float(), float(), float()}} | {:error, term()}
Computes the apparent geocentric position of the Sun for the given datetime.
Chains the Sun/SSB, EMB/SSB and Earth/EMB segments from the loaded JPL ephemeris (Sun/SSB − EMB/SSB + Earth/EMB), then applies IAU 1980 precession and nutation.
Arguments
date_timeis aDateTimein any time zone.
Returns
{:ok, {ra_deg, dec_deg, distance_km}}where right ascension is in degrees in the range [0, 360), declination is in degrees in the range [-90, 90], and distance is in kilometers.{:error, reason}if a required ephemeris segment is not found.
Examples
iex> {:ok, {right_ascension, declination, distance}} =
...> Astro.Ephemeris.sun_position(~U[2024-06-21 12:00:00Z])
iex> {Float.round(right_ascension, 4), Float.round(declination, 4), round(distance)}
{90.6638, 23.4325, 152035789}
Computes the apparent geocentric position of the Sun for the given dynamical time.
Arguments
dynamical_timeis TDB seconds past J2000.0.
Returns
{:ok, {ra_deg, dec_deg, distance_km}}where right ascension is in degrees in the range [0, 360), declination is in degrees in the range [-90, 90], and distance is in kilometers.{:error, reason}if a required ephemeris segment is not found.
Examples
iex> {:ok, {right_ascension, declination, distance}} = Astro.Ephemeris.sun_position_dt(0.0)
iex> {Float.round(right_ascension, 4), Float.round(declination, 4), round(distance)}
{281.2947, -23.0353, 147098431}