Deep Space Propagation#

This notebook shows how to propagate TLEs with orbital period above 225 minutes (deep-space regime) and how to keep gradients enabled through propagation.

In dSGP4, deep-space satellites are selected automatically when\n \n $\(\n \frac{2\pi}{n_0} \ge 225\;\text{minutes}\n \)\(\n \n where \)n_0$ is the mean motion in rad/min.

import dsgp4
import numpy as np
import torch

1. Load a deep-space TLE#

You can use any TLE with mean motion low enough to satisfy the 225-minute rule (for example geostationary satellites).

# Replace these lines with your deep-space TLE lines.
line1 = "1 41866U 16071A   24087.50000000 -.00000149  00000+0  00000+0 0  9990"
line2 = "2 41866   0.0171  87.5375 0001375 158.4767 157.4602  1.00270055 26844"

tle = dsgp4.tle.TLE([line1, line2])

# Initialize (deep-space mode is selected automatically when applicable).
dsgp4.initialize_tle(tle, gravity_constant_name="wgs-84")

period_minutes = float(2.0 * np.pi / tle._no_unkozai)
print("method:", tle._method)
print("orbital period [min]:", period_minutes)
method: d
orbital period [min]: 1436.175046066531

2. Propagate at one or multiple epochs#

tsince = torch.tensor([0.0, 360.0, 720.0, 1440.0])  # minutes since epoch
state = dsgp4.propagate(tle, tsince, initialized=True)

# state shape: [N, 2, 3]
# row 0: position [km], row 1: velocity [km/s]
print(state.shape)
print("r(t0) [km]:", state[0, 0])
print("v(t0) [km/s]:", state[0, 1])
torch.Size([4, 2, 3])
r(t0) [km]: tensor([ 3.0597e+04,  2.9019e+04, -4.6631e+00])
v(t0) [km/s]: tensor([-2.1155e+00,  2.2307e+00, -3.2063e-04])

3. Enable gradients through deep-space propagation#

To differentiate with respect to TLE parameters, initialize with with_grad=True and backpropagate from any scalar objective.

tle = dsgp4.tle.TLE([line1, line2])
tle_elements = dsgp4.initialize_tle(
    tle,
    gravity_constant_name="wgs-84",
    with_grad=True,
)

tsince = torch.tensor(120.0)
state = dsgp4.propagate(tle, tsince, initialized=True)  # [2, 3]

# Example objective: x-position at tsince=120 min
loss = state[0, 0]
loss.backward()

# Gradient order in tle_elements:
# [bstar, ndot, nddot, ecco, argpo, inclo, mo, no_kozai, nodeo]
print(tle_elements.grad)
tensor([-3.7028e-07,  0.0000e+00,  0.0000e+00,  2.2769e+04, -4.0446e+04,
         5.4492e+01, -4.0435e+04, -6.6712e+06, -4.0446e+04])

4. Batch propagation with mixed near-earth and deep-space objects#

If a batch contains deep-space members, dSGP4 automatically falls back to a per-satellite propagation path while preserving the same API.

tles = [
    dsgp4.tle.TLE([line1, line2]),  # deep-space example
    dsgp4.tle.TLE([
        "1 25544U 98067A   24087.49097222  .00016717  00000+0  10270-3 0  9993",
        "2 25544  51.6400  82.2420 0006290  58.9900  53.5550 15.50000000000000",
    ]),
]

_, initialized = dsgp4.initialize_tle(tles, gravity_constant_name="wgs-84")
tsinces = torch.tensor([60.0, 60.0])
batch_state = dsgp4.propagate_batch(initialized, tsinces, initialized=True)
print(batch_state.shape)  # [2, 2, 3]
torch.Size([2, 2, 3])

Notes#

  • Deep-space support is available in scalar propagation and in mixed batches.

  • Gradients are supported through the deep-space scalar path.

  • For reproducibility against external implementations, use the same gravity constants and operation mode.