Orbital Mechanics

missiontools.orbit

Orbital mechanics, propagation, coordinate frame transformations, and access analysis.

Propagation

propagate_analytical()

Analytically propagate a Keplerian orbit to ECI state vectors. Supports unperturbed two-body motion and mean J2 secular perturbations.

sun_synchronous_inclination()

Required inclination for a sun-synchronous RAAN precession rate.

sun_synchronous_orbit()

Keplerian elements for a circular sun-synchronous orbit, given altitude and local solar time at the ascending or descending node.

geostationary_orbit()

Keplerian elements for a geostationary orbit at a given longitude.

highly_elliptical_orbit()

Keplerian elements for a critically inclined HEO (Molniya-style) with frozen apsides, given period, eccentricity, and apogee placement.

Frame transformations

gmst()

Greenwich Mean Sidereal Time (rad) from UTC epochs using the IAU 1982 polynomial.

eci_to_ecef() / ecef_to_eci()

Rotate vectors between ECI and ECEF via GMST rotation.

geodetic_to_ecef()

Convert WGS84 geodetic coordinates (latitude, longitude, altitude) to ECEF Cartesian.

eci_to_lvlh() / lvlh_to_eci()

Rotate vectors between ECI and the LVLH (RSW) frame, defined with = radial, ŷ = along-track, = orbit-normal.

sun_vec_eci()

Low-precision (≈0.01°) unit vector toward the Sun in ECI using the Astronomical Almanac algorithm.

Access analysis

earth_access()

Instantaneous boolean visibility array for a ground station.

earth_access_intervals()

Time intervals when a satellite is visible above an elevation mask. Uses coarse scan followed by binary-search edge refinement.

space_to_space_access()

Instantaneous LOS check between two spacecraft (spherical body model).

space_to_space_access_intervals()

Time intervals with unobstructed LOS between two spacecraft.

Eclipse

in_sunlight()

Cylindrical shadow model — returns True where the spacecraft is outside the Earth’s shadow.

Planned functionality

  • Numerical orbit propagation (RK4 / RK78)

  • Orbital manoeuvres (Hohmann, plane change, bi-elliptic)

  • Relative motion (Clohessy–Wiltshire / Hill’s equations)

  • Ground track computation

missiontools.orbit.propagate_analytical(t, epoch, a, e, i, arg_p, raan, ma, propagator_type='twobody', central_body_mu=398600441800000.0, central_body_j2=1.75553e+25, central_body_radius=6371008.7714)[source]

Propagate a Keplerian orbit analytically and return ECI state vectors.

Advances the mean anomaly from epoch to each time in t using the selected propagation model, solves Kepler’s equation for the eccentric anomaly, and transforms the result into ECI Cartesian position and velocity vectors.

Parameters:
  • t (list[datetime] | npt.NDArray[np.datetime64]) – Times at which to evaluate the state vector.

  • epoch (datetime | np.datetime64) – Epoch of the supplied orbital elements (i.e. the time at which ma is defined).

  • a (float | np.floating) – Semi-major axis (m).

  • e (float | np.floating) – Eccentricity (dimensionless, 0 <= e < 1 for elliptical orbits).

  • i (float | np.floating) – Inclination (rad).

  • arg_p (float | np.floating) – Argument of perigee (rad).

  • raan (float | np.floating) – Right ascension of the ascending node (rad).

  • ma (float | np.floating) – Mean anomaly at epoch (rad).

  • propagator_type (str, optional) – Propagation model to use. "twobody" (default) uses unperturbed Keplerian motion. "j2" incorporates mean J2 perturbations

  • central_body_mu (float | np.floating, optional) – Standard gravitational parameter of the central body (m³/s²). Defaults to EARTH_MU.

  • central_body_j2 (float | np.floating, optional) – J2 perturbation parameter of the central body (m⁵/s²), defined as \(\mu J_2 R^2\). Only used when propagator_type is "j2". Defaults to EARTH_J2.

  • central_body_radius (float | np.floating, optional) – Equatorial radius of the central body (m). Accepted for API consistency when unpacking a keplerian_params dict (see keplerian_params) but not used in the propagation calculation. Defaults to EARTH_MEAN_RADIUS.

Returns:

  • r (npt.NDArray[np.floating]) – Position vectors in the ECI frame, shape (N, 3) (m).

  • v (npt.NDArray[np.floating]) – Velocity vectors in the ECI frame, shape (N, 3) (m/s).

