Skip to content

skyweaver.orbits

Orbit specifications and conversion to SGP4/Skyfield objects.

This module defines a lightweight, physical orbit description for artificial Earth satellites and provides conversion utilities for building sgp4 and Skyfield satellite objects.

The initial design target is circular or near-circular LEO orbits for simulation and coverage studies.

OrbitSpec dataclass

OrbitSpec(name, epoch, altitude_km, inclination_deg, raan_deg=0.0, mean_anomaly_deg=0.0, eccentricity=0.0, arg_perigee_deg=0.0, bstar=0.0)

A simple physical specification for an artificial Earth orbit.

Parameters:

Name Type Description Default
name str

Human-readable orbit name.

required
epoch datetime

Epoch of the element set. Naive datetimes are interpreted as UTC.

required
altitude_km float

Mean altitude above the WGS84 equatorial radius, in kilometers.

required
inclination_deg float

Inclination in degrees.

required
raan_deg float

Right ascension of the ascending node, in degrees.

0.0
mean_anomaly_deg float

Mean anomaly at epoch, in degrees.

0.0
eccentricity float

Orbital eccentricity. For the initial skyweaver use case, this will generally be 0.0 or very small.

0.0
arg_perigee_deg float

Argument of perigee in degrees. For circular orbits this is formally arbitrary, but SGP4 still requires a value.

0.0
bstar float

Ballistic drag coefficient in inverse Earth radii. Leave at 0.0 for idealized artificial design studies.

0.0
Notes

This class stores a small, physically meaningful set of inputs that can later be converted into an SGP4 satellite record.

mean_motion_rad_min property

mean_motion_rad_min

Return the mean motion in radians per minute.

mean_motion_rad_s property

mean_motion_rad_s

Return the Keplerian mean motion in radians per second.

mean_motion_rev_day property

mean_motion_rev_day

Return the mean motion in revolutions per day.

period_min property

period_min

Return the orbital period in minutes.

period_s property

period_s

Return the orbital period in seconds.

semi_major_axis_km property

semi_major_axis_km

Return the semi-major axis in kilometers.

__post_init__

__post_init__()

Validate fields and normalize periodic angles.

Source code in src/skyweaver/orbits.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
def __post_init__(self) -> None:
    """Validate fields and normalize periodic angles."""
    epoch_utc = _ensure_utc(self.epoch)
    object.__setattr__(self, "epoch", epoch_utc)

    if self.altitude_km <= 0.0:
        raise ValueError("altitude_km must be positive")

    if not (0.0 <= self.eccentricity < 1.0):
        raise ValueError("eccentricity must satisfy 0 <= e < 1")

    if not (0.0 <= self.inclination_deg <= 180.0):
        raise ValueError("inclination_deg must satisfy 0 <= i <= 180")

    object.__setattr__(self, "raan_deg", _wrap_angle_deg(self.raan_deg))
    object.__setattr__(
        self,
        "mean_anomaly_deg",
        _wrap_angle_deg(self.mean_anomaly_deg),
    )
    object.__setattr__(
        self,
        "arg_perigee_deg",
        _wrap_angle_deg(self.arg_perigee_deg),
    )

circular classmethod

circular(*, name, epoch, altitude_km, inclination_deg, raan_deg=0.0, phase_deg=0.0, bstar=0.0)

Construct a circular orbit.

Parameters:

Name Type Description Default
name str

Orbit name.

required
epoch datetime

Epoch of the orbit. Naive datetimes are interpreted as UTC.

required
altitude_km float

Altitude above Earth's equatorial radius.

required
inclination_deg float

Inclination in degrees.

required
raan_deg float

Right ascension of the ascending node in degrees.

0.0
phase_deg float

Orbital phase, mapped here onto mean anomaly for circular orbits.

0.0
bstar float

Optional drag term for SGP4.

