Downloading & Visualizing TLE Data For Starlink Satellites
Slow Page
This page may load slowly due to the embedded interactive 3D plot. Please be patient while it loads.
This example demonstrates how to download Two-Line Element (TLE) data from the CelesTrak dataset using the Brahe library, and then visualize the complete Starlink satellite constellation in an interactive 3D plot.
Initialize Earth Orientation Parameters
Before starting, we need to import brahe and ensure that we have Earth orientation parameters initialized. We'll use initialize_eop(), which provides a CachingEOPProvider to deliver up-to-date Earth orientation parameters.
| import time
import brahe as bh
bh.initialize_eop()
|
Download Starlink TLEs
We'll use the CelesTrak dataset to fetch the latest TLE data for all Starlink satellites. The get_tles_as_propagators function downloads the data and creates SGP4 propagators in one step:
| propagators = bh.datasets.celestrak.get_tles_as_propagators("starlink", 60.0)
# Filter out any re-enerting spacecraft with < 350 km semi-major axis
# This can sometimes cause numerical issues with the propagator for very low orbit
# when eccentricity becomes negative.
propagators = [
prop for prop in propagators if prop.semi_major_axis >= (bh.R_EARTH + 350.0e3)
]
|
Inspect Satellite Data
Let's examine the properties of the first satellite to understand the orbital parameters:
| # Inspect the first satellite
first_sat = propagators[0]
print(f"\nFirst satellite: {first_sat.get_name()}")
print(f"Epoch: {first_sat.epoch}")
print(f"Semi-major axis: {first_sat.semi_major_axis / 1000:.1f} km")
print(f"Inclination: {first_sat.inclination:.1f} degrees")
print(f"Eccentricity: {first_sat.eccentricity:.6f}")
|
Visualize in 3D
We'll create an interactive 3D visualization of the entire Starlink constellation using Plotly. We'll use the Natural Earth 50m texture for a realistic Earth representation:
| fig = bh.plot_trajectory_3d(
[], # Empty trajectory list; we'll add markers for each satellite
units="km",
show_earth=True,
earth_texture="natural_earth_50m",
backend="plotly",
view_azimuth=45.0,
view_elevation=30.0,
view_distance=3.0,
sphere_resolution_lon=600, # Reduce sphere texture resolution for performance
sphere_resolution_lat=300,
)
|
Finally, we'll add points for all satellites at the current epoch:
| # Get the current time for display
epc = bh.Epoch.now()
# For each satellite, add a marker at the current position
for prop in propagators:
state = prop.state_eci(epc)
fig.add_scatter3d(
x=[state[0] / 1000],
y=[state[1] / 1000],
z=[state[2] / 1000],
mode="markers",
marker=dict(size=2, color="white"),
name=prop.get_name(),
showlegend=False,
)
|
The resulting plot shows the complete Starlink constellation orbiting Earth. The interactive visualization allows you to rotate, zoom, and pan to explore the satellite positions from different angles.
Full Code Example
| visualizing_starlink.py |
|---|
| import time
import brahe as bh
bh.initialize_eop()
# Download TLE data for all Starlink satellites from CelesTrak
# The get_tles_as_propagators function:
# - Downloads latest TLE data (cached for 6 hours)
# - Parses each TLE into an SGP4 propagator
# - Sets default propagation step size (60 seconds)
print("Downloading Starlink TLEs from CelesTrak...")
start_time = time.time()
propagators = bh.datasets.celestrak.get_tles_as_propagators("starlink", 60.0)
# Filter out any re-enerting spacecraft with < 350 km semi-major axis
# This can sometimes cause numerical issues with the propagator for very low orbit
# when eccentricity becomes negative.
propagators = [
prop for prop in propagators if prop.semi_major_axis >= (bh.R_EARTH + 350.0e3)
]
elapsed = time.time() - start_time
print(
f"Initialized propagators for {len(propagators)} Starlink satellites in {elapsed:.2f} seconds."
)
# Inspect the first satellite
first_sat = propagators[0]
print(f"\nFirst satellite: {first_sat.get_name()}")
print(f"Epoch: {first_sat.epoch}")
print(f"Semi-major axis: {first_sat.semi_major_axis / 1000:.1f} km")
print(f"Inclination: {first_sat.inclination:.1f} degrees")
print(f"Eccentricity: {first_sat.eccentricity:.6f}")
# Create interactive 3D plot with Earth texture
print("\nCreating 3D visualization of satellites...")
ts = time.time()
fig = bh.plot_trajectory_3d(
[], # Empty trajectory list; we'll add markers for each satellite
units="km",
show_earth=True,
earth_texture="natural_earth_50m",
backend="plotly",
view_azimuth=45.0,
view_elevation=30.0,
view_distance=3.0,
sphere_resolution_lon=600, # Reduce sphere texture resolution for performance
sphere_resolution_lat=300,
)
te = time.time() - ts
print(f"Created base 3D plot in {te:.2f} seconds.")
ts = time.time()
# Get the current time for display
epc = bh.Epoch.now()
# For each satellite, add a marker at the current position
for prop in propagators:
state = prop.state_eci(epc)
fig.add_scatter3d(
x=[state[0] / 1000],
y=[state[1] / 1000],
z=[state[2] / 1000],
mode="markers",
marker=dict(size=2, color="white"),
name=prop.get_name(),
showlegend=False,
)
te = time.time() - ts
print(f"Added satellite markers in {te:.2f} seconds.")
|
See Also