Parameters:
Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

missiontools.orbit.sun_synchronous_inclination(a, e=0.0, central_body_mu=398600441800000.0, central_body_j2=1.75553e+25)[source]

Return the inclination (rad) required for a sun-synchronous orbit.

A sun-synchronous orbit is one whose RAAN precesses at exactly the mean solar rate (+2π rad per Julian year), keeping the orbital plane at a roughly constant angle with respect to the Sun. The required inclination is derived by setting the J2 secular RAAN drift rate equal to the mean solar motion and solving for i.

From Vallado eq. 9-37:

\[\dot{\Omega} = -\frac{3}{2} \frac{n J_2 R^2}{p^2} \cos i \;=\; n_{\odot}\]

Solving for i:

\[\cos i = -\frac{2\, n_{\odot}\, p^2}{3\, n\, J_2 R^2}\]

where \(p = a(1-e^2)\) is the semi-latus rectum, \(n = \sqrt{\mu / a^3}\) is the mean motion, and \(J_2 R^2\) = central_body_j2 / central_body_mu.

Parameters:
  • a (float | np.floating) – Semi-major axis (m).

  • e (float | np.floating, optional) – Eccentricity (dimensionless, 0 <= e < 1). Defaults to 0 (circular).

  • central_body_mu (float | np.floating, optional) – Standard gravitational parameter (m³/s²). Defaults to EARTH_MU.

  • central_body_j2 (float | np.floating, optional) – Combined J2 parameter \(\mu J_2 R^2\) (m⁵/s²). Defaults to EARTH_J2.

Returns:

float – Sun-synchronous inclination in radians (will be in (π/2, π) for a prograde-retrograde orbit around Earth, typically ~97–100°).

Raises:

ValueError – If a or central_body_mu are non-positive, if e is outside [0, 1), or if no sun-synchronous orbit exists for the supplied parameters (|cos i| > 1).

Parameters:
Return type:

float

missiontools.orbit.sun_synchronous_orbit(altitude, local_time_at_node, node_type='ascending', epoch=None, central_body_mu=398600441800000.0, central_body_j2=1.75553e+25, central_body_radius=6378137.0)[source]

Return Keplerian elements for a circular sun-synchronous orbit.

Computes the RAAN such that the specified node type crosses the equator at the requested local solar time on the given epoch, and the inclination that produces a sun-synchronous RAAN drift rate.

The returned dict is ready to unpack directly into propagate_analytical() (propagate_analytical(t, **params)).

Parameters:
  • altitude (float | np.floating) – Orbit altitude above the body’s equatorial surface (m).

  • local_time_at_node (str) – Local solar time at the specified node crossing, formatted as "HH:MM" or "HH:MM:SS" (24-hour clock).

  • node_type (str, optional) – 'ascending' (default) or 'descending'. Indicates which node crossing the local time refers to.

  • epoch (datetime | np.datetime64 | None, optional) – Epoch at which the orbital elements are defined and the node crossing occurs. Defaults to J2000.0 (2000-01-01T12:00:00 UTC).

  • central_body_mu (float | np.floating, optional) – Standard gravitational parameter (m³/s²). Defaults to EARTH_MU.

  • central_body_j2 (float | np.floating, optional) – Combined J2 parameter μ × J₂_dim × R² (m⁵/s²). Defaults to EARTH_J2.

  • central_body_radius (float | np.floating, optional) – Equatorial radius used for altitude→semi-major-axis conversion (m). Defaults to EARTH_SEMI_MAJOR_AXIS (WGS84 equatorial radius).

Returns:

dict – Keplerian parameter dict with keys epoch, a, e, i, arg_p, raan, ma, central_body_mu, central_body_j2, central_body_radius. All angles are in radians; epoch is datetime64[us].

Raises:

ValueError – If local_time_at_node cannot be parsed, node_type is not 'ascending' or 'descending', altitude is negative, or no sun-synchronous orbit exists for the given parameters.

Parameters:
Return type:

dict

missiontools.orbit.geostationary_orbit(longitude_deg, epoch=None, central_body_mu=398600441800000.0, central_body_j2=1.75553e+25, central_body_radius=6378137.0)[source]

Return Keplerian elements for a geostationary orbit.

Computes the semi-major axis for a geosynchronous orbit (period equal to one sidereal day) and sets the mean anomaly so the satellite is located at longitude_deg in geographic longitude exactly at the epoch.

