Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ print(states.shape) # (2, 2, 3)
- Time input (`tsince`) is in minutes from the TLE epoch.
- Output units are km (position) and km/s (velocity).
- Supported gravity constants: `wgs-72`, `wgs-84`, `wgs-72old`.
- Deep-space propagation is currently not supported (periods above 225 minutes).
- Deep-space propagation is supported.
- Default torch dtype is set to `float64` when importing `dsgp4`.

## Development
Expand Down
176 changes: 176 additions & 0 deletions doc/notebooks/deep_space_propagation.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "7d660414",
"metadata": {},
"source": [
"# Deep Space Propagation\n",
"\n",
"This notebook shows how to propagate TLEs with orbital period above 225 minutes (deep-space regime) and how to keep gradients enabled through propagation.\n",
"\n",
"In dSGP4, deep-space satellites are selected automatically when\\n\n",
"\\n\n",
"$$\\n\n",
"\\frac{2\\pi}{n_0} \\ge 225\\;\\text{minutes}\\n\n",
"$$\\n\n",
"\\n\n",
"where $n_0$ is the mean motion in rad/min."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3e2e1e65",
"metadata": {},
"outputs": [],
"source": [
"import dsgp4\n",
"import numpy as np\n",
"import torch"
]
},
{
"cell_type": "markdown",
"id": "5f44d3e7",
"metadata": {},
"source": [
"## 1. Load a deep-space TLE\n",
"\n",
"You can use any TLE with mean motion low enough to satisfy the 225-minute rule (for example geostationary satellites)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "45671b5d",
"metadata": {},
"outputs": [],
"source": [
"# Replace these lines with your deep-space TLE lines.\n",
"line1 = \"1 41866U 16071A 24087.50000000 -.00000149 00000+0 00000+0 0 9990\"\n",
"line2 = \"2 41866 0.0171 87.5375 0001375 158.4767 157.4602 1.00270055 26844\"\n",
"\n",
"tle = dsgp4.tle.TLE([line1, line2])\n",
"\n",
"# Initialize (deep-space mode is selected automatically when applicable).\n",
"dsgp4.initialize_tle(tle, gravity_constant_name=\"wgs-84\")\n",
"\n",
"period_minutes = float(2.0 * np.pi / tle._no_unkozai)\n",
"print(\"method:\", tle._method)\n",
"print(\"orbital period [min]:\", period_minutes)"
]
},
{
"cell_type": "markdown",
"id": "d124e84d",
"metadata": {},
"source": [
"## 2. Propagate at one or multiple epochs"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f2746b3d",
"metadata": {},
"outputs": [],
"source": [
"tsince = torch.tensor([0.0, 360.0, 720.0, 1440.0]) # minutes since epoch\n",
"state = dsgp4.propagate(tle, tsince, initialized=True)\n",
"\n",
"# state shape: [N, 2, 3]\n",
"# row 0: position [km], row 1: velocity [km/s]\n",
"print(state.shape)\n",
"print(\"r(t0) [km]:\", state[0, 0])\n",
"print(\"v(t0) [km/s]:\", state[0, 1])"
]
},
{
"cell_type": "markdown",
"id": "d0dd15f2",
"metadata": {},
"source": [
"## 3. Enable gradients through deep-space propagation\n",
"\n",
"To differentiate with respect to TLE parameters, initialize with `with_grad=True` and backpropagate from any scalar objective."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e16a0407",
"metadata": {},
"outputs": [],
"source": [
"tle = dsgp4.tle.TLE([line1, line2])\n",
"tle_elements = dsgp4.initialize_tle(\n",
" tle,\n",
" gravity_constant_name=\"wgs-84\",\n",
" with_grad=True,\n",
")\n",
"\n",
"tsince = torch.tensor(120.0)\n",
"state = dsgp4.propagate(tle, tsince, initialized=True) # [2, 3]\n",
"\n",
"# Example objective: x-position at tsince=120 min\n",
"loss = state[0, 0]\n",
"loss.backward()\n",
"\n",
"# Gradient order in tle_elements:\n",
"# [bstar, ndot, nddot, ecco, argpo, inclo, mo, no_kozai, nodeo]\n",
"print(tle_elements.grad)"
]
},
{
"cell_type": "markdown",
"id": "5e026f59",
"metadata": {},
"source": [
"## 4. Batch propagation with mixed near-earth and deep-space objects\n",
"\n",
"If a batch contains deep-space members, dSGP4 automatically falls back to a per-satellite propagation path while preserving the same API."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "33cf0709",
"metadata": {},
"outputs": [],
"source": [
"tles = [\n",
" dsgp4.tle.TLE([line1, line2]), # deep-space example\n",
" dsgp4.tle.TLE([\n",
" \"1 25544U 98067A 24087.49097222 .00016717 00000+0 10270-3 0 9993\",\n",
" \"2 25544 51.6400 82.2420 0006290 58.9900 53.5550 15.50000000000000\",\n",
" ]),\n",
"]\n",
"\n",
"_, initialized = dsgp4.initialize_tle(tles, gravity_constant_name=\"wgs-84\")\n",
"tsinces = torch.tensor([60.0, 60.0])\n",
"batch_state = dsgp4.propagate_batch(initialized, tsinces, initialized=True)\n",
"print(batch_state.shape) # [2, 2, 3]"
]
},
{
"cell_type": "markdown",
"id": "7ff97818",
"metadata": {},
"source": [
"## Notes\n",
"\n",
"- Deep-space support is available in scalar propagation and in mixed batches.\n",
"- Gradients are supported through the deep-space scalar path.\n",
"- For reproducibility against external implementations, use the same gravity constants and operation mode."
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
1 change: 1 addition & 0 deletions doc/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ for more complex tasks.
.. toctree::
:maxdepth: 1

notebooks/deep_space_propagation.ipynb
notebooks/covariance_transformation.ipynb
notebooks/covariance_propagation.ipynb
notebooks/gradient_based_optimization.ipynb
Loading
Loading