Sgp4Ex

Sgp4Ex is an Elixir NIF wrapper for the SGP4 source code available at https://celestrak.org/publications/AIAA/2006-6753/ - it allows propagation of Two-Line Element sets (TLEs) to get TEME state vectors describing the position/velocity of satellites.

Features

Installation

Sgp4Ex can be installed by adding it to mix.exs:

def deps do
[
{:sgp4_ex, "~> 0.1.0"}
]
end

Usage

Basic TLE Propagation

# Parse a TLE
line1 = "1 25544U 98067A 21275.54791667 .00001264 00000-0 39629-5 0 9993"
line2 = "2 25544 51.6456 23.4367 0001234 45.6789 314.3210 15.48999999 12"
{:ok, tle} = Sgp4Ex.parse_tle(line1, line2)
# Propagate to a specific time
epoch = ~U[2021-10-02T14:00:00Z]
{:ok, teme_state} = Sgp4Ex.propagate_tle_to_epoch(tle, epoch)
# Get position and velocity in TEME frame (km and km/s)
{x, y, z} = teme_state.position
{vx, vy, vz} = teme_state.velocity

Geodetic Coordinates

# Get latitude, longitude, and altitude
{:ok, geo} = Sgp4Ex.propagate_to_geodetic(tle, epoch)
IO.puts("Latitude: #{geo.latitude}°")
IO.puts("Longitude: #{geo.longitude}°")
IO.puts("Altitude: #{geo.altitude_km} km")

Forgiving TLE Parser

The TLE parser automatically handles common data issues:

Technical Details

Coordinate Systems

The implementation uses the classical IAU 1982 model for Greenwich Mean Sidereal Time (GMST). This differs from modern implementations like Skyfield by approximately 0.536° in longitude due to the Equation of the Equinoxes (the difference between mean and apparent sidereal time).

Native NIF and Elixir fallback

Propagation prefers the compiled C++ NIF. If the NIF is missing, fails to load, or raises, Sgp4Ex automatically uses a pure-Elixir implementation of the same Vallado SGP4/SDP4 algorithm (WGS-72, improved opsmode). Check the active backend with Sgp4Ex.propagator/0.

Force a backend in config:

config :sgp4_ex, propagator: :auto # default: NIF when available
# config :sgp4_ex, propagator: :nif
# config :sgp4_ex, propagator: :elixir

The public propagate_tle_to_epoch/2 API caches the initialized satellite record, so repeating a TLE across epochs avoids re-running SGP4 init. The NIF currently re-parses the TLE and re-inits on every call.

Compare the two implementations from this repo:

mix sgp4.bench
mix sgp4.bench --n 20000

Build Requirements

The build process is handled automatically by the custom Mix task. The Elixir fallback does not require a C++ toolchain.

License

This project is licensed under the same terms as the original SGP4 source code.