The orbit is equatorial and circular: i = 0, e = 0, RAAN = 0, arg_p = 0. For i = 0 these three angles are degenerate; only their sum (the mean longitude) is physically meaningful, which is captured entirely by ma.

Parameters:
  • longitude_deg (float) – Geographic (sub-satellite) longitude at epoch (deg). Any value is accepted; values outside [-180, 180] are wrapped automatically.

  • epoch (datetime | np.datetime64 | None, optional) – Epoch at which the satellite is at longitude_deg. Defaults to J2000.0 (2000-01-01T12:00:00 UTC).

  • central_body_mu (float, optional) – Standard gravitational parameter (m³/s²). Defaults to EARTH_MU.

  • central_body_j2 (float, optional) – Combined J2 parameter μ × J₂_dim × R² (m⁵/s²). Defaults to EARTH_J2.

  • central_body_radius (float, optional) – Equatorial radius (m). Defaults to EARTH_SEMI_MAJOR_AXIS.

Returns:

dict – Keplerian parameter dict with keys epoch, a, e, i, arg_p, raan, ma, central_body_mu, central_body_j2, central_body_radius.

Parameters:
Return type:

dict

missiontools.orbit.highly_elliptical_orbit(period_s, e, epoch, apogee_solar_time, apogee_longitude_deg, arg_p_deg=270.0, central_body_mu=398600441800000.0, central_body_j2=1.75553e+25, central_body_radius=6378137.0)[source]

Return Keplerian elements for a critically inclined highly elliptical orbit.

Constructs a Molniya-style HEO with the argument of perigee at the critical inclination so that the apsidal line is frozen (no secular drift in arg_p under J2). The RAAN and initial mean anomaly are set so that the first apogee after epoch occurs over the requested geographic longitude at the requested local solar time.

Parameters:
  • period_s (float) – Orbital period (s). Must be positive.

  • e (float) – Eccentricity (dimensionless, 0 < e < 1).

  • epoch (datetime | np.datetime64) – Reference epoch for the orbital elements.

  • apogee_solar_time (str) – Local mean solar time at the apogee sub-satellite point, formatted as 'HH:MM' or 'HH:MM:SS' (24-hour clock).

  • apogee_longitude_deg (float) – Geographic longitude of the apogee sub-satellite point (deg). Any value is accepted; values outside [-180, 180] wrap correctly.

  • arg_p_deg (float, optional) – Argument of perigee (deg). Defaults to 270° (apogee in northern hemisphere). Use 90° for a southern-hemisphere apogee. The inclination is chosen automatically as the critical inclination consistent with arg_p_deg:

    • arg_p_deg closest to 270° → i 63.435° (northern)

    • arg_p_deg closest to 90° → i 116.565° (southern)

  • central_body_mu (float, optional) – Standard gravitational parameter (m³/s²). Defaults to EARTH_MU.

  • central_body_j2 (float, optional) – Combined J2 parameter μ × J₂_dim × R² (m⁵/s²). Defaults to EARTH_J2.

  • central_body_radius (float, optional) – Equatorial radius (m). Defaults to EARTH_SEMI_MAJOR_AXIS.

Returns:

dict – Keplerian parameter dict with keys epoch, a, e, i, arg_p, raan, ma, central_body_mu, central_body_j2, central_body_radius.

Raises:

ValueError – If period_s 0, e is outside (0, 1), or apogee_solar_time cannot be parsed.

Parameters:
Return type:

dict

Notes

The apogee placement uses a mean-solar-time approximation accurate to within ~16 minutes (equation of time). The RAAN is computed from the exact GMST at the derived apogee time, so the geographic longitude accuracy is limited only by the solar-time approximation.

missiontools.orbit.gmst(t)[source]

Greenwich Mean Sidereal Time (rad) from an array of UTC/UT1 datetimes.

Uses the IAU 1982 polynomial. T is computed directly from the integer microsecond offset from J2000.0, avoiding the ~40 µs precision floor of a single-precision Julian Date float.

Parameters:

t (npt.NDArray[np.datetime64]) – Observation times as datetime64[us]. Values are interpreted as UT1 (passing UTC introduces < 0.004° error; passing TT introduces ~0.29° error and should be avoided).

Returns:

npt.NDArray[np.floating] – GMST in radians, wrapped to [0, 2π).

