Two-Line Element Set
Examples showing how to use two-line element sets to generate a state vector and get geodetic position of satellite
Generate State Vector
[1]:
import satkit as sk
# The two-line element set
# Lets pick a random StarLink satellite
# The lines below were downloaded from https://www.celetrack.org
tle_lines = [
'0 STARLINK-30477',
'1 57912U 23146X 24099.49439401 .00006757 00000+0 51475-3 0 9997',
'2 57912 43.0018 157.5807 0001420 272.5369 87.5310 15.02537576 31746'
]
# Create a TLE object
starlink30477 = sk.TLE.from_lines(tle_lines)
# We want the orbital state at April 9 2024, 12:00pm UTC
thetime = sk.time(2024, 4, 9, 12, 0, 0)
# The state is output in the "TEME" frame, which is an approximate inertial
# frame that does not include precession or nutation
# pTEME is geocentric position in meters
# vTEME is geocentric velocity in meters / second
# for now we will ignore the velocity
pTEME, _vTEME = sk.sgp4(starlink30477, thetime)
# Suppose we want currrent latitude, longitude, and altitude of satellite:
# we need to rotate into an Earth-fixed frame, the ITRF
# We use a "quaternion" to represent the rotation. Quaternion rotations
# in the satkit toolbox can be represented as multiplications of a 3-vector
pITRF = sk.frametransform.qteme2itrf(thetime) * pTEME
# Now lets make a "ITRFCoord" object to extract geodetic coordinates
coord = sk.itrfcoord(pITRF)
# Get the latitude, longitude, and
# altitude (height above ellipsoid, or hae) of the satellite
print(coord)
ITRFCoord(lat: 29.3890 deg, lon: 170.8051 deg, hae: 560.11 km)
Plot satellite ground track
[2]:
import satkit as sk
import numpy as np
import plotly.graph_objects as go
# The two-line element set
# Same satellite as above...
# The lines below were downloaded from https://www.celetrack.org
tle_lines = [
'0 STARLINK-30477',
'1 57912U 23146X 24099.49439401 .00006757 00000+0 51475-3 0 9997',
'2 57912 43.0018 157.5807 0001420 272.5369 87.5310 15.02537576 31746'
]
# Create a TLE object
starlink30477 = sk.TLE.from_lines(tle_lines)
# We want the orbital state at April 9 2024, 12:00pm UTC
thetime = sk.time(2024, 4, 9, 12, 0, 0)
# plot for 5 orbits. The mean motion in the TLE is number of orbits in a day
timearr = np.array([thetime + sk.duration(days=x) for x in np.linspace(0, 5/starlink30477.mean_motion, 1000)])
# Get position in the TEME frame
pTEME, _vTEME = sk.sgp4(starlink30477, timearr)
qarr = sk.frametransform.qteme2itrf(timearr)
pITRF = np.array([q * p for q, p in zip(qarr, pTEME)])
coord = [sk.itrfcoord(p) for p in pITRF]
lat, lon, alt = zip(*[(c.latitude_deg, c.longitude_deg, c.altitude) for c in coord])
fig = go.Figure()
fig.add_trace(go.Scattergeo(lat=lat, lon=lon, mode='lines'))
fig.update_layout(margin={"r":0,"t":40,"l":0,"b":0}, title='Ground Track', geo=dict(showland=True, showcountries=True))
fig.show()
fig = go.Figure()
fig.add_trace(go.Scatter(x=[t.datetime() for t in timearr], y=np.array(alt)/1e3, mode='lines'))
fig.update_layout(yaxis_title='Altitude (km)', xaxis_title='Time', font=dict(size=14), title='Altitude vs Time')
fig.show()