Overview & Extraction Notes
This paper represents the most significant effort to reconcile 25 years of divergent SGP4 implementations. It documents the bugs, provides corrected C++ and FORTRAN 90 source code, supplies 518 test vectors across 29 satellites, and formally defines the TEME coordinate frame that SGP4 output occupies.
Why This Paper Exists
Section titled “Why This Paper Exists”Spacetrack Report No. 3 (1980) contained the canonical SGP4/SDP4 algorithms, but no authoritative digital source files were ever distributed. Over the following quarter century, independent reimplementations introduced divergent bugs, and compensating fixes were applied without coordination. By the early 2000s, multiple organizations ran code that all claimed to be “SGP4” but produced materially different results.
The divergence was partly a consequence of the transcription problem — the invisible column 72 boundary in FORTRAN IV fixed-format source, combined with the absence of any authoritative digital distribution.
Rev-1 was the first comprehensive effort to:
- Document the specific bugs and their orbital effects
- Provide corrected source code in both FORTRAN 90 and C++
- Supply extensive test cases covering edge cases and failure modes
- Define the TEME coordinate frame precisely enough for interoperability
- Establish a baseline that the broader community could synchronize against
The “Official” vs. “Unofficial” Problem
Section titled “The “Official” vs. “Unofficial” Problem”By 2006, three major public versions were in circulation:
| Version | Origin | Key Differences |
|---|---|---|
| STR#3 (1980) | AFSPC standalone | Mixed precision, original bugs |
| GSFC (1996) | NASA Goddard / SeaWiFS | Some fixes from 1990 standalone |
| Dundee (Crawford) | Independent researcher | Most comprehensive external fix history |
These differed in their handling of the secular integrator, Kepler convergence criteria, Lyddane singularity, and negative inclination values. Rev-1 synthesized insights from all three into a single non-proprietary version believed to be compatible with the operational code.
Single vs. Double Precision
Section titled “Single vs. Double Precision”The original STR#3 FORTRAN mixed single-precision and double-precision arithmetic. Rev-1 uses full double precision throughout, eliminating an entire class of precision-related discrepancies. This is the primary cause of the 1—2 km differences observed when comparing Rev-1 output against the original test vectors.
Key Bugs Fixed
Section titled “Key Bugs Fixed”Rev-1 documents five categories of bugs, each demonstrated by specific satellite numbers that triggered the failure:
1. Lyddane Singularity
Section titled “1. Lyddane Singularity”Affected satellites: 04632, 14128, 20413, 23177, 23599
The Lyddane modification to Brouwer’s theory introduces a singularity at low inclination that the original code did not guard against. These satellites, with near-equatorial orbits, caused division-by-zero or catastrophic cancellation in the short-period corrections.
2. Negative Inclination
Section titled “2. Negative Inclination”Affected satellites: 25954, 28626
The TLE fitting process occasionally produces slightly negative inclination values. The original code assumed and computed and without bounds checking, leading to sign errors that propagated through the perturbation calculations.
3. Secular Integrator State Saving
Section titled “3. Secular Integrator State Saving”Affected satellite: 09880
The deep-space secular integrator uses a 720-minute step size and must save its state between calls. The original code had a state-saving bug where the integrator’s accumulated perturbations were not properly preserved across propagation calls, producing discontinuous jumps for deep-space objects.
4. Kepler’s Equation Convergence
Section titled “4. Kepler’s Equation Convergence”Affected satellite: 23333
For high-eccentricity orbits (), the Newton-Raphson iteration in the original code could fail to converge within 10 iterations. Rev-1 improved the convergence logic and increased the iteration limit for these cases. Satellite 23333 is a Molniya-type orbit with that exposed the boundary of the original solver.
5. Perigee Height Thresholds
Section titled “5. Perigee Height Thresholds”The original code used three perigee height thresholds (98, 156, and 220 km) to select different atmospheric drag treatments. The threshold logic contained off-by-one comparisons that could select the wrong drag regime for satellites near these boundaries.
TEME Coordinate Frame
Section titled “TEME Coordinate Frame”Before Rev-1, SGP4 output was loosely described as “ECI” (Earth-Centered Inertial) without specifying which of several possible inertial frames was meant. Rev-1 formally defined the output frame as TEME — True Equator, Mean Equinox — characterized by:
- True equator: the instantaneous Earth equatorial plane including nutation
- Mean equinox: a simplified equinox direction using only 4 of the 106 IAU-80 nutation terms
- Not J2000: TEME is a “of date” frame that rotates slowly relative to J2000
- Not TOD: TOD uses all 106 nutation terms; TEME uses only 4
The Appendix C provides the complete transformation matrices for converting TEME to J2000 and ITRF, including worked numerical examples.
Nutation at Propagation Time vs. TLE Epoch
Section titled “Nutation at Propagation Time vs. TLE Epoch”A subtle question: when computing the TEME-to-J2000 transformation, should the nutation matrix be evaluated at the propagation time or at the TLE epoch? Rev-1 demonstrates that this choice produces a 23.6 m position difference over just 3 days. The “of date” approach (nutation at propagation time) is the correct one.
Test Case Design
Section titled “Test Case Design”Rev-1 provides 29 test satellites (expanded from STR#3’s single near-earth and single deep-space test case) covering the full range of orbital regimes:
| Category | Count | What It Tests |
|---|---|---|
| Near-earth normal | 8 | Standard LEO propagation |
| Low perigee | 4 | Atmospheric drag regime selection |
| Decaying orbits | 3 | Orbital decay and re-entry handling |
| 12-hour resonance | 4 | Molniya-type deep-space resonance |
| 24-hour resonance | 3 | GEO-type resonance |
| Low inclination | 3 | Lyddane singularity region |
| High eccentricity | 2 | Kepler convergence stress |
| Sub-orbital | 2 | Below 100 km perigee |
The complete test case data (518 vectors) is provided in Appendix D and Appendix E.
Cross-Reference: STR#3 vs. Rev-1
Section titled “Cross-Reference: STR#3 vs. Rev-1”| Aspect | STR#3 (1980) | Rev-1 (2006/2008) |
|---|---|---|
| Language | FORTRAN IV (fixed format) | FORTRAN 90 + C++ |
| Precision | Mixed single/double | Full double precision |
| Test cases | 25 vectors, 2 satellites | 518 vectors, 29 satellites |
| Constants | WGS-72 hardcoded | WGS-72 and WGS-84 selectable |
| Output frame | Undefined “ECI” | TEME (formally defined) |
| Integrator | 720-min step, state bug | 720-min step, state bug fixed |
| Kepler iteration | 10 max, no guard | Improved convergence for high |
| Lyddane fix | None | Singularity guard for |
Extraction Inventory
Section titled “Extraction Inventory”| Component | Files | Content |
|---|---|---|
| Main body | 9 | Sections I—VII (590 lines of transcribed text) |
| Appendix A | 1 | Organization comparison table |
| Appendix B | 1 | TLE format specification |
| Appendix C | 1 | TEME coordinate frame definition and transformations |
| Appendix D | 1 | 29 test satellite TLEs with metadata |
| Appendix E | 1 | 518 test vectors (position and velocity) |