Parameters:

t (ndarray[tuple[Any, ...], dtype[datetime64]])

Return type:

ndarray[tuple[Any, …], dtype[floating]]

missiontools.orbit.eci_to_ecef(eci_vecs, t)[source]

Convert ECI position/velocity vectors to ECEF via GMST rotation.

Parameters:
  • eci_vecs (npt.NDArray[np.floating]) – Vectors in the ECI frame, shape (N, 3) or (3,) for a single vector.

  • t (npt.NDArray[np.datetime64]) – UTC/UT1 observation times as datetime64[us], shape (N,) or scalar. Must match the first dimension of eci_vecs.

Returns:

npt.NDArray[np.floating] – Vectors in the ECEF frame, same shape as eci_vecs.

Parameters:
Return type:

ndarray[tuple[Any, …], dtype[floating]]

missiontools.orbit.ecef_to_eci(ecef_vecs, t)[source]

Convert ECEF position/velocity vectors to ECI via GMST rotation.

Parameters:
  • ecef_vecs (npt.NDArray[np.floating]) – Vectors in the ECEF frame, shape (N, 3) or (3,) for a single vector.

  • t (npt.NDArray[np.datetime64]) – UTC/UT1 observation times as datetime64[us], shape (N,) or scalar. Must match the first dimension of ecef_vecs.

Returns:

npt.NDArray[np.floating] – Vectors in the ECI frame, same shape as ecef_vecs.

Parameters:
Return type:

ndarray[tuple[Any, …], dtype[floating]]

missiontools.orbit.geodetic_to_ecef(lat, lon, alt=0.0)[source]

Convert geodetic coordinates to ECEF Cartesian coordinates (WGS84).

Parameters:
  • lat (float | npt.NDArray[np.floating]) – Geodetic latitude (rad), scalar or shape (N,).

  • lon (float | npt.NDArray[np.floating]) – Longitude (rad), scalar or shape (N,).

  • alt (float | npt.NDArray[np.floating], optional) – Height above the WGS84 ellipsoid (m). Defaults to 0.

Returns:

npt.NDArray[np.floating] – ECEF position vector(s) (m), shape (3,) for scalar inputs or (N, 3) for array inputs.

Parameters:
Return type:

ndarray[tuple[Any, …], dtype[floating]]

missiontools.orbit.eci_to_lvlh(vecs, r_eci, v_eci)[source]

Convert vectors from the ECI frame to the LVLH (RSW) frame.

The LVLH frame is defined by the satellite’s instantaneous orbital state:

  • x̂ (R) — radial, pointing away from the central body

  • ŷ (S) — along-track, in the orbital plane (= velocity direction for circular orbits)

  • ẑ (W) — cross-track/normal, in the angular-momentum direction (right-hand normal to the orbital plane)

Parameters:
  • vecs (npt.NDArray[np.floating]) – Vectors to transform in the ECI frame, shape (N, 3) or (3,).

  • r_eci (npt.NDArray[np.floating]) – Satellite ECI position vector(s), shape (N, 3) or (3,) (m).

  • v_eci (npt.NDArray[np.floating]) – Satellite ECI velocity vector(s), shape (N, 3) or (3,) (m/s).

Returns:

npt.NDArray[np.floating] – Vectors in the LVLH frame, same shape as vecs.

Parameters:
Return type:

ndarray[tuple[Any, …], dtype[floating]]

missiontools.orbit.lvlh_to_eci(vecs, r_eci, v_eci)[source]

Convert vectors from the LVLH (RSW) frame to the ECI frame.

Inverse of eci_to_lvlh(). Because the LVLH rotation matrix Q is orthonormal, the inverse is simply its transpose: v_eci = Qᵀ v_lvlh.

Parameters:
  • vecs (npt.NDArray[np.floating]) – Vectors to transform in the LVLH frame, shape (N, 3) or (3,).

  • r_eci (npt.NDArray[np.floating]) – Satellite ECI position vector(s), shape (N, 3) or (3,) (m).

  • v_eci (npt.NDArray[np.floating]) – Satellite ECI velocity vector(s), shape (N, 3) or (3,) (m/s).

Returns:

npt.NDArray[np.floating] – Vectors in the ECI frame, same shape as vecs.

Parameters:
Return type:

ndarray[tuple[Any, …], dtype[floating]]

missiontools.orbit.sun_vec_eci(t)[source]

