question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Difference between the TLE and the model at the epoch of the TLE file

See original GitHub issue

When I propagate the orbit using the twoline2rv and propagate functions to the epoch day, I don’t obtain the same orbital parameters that appear on the TLE file. Am I doing something wrong or is it a limitation of the model itself?

I made the following example using the current TLE of the ISS:

from numpy import pi, sqrt
from sgp4.earth_gravity import wgs72, wgs84
from sgp4.ext import rv2coe
from sgp4.io import twoline2rv

line1 = "1 25544U 98067A   21041.71818700  .00002037  00000-0  45184-4 0  9998"
line2 = "2 25544  51.6445 248.2549 0002750 357.9058 122.1739 15.48954337268990"
rad2deg = 180/pi
G = 6.67408*10**(-20) # Gravitational constant
M = 5.9722*10**24     # Earth's mass
mu = G*M              # Standard gravitational parameter

#====================== TLE orbital parameters and epoch =====================#
TLE_i = 51.6445       # Inclination
TLE_RAAN = 248.2549   # Right Ascention of the Ascending Node
TLE_e = 0.0002750     # Eccentricity
TLE_w = 357.9058      # Argument of the Perigee
TLE_MA = 122.1739     # Mean Anomaly
TLE_MM = 15.48954337  # Mean Motion (revolutions per day)
year = 2021
month = 2
epoch_day = 41.71818700
day = epoch_day - 31
hour = (day - int(day))*24
minute = (hour - int(hour))*60
second = (minute - int(minute))*60

#=================================  SGP4 model ===============================#
sat_model = twoline2rv(line1, line2, wgs84)#wgs72)
pos, vel = sat_model.propagate(year, month, int(day),
                               int(hour), int(minute), second)
p, a, e, i, RAAN, w, theta, MA, argl, tlon, lonp = rv2coe(pos, vel, mu)

#================== Difference between the TLE and the model =================#
i_diff = abs(TLE_i - i*rad2deg)
RAAN_diff = abs(TLE_RAAN - RAAN*rad2deg)
e_diff = abs(TLE_e - e)
w_diff = abs(TLE_w - w*rad2deg)
MA_diff = abs(TLE_MA - MA*rad2deg)
a = a
n = sqrt(mu/(a**3))
period = 2*pi/n
MM = 86400/period
MM_diff = abs(TLE_MM - MM)
def print_differences():
    print("Incl. (TLE): {}°, incl. (model): {}°, diff.: {}°".format(TLE_i, i*rad2deg, i_diff))
    print("RAAN (TLE): {}°, RAAN (model): {}°, diff.: {}°".format(TLE_RAAN, RAAN*rad2deg, RAAN_diff))
    print("Eccentricity (TLE): {}, Eccentricity (model): {}, diff.: {}".format(TLE_e, e, e_diff))
    print("w (TLE): {}°, w (model): {}°, diff.: {}°".format(TLE_w, w*rad2deg, w_diff))
    print("MA (TLE): {}°, MA (model): {}°, diff.: {}°".format(TLE_MA, MA*rad2deg, MA_diff))
    print("Mean motion (TLE): {}, mean motion (model): {}, diff.: {}".format(TLE_MM, MM, MM_diff))

print_differences()

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
dcajacobcommented, Feb 11, 2021

Brandon’s intuition is correct. rv2coe returns the osculating elements, not the SGP4 elements. They’re different. He’s also correct about the generation of TLEs from state vectors. It’s not a simple process. You need to take many state vectors over time and “fit”: an estimated TLE that when propagated, minimizes the error between the resultant state vectors and the source state vectors.

On Thu, Feb 11, 2021 at 8:30 AM Brandon Rhodes notifications@github.com wrote:

Thanks, that example is simpler! So the core problem is that rv2coe() → propagate() is not performing a round trip: the orbit that comes back doesn’t propagate to the requested vectors.

I know that TLEs are produced by curve fitting (least squares or somesuch) and not from a single vector pair, but I’ve never studied how the rv2coe() parameters behave if fed back into the SGP4 propagator instead of a standard simpler Kepler routine (which presumably would produce the same vectors exactly?). The routine is only mentioned in the Report —

https://www.celestrak.com/publications/AIAA/2006-6753/AIAA-2006-6753-Rev1.pdf

— as being present for testing, and indeed I see in tests.py that it’s used to write the extended fields in the longer lines in the https://github.com/brandon-rhodes/python-sgp4/blob/master/sgp4/tcppver.out#L3 file, where not only the time and x,y,z,xdot,ydot,zdot are printed, but orbital elements showing how they evolve over the hours since the epoch.

I’m not familiar enough with the SGP4 internals (this Python library merely wraps the official C++ code) to know which internal corrections are responsible for SGP4 not behaving like a simple Kepler propagation.

If my goal were to create orbit elements that reproduced exactly a vector position and velocity, I would try starting with the rv2coe() parameters as a guess, and then use something like https://docs.scipy.org/doc/scipy/reference/optimize.html to narrow down the parameters until the output vectors at the epoch matched exactly. You might try that approach and see what happens. Studying the SGP4 source and the publications surrounding the algorithm might suggest which corrections inside of it prevent it from simply returning raw Kepler positions at a given time.

In the meantime, I’ll mark this issue as an open question; maybe someone more expert on SGP4 than I am will see the question and know more details!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/brandon-rhodes/python-sgp4/issues/86#issuecomment-777457796, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAYP3CRCTXLVLGCJTGL2WC3S6PLVTANCNFSM4XNUZZFA .

– Very Respectfully,

Dan CaJacob

1reaction
matvidalcommented, Feb 17, 2021

Thank you both @brandon-rhodes and @dcajacob for your answers. I haven’t replied because I have been doing research on this topic. I found this document from JPL that I’m studying right now: https://trs.jpl.nasa.gov/bitstream/handle/2014/44785/10-0441_A1b.pdf?sequence=1&isAllowed=y

If I implement a solution in python I will post it here. Thanks again and take care.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Two-line element set - Wikipedia
A two-line element set (TLE) is a data format encoding a list of orbital elements of an Earth-orbiting object for a given point...
Read more >
SGP4 propagator - Satellites - Agi
The SGP4 propagator generates ephemeris in the True Equator Mean Equinox coordinate system based on the epoch of the specified TLE.
Read more >
TLE · Satellite Toolbox
TLE. The TLE, or Two Line Elements set, is a data format that contains information about the orbit at a specific epoch of...
Read more >
CelesTrak: "More Frequently Asked Questions"
What is the format for the two-line element sets? ... coordinates produced by the SGP4/SDP4 orbital model is true equator, mean equinox (TEME)...
Read more >
Correcting TLEs at Epoch: Application to the GPS Constellation
In Section 3, we describe our method to correct the along-track position of a given TLE orbit and present our model's performances on...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found