0.0
Source code in src/skyweaver/orbits.py
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
@classmethod
def circular(
    cls,
    *,
    name: str,
    epoch: datetime,
    altitude_km: float,
    inclination_deg: float,
    raan_deg: float = 0.0,
    phase_deg: float = 0.0,
    bstar: float = 0.0,
) -> "OrbitSpec":
    """Construct a circular orbit.

    Parameters
    ----------
    name
        Orbit name.
    epoch
        Epoch of the orbit. Naive datetimes are interpreted as UTC.
    altitude_km
        Altitude above Earth's equatorial radius.
    inclination_deg
        Inclination in degrees.
    raan_deg
        Right ascension of the ascending node in degrees.
    phase_deg
        Orbital phase, mapped here onto mean anomaly for circular orbits.
    bstar
        Optional drag term for SGP4.
    """
    return cls(
        name=name,
        epoch=epoch,
        altitude_km=altitude_km,
        inclination_deg=inclination_deg,
        raan_deg=raan_deg,
        mean_anomaly_deg=phase_deg,
        eccentricity=0.0,
        arg_perigee_deg=0.0,
        bstar=bstar,
    )

summary

summary()

Return a compact human-readable orbit summary.

Source code in src/skyweaver/orbits.py
254
255
256
257
258
259
260
261
262
263
def summary(self) -> str:
    """Return a compact human-readable orbit summary."""
    return (
        f"OrbitSpec(name={self.name!r}, altitude_km={self.altitude_km:.1f}, "
        f"inclination_deg={self.inclination_deg:.3f}, "
        f"raan_deg={self.raan_deg:.3f}, "
        f"mean_anomaly_deg={self.mean_anomaly_deg:.3f}, "
        f"eccentricity={self.eccentricity:.6f}, "
        f"period_min={self.period_min:.2f})"
    )

to_earth_satellite

to_earth_satellite(satnum=99999)

Wrap this orbit as a Skyfield EarthSatellite.

Parameters:

Name Type Description Default
satnum int

Satellite number to assign to the underlying SGP4 record.

99999

Returns:

Type Description
EarthSatellite

Skyfield Earth satellite object.

Source code in src/skyweaver/orbits.py
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
def to_earth_satellite(self, satnum: int = 99999) -> EarthSatellite:
    """Wrap this orbit as a Skyfield `EarthSatellite`.

    Parameters
    ----------
    satnum
        Satellite number to assign to the underlying SGP4 record.

    Returns
    -------
    EarthSatellite
        Skyfield Earth satellite object.
    """
    ts = load.timescale()
    satrec = self.to_satrec(satnum=satnum)
    satellite = EarthSatellite.from_satrec(satrec, ts)
    satellite.name = self.name
    return satellite

to_satrec

to_satrec(satnum=99999)

Convert this orbit specification into an sgp4.api.Satrec.

Parameters:

Name Type Description Default
satnum int

Satellite number to assign to the record.

99999

Returns:

Type Description
Satrec

Initialized SGP4 satellite record.

Source code in src/skyweaver/orbits.py
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
def to_satrec(self, satnum: int = 99999) -> Satrec:
    """Convert this orbit specification into an `sgp4.api.Satrec`.

    Parameters
    ----------
    satnum
        Satellite number to assign to the record.

    Returns
    -------
    Satrec
        Initialized SGP4 satellite record.
    """
    jd, fr = jday_datetime(self.epoch)
    sgp4_epoch_days = (jd + fr) - SGP4_EPOCH_OFFSET_JD

    satrec = Satrec()
    satrec.sgp4init(
        WGS72,
        "i",
        satnum,
        sgp4_epoch_days,
        self.bstar,
        0.0,
        0.0,
        self.eccentricity,
        np.deg2rad(self.arg_perigee_deg),
        np.deg2rad(self.inclination_deg),
        np.deg2rad(self.mean_anomaly_deg),
        self.mean_motion_rad_min,
        np.deg2rad(self.raan_deg),
    )
    check_satrec(satrec)
    return satrec