Unit vector(s) pointing toward the Sun in the ECI frame.

Uses the Astronomical Almanac low-precision solar coordinates (~0.01° accuracy). The Sun’s ecliptic longitude is converted to ECI (mean equatorial J2000) by rotating by the mean obliquity about the x-axis.

Parameters:

t (np.datetime64 | npt.NDArray[np.datetime64]) – Epoch(s) as datetime64[us]. Scalar or (N,) array.

Returns:

npt.NDArray[np.floating] – Unit vector(s) toward the Sun in ECI. Shape (3,) for a scalar epoch, (N, 3) for an array of N epochs.

Parameters:

t (datetime64 | ndarray[tuple[Any, ...], dtype[datetime64]])

Return type:

ndarray[tuple[Any, …], dtype[floating]]

missiontools.orbit.earth_access(vecs, lat, lon, alt=0.0, el_min=0.0, frame='eci', t=None)[source]

Determine which positions are visible from a ground station.

A position is considered visible when the elevation angle from the ground station to that position is greater than or equal to el_min.

Note

Earth blockage is not explicitly checked. For a surface station with el_min >= 0, a positive elevation angle implies the line-of-sight clears the Earth. Sub-zero masks or elevated ground stations may require an additional ray–ellipsoid intersection check.

Parameters:
  • vecs (npt.NDArray[np.floating]) – Position vectors, shape (N, 3) (m).

  • lat (float | np.floating) – Ground station geodetic latitude (rad).

  • lon (float | np.floating) – Ground station longitude (rad).

  • alt (float | np.floating, optional) – Ground station height above the WGS84 ellipsoid (m). Defaults to 0.

  • el_min (float | np.floating, optional) – Minimum elevation angle (rad). Defaults to 0 (above the horizon).

  • frame (str, optional) – Reference frame of vecs: 'eci' (default) or 'ecef'.

  • t (npt.NDArray[np.datetime64] | None, optional) – UTC/UT1 observation times as datetime64[us], shape (N,). Required when frame='eci'; ignored when frame='ecef'.

Returns:

npt.NDArray[np.bool_] – Boolean array of shape (N,). True where the position is visible from the ground station above el_min.

Raises:

ValueError – If frame='eci' and t is None, or if frame is not 'eci' or 'ecef'.

Parameters:
Return type:

ndarray[tuple[Any, …], dtype[bool]]

missiontools.orbit.earth_access_intervals(t_start, t_end, keplerian_params, lat, lon, alt=0.0, el_min=0.0, propagator_type='twobody', max_step=np.timedelta64(30, 's'), refine_tol=np.timedelta64(1, 's'), batch_size=10000)[source]

Find time intervals when a satellite is visible from a ground station.

Performs a coarse scan at max_step cadence to detect access windows, then refines each rising/falling edge with binary search to within refine_tol.

Warning

Passes shorter than max_step may be missed entirely. Set max_step to at most half the shortest expected pass duration.

Parameters:
  • t_start (np.datetime64) – Start of the search window (datetime64[us]).

  • t_end (np.datetime64) – End of the search window (datetime64[us]).

  • keplerian_params (dict) – Orbital elements at epoch. Must contain the keys epoch, a, e, i, arg_p, raan, ma. Optionally central_body_mu, central_body_j2, central_body_radius.

  • lat (float | np.floating) – Ground station geodetic latitude (rad).

  • lon (float | np.floating) – Ground station longitude (rad).

  • alt (float | np.floating, optional) – Ground station height above the WGS84 ellipsoid (m). Defaults to 0.

  • el_min (float | np.floating, optional) – Minimum elevation angle (rad). Defaults to 0 (horizon).

  • propagator_type (str, optional) – 'twobody' (default) or 'j2'.

  • max_step (np.timedelta64, optional) – Maximum coarse scan step size. Defaults to 30 s.

  • refine_tol (np.timedelta64, optional) – Binary-search convergence tolerance for edge times. Defaults to 1 s.

  • batch_size (int, optional) – Number of scan steps per propagation batch. Limits peak memory usage to roughly batch_size × 24 bytes. Defaults to 10 000.

Returns:

list[tuple[np.datetime64, np.datetime64]] – List of (start, end) pairs in datetime64[us], one per continuous access window. Empty list if no access occurs.

Parameters:
Return type:

list[tuple[datetime64, datetime64]]

