Sidereon.Angles (Sidereon v3.0.2)

Copy Markdown View Source

Angular geometry calculations for satellites.

Computes angular separations between a satellite and celestial bodies (Sun, Moon) using vector geometry in the GCRS frame. Useful for:

  • Solar panel pointing analysis
  • Lunar interference assessment
  • Optical brightness estimation (phase angle)
  • Eclipse geometry (Earth angular radius)

All positions are expected in km in the GCRS (J2000/ICRF) frame. All returned angles are in degrees.

Direct helpers return {:error, :invalid_input} when their geometry is degenerate or outside the supported domain.

Example

{:ok, eph} = Sidereon.Ephemeris.load("de421.bsp")
{:ok, tle} = Sidereon.parse_tle(line1, line2)
result = Sidereon.Angles.compute(tle, ~U[2024-06-21 12:00:00Z], eph)
result.sun_angle      # degrees
result.moon_angle     # degrees
result.sun_elevation  # degrees (positive = sunlit side)
result.earth_angle    # degrees (angular radius of Earth)

Summary

Functions

Angular separation between two non-zero vectors, in degrees, or an invalid-input error.

Angular separation between two {longitude_deg, latitude_deg} pairs, or an invalid-input error.

Solar beta angle for an orbit normal and Sun vector, in degrees, or an invalid-input error.

Solar beta angle computed from position, velocity, and Sun vector, in degrees, or an invalid-input error.

Compute all standard angles for a satellite at a given time.

Angular radius of the Earth as seen from the satellite.

Angle between satellite nadir (toward Earth) and the Moon direction.

Position angle from the first {longitude_deg, latitude_deg} coordinate to the second, in degrees, or an invalid-input error.

Angle between satellite nadir (toward Earth) and the Sun direction.

Sun elevation above or below the satellite's local horizontal plane.

Functions

angular_separation(a, b)

@spec angular_separation(
  {number(), number(), number()},
  {number(), number(), number()}
) ::
  float() | {:error, :invalid_input}

Angular separation between two non-zero vectors, in degrees, or an invalid-input error.

angular_separation_coords(arg1, arg2)

@spec angular_separation_coords({number(), number()}, {number(), number()}) ::
  float() | {:error, :invalid_input}

Angular separation between two {longitude_deg, latitude_deg} pairs, or an invalid-input error.

beta_angle(orbit_normal, sun_position)

@spec beta_angle({number(), number(), number()}, {number(), number(), number()}) ::
  float() | {:error, :invalid_input}

Solar beta angle for an orbit normal and Sun vector, in degrees, or an invalid-input error.

beta_angle_from_state(r, v, sun_position)

@spec beta_angle_from_state(
  {number(), number(), number()},
  {number(), number(), number()},
  {number(), number(), number()}
) :: float() | {:error, :invalid_input}

Solar beta angle computed from position, velocity, and Sun vector, in degrees, or an invalid-input error.

compute(tle, datetime, ephemeris)

@spec compute(Sidereon.Elements.t(), DateTime.t(), Sidereon.Ephemeris.t()) ::
  {:ok, map()} | {:error, term()}

Compute all standard angles for a satellite at a given time.

Propagates the TLE, gets Sun and Moon positions from the ephemeris, and returns a map of angles.

Parameters

  • tle - parsed %Sidereon.Elements{} struct
  • datetime - DateTime.t() observation time
  • ephemeris - loaded %Sidereon.Ephemeris{} handle

Returns

%{
  sun_angle: float(),       # nadir-to-Sun angle in degrees
  moon_angle: float(),      # nadir-to-Moon angle in degrees
  sun_elevation: float(),   # Sun elevation above local horizontal
  earth_angle: float()      # Earth angular radius from satellite
}

earth_angular_radius(satellite_gcrs_position)

@spec earth_angular_radius({number(), number(), number()}) ::
  float() | {:error, :invalid_input}

Angular radius of the Earth as seen from the satellite.

This is the half-angle of the cone that just encloses the Earth's disk as seen from the satellite's position: asin(R_earth / |sat_position|).

Useful for eclipse geometry: if the Sun is within this angular radius of the anti-nadir direction, the satellite may be in Earth's shadow.

Parameters

  • satellite_gcrs_position - {x, y, z} satellite position in GCRS (km)

Returns the angular radius in degrees, or {:error, :invalid_input} when the satellite position is inside the Earth or otherwise unsupported.

moon_angle(satellite_gcrs_position, moon_position_from_earth)

@spec moon_angle(
  {number(), number(), number()},
  {number(), number(), number()}
) :: float() | {:error, :invalid_input}

Angle between satellite nadir (toward Earth) and the Moon direction.

Parameters

  • satellite_gcrs_position - {x, y, z} satellite position in GCRS (km)
  • moon_position_from_earth - {x, y, z} Moon position relative to Earth (km)

Returns the angle in degrees, or {:error, :invalid_input} for degenerate vectors.

phase_angle(satellite_gcrs_position, sun_position_from_earth, observer_position)

@spec phase_angle(
  {number(), number(), number()},
  {number(), number(), number()},
  {number(), number(), number()}
) :: float() | {:error, :invalid_input}

Sun-satellite-observer phase angle.

The phase angle is the angle at the satellite between the Sun and the observer. It determines the illumination geometry for optical brightness estimation:

  • 0 deg = full phase (Sun behind observer, satellite fully lit)
  • 180 deg = new phase (Sun behind satellite, satellite in shadow from observer)

Parameters

  • satellite_gcrs_position - {x, y, z} satellite position in GCRS (km)
  • sun_position_from_earth - {x, y, z} Sun position relative to Earth (km)
  • observer_position - {x, y, z} observer position in GCRS (km)

Returns the phase angle in degrees (0 to 180), or {:error, :invalid_input} for degenerate vectors.

position_angle(arg1, arg2)

@spec position_angle({number(), number()}, {number(), number()}) ::
  float() | {:error, :invalid_input}

Position angle from the first {longitude_deg, latitude_deg} coordinate to the second, in degrees, or an invalid-input error.

sun_angle(satellite_gcrs_position, sun_position_from_earth)

@spec sun_angle(
  {number(), number(), number()},
  {number(), number(), number()}
) :: float() | {:error, :invalid_input}

Angle between satellite nadir (toward Earth) and the Sun direction.

The nadir vector points from the satellite toward Earth's center, i.e., it is the negation of the satellite's GCRS position.

Parameters

  • satellite_gcrs_position - {x, y, z} satellite position in GCRS (km)
  • sun_position_from_earth - {x, y, z} Sun position relative to Earth (km)

Returns the angle in degrees (0 = Sun is directly below satellite toward Earth, 180 = Sun is directly above/away from Earth), or {:error, :invalid_input} for degenerate vectors.

sun_elevation(satellite_gcrs_position, sun_position_from_earth)

@spec sun_elevation(
  {number(), number(), number()},
  {number(), number(), number()}
) :: float() | {:error, :invalid_input}

Sun elevation above or below the satellite's local horizontal plane.

The local horizontal plane is perpendicular to the radial (nadir) vector. Positive elevation means the Sun is on the sunlit (away from Earth) side; negative means it is on the shadow (Earth) side.

Parameters

  • satellite_gcrs_position - {x, y, z} satellite position in GCRS (km)
  • sun_position_from_earth - {x, y, z} Sun position relative to Earth (km)

Returns elevation in degrees (-90 to +90), or {:error, :invalid_input} for degenerate vectors.