missiontools.orbit.space_to_space_access(r1, r2, body_radius=6371008.7714)[source]

Determine which positions have an unobstructed line-of-sight.

Checks whether the straight-line segment between each pair of positions clears the central body, modelled as a sphere of radius body_radius. Both position arrays must be in the same reference frame with the central body centre at the origin (ECI and ECEF both satisfy this).

Note

A spherical obstruction model is used. The maximum error relative to the WGS84 ellipsoid is ≤ 21 km (< 0.4 % of a typical orbit radius), which is negligible for access analysis.

Choosing body_radius:

  • EARTH_MEAN_RADIUS (default, 6 371 008 m) — best representative average; minimises neither false positives nor false negatives.

  • EARTH_SEMI_MAJOR_AXIS (6 378 137 m) — conservative for equatorial and mid-latitude paths. A larger sphere is more likely to flag LOS as blocked near the Earth’s limb, so this choice under-reports access (safe side for link planning).

  • A smaller radius such as EARTH_SEMI_MINOR_AXIS — conservative in the opposite direction; may slightly over-report access near the poles.

Parameters:
  • r1 (npt.NDArray[np.floating]) – First spacecraft position(s) (m), shape (N, 3) or (3,).

  • r2 (npt.NDArray[np.floating]) – Second spacecraft position(s) (m), shape (N, 3) or (3,). Must be matched element-wise with r1.

  • body_radius (float, optional) – Radius of the obstructing central body sphere (m). Default: EARTH_MEAN_RADIUS (6 371 008 m).

Returns:

npt.NDArray[np.bool_] – Shape (N,)True where the LOS is not blocked by the central body. Returns a plain bool for scalar (3,) inputs.

Parameters:
Return type:

ndarray[tuple[Any, …], dtype[bool]]

missiontools.orbit.space_to_space_access_intervals(t_start, t_end, keplerian_params_1, keplerian_params_2, body_radius=6371008.7714, propagator_type_1='twobody', propagator_type_2='twobody', max_step=np.timedelta64(30, 's'), refine_tol=np.timedelta64(1, 's'), batch_size=10000)[source]

Find time intervals when two spacecraft have unobstructed line-of-sight.

Performs a coarse scan at max_step cadence to detect access windows, then refines each rising/falling edge with binary search to within refine_tol.

Warning

Passes shorter than max_step may be missed entirely. Set max_step to at most half the shortest expected pass duration.

Parameters:
  • t_start (np.datetime64) – Start of the search window (datetime64[us]).

  • t_end (np.datetime64) – End of the search window (datetime64[us]).

  • keplerian_params_1 (dict) – Orbital elements of spacecraft 1. Same format as earth_access_intervals().

  • keplerian_params_2 (dict) – Orbital elements of spacecraft 2.

  • body_radius (float, optional) – Radius of the obstructing central body sphere (m). Default: EARTH_MEAN_RADIUS.

  • propagator_type_1 (str, optional) – Propagator for spacecraft 1: 'twobody' (default) or 'j2'.

  • propagator_type_2 (str, optional) – Propagator for spacecraft 2: 'twobody' (default) or 'j2'.

  • max_step (np.timedelta64, optional) – Maximum coarse scan step size. Defaults to 30 s.

  • refine_tol (np.timedelta64, optional) – Binary-search convergence tolerance for edge times. Defaults to 1 s.

  • batch_size (int, optional) – Number of scan steps per propagation batch. Defaults to 10 000.

Returns:

list[tuple[np.datetime64, np.datetime64]] – List of (start, end) pairs in datetime64[us], one per continuous access window. Empty list if no access occurs.

Parameters:
Return type:

list[tuple[datetime64, datetime64]]

missiontools.orbit.in_sunlight(r_eci, t, body_radius=6378137.0)[source]

Determine whether a spacecraft is in sunlight using a cylindrical shadow model.

Parameters:
  • r_eci (array_like, shape (3,) or (N, 3)) – Spacecraft position(s) in the ECI frame (m).

  • t (datetime64 or array of datetime64) – Epoch(s) for computing the Sun direction.

  • body_radius (float, optional) – Central body equatorial radius (m). Defaults to Earth WGS84.

Returns:

np.bool_ or ndarray of boolTrue where the spacecraft is in sunlight. Scalar input gives a scalar result; array input gives an (N,) array.

Parameters:
Return type:

bool | ndarray[tuple[Any, …], dtype[bool]]