A modular and extensible LEO network simulation platform to explore traffic flow, throughput, stretch/latency, and coverage. LEOCraft operates at flow level to evaluate a given LEO constellation quickly.
Clone the LEOCraft repository.
git clone https://github.com/suvambasak/LEOCraft.git
Change the directory.
cd LEOCraft
Create a conda environment from environment.yml or environment_macOS.yml.
conda env create -f tools/environment.yml
or
conda env create -f tools/environment_macOS.yml
Activate leocraft
environment.
conda activate leocraft
Since LEOCraft
is a flow-level simulator, it uses Gurobi Optimizer to solve the linear program of throughput maximization. To set Gurobi Optimizer:
Extract the license tools licensetools12.0.1_linux64.tar.gz or download the license tools based on your platform to the binary grbgetkey
.
Sign up and generate free Named-User Academic license.
To save the license on your system, execute the following.
./grbgetkey <LICENSE_KEY>
Enter and store the gurobi.lic
file in the home directory.
info : grbgetkey version 12.0.1, build v12.0.1rc0
info : Platform is linux64 (linux) - "Linux Mint 22.1"
info : Contacting Gurobi license server...
info : License file for license ID XXXXXXX was successfully retrieved
info : License expires at the end of the day on XXXX-XX-XX
info : Saving license file...
In which directory would you like to store the Gurobi license file?
[hit Enter to store it in /home/suvam]:
Export the LEOCraft
project path in the shell, which will allow seamless execution of scripts.
export PYTHONPATH=$(pwd)
Or, for instance, if the repository is cloned at /mnt/Storage/Projects/LEOCraft
export PYTHONPATH="/mnt/Storage/Projects/LEOCraft"
To validate the simulation environment setup, execute example_starlink.py, which simulates the Starlink multi-shell LEO constellation.
python examples/example_starlink.py
The LEOCraft
setup is successful if you see something like this.
[LEOConstellation] Building ground stations...
[LEOConstellation] Building shells...
[LEOConstellation] Building ground to satellite links...
[LEOConstellation] GSLs generated in: 0.08m
[LEOConstellation] Adding satellites into network graph...
[LEOConstellation] Adding ISLs into network graph...
[LEOConstellation] Routes generated in: 2.2m
[Throughput] Building throughput...
[Throughput] Computing throughput...
LP formation...Set parameter Username
Academic license - for non-commercial use only - expires XXXX-XX-XX
[Throughput] Optimized in: 0.11m
[Throughput] Throughput: 6144.55 Gbps
[Throughput] Total accommodated flow: 30.562 %
[Throughput] NS path selection: 5.929 %
[Throughput] EW path selection: 3.848 %
[Throughput] NESW path selection: 5.325 %
[Throughput] HG path selection: 2.601 %
[Throughput] LG path selection: 7.466 %
[Coverage] Building coverage...
[Coverage] Computing coverage...
[Coverage] Out of coverage GS: 0
[Coverage] GS coverage metric: 148.79394673481124
[Stretch] Building stretch...
[Stretch] Computing stretch...
[Stretch] NS stretch: 1.357
[Stretch] NS hop count: 7.0
[Stretch] EW stretch: 1.504
[Stretch] EW hop count: 8.0
[Stretch] NESW stretch: 1.253
[Stretch] NESW hop count: 6.0
[Stretch] LG stretch: 1.434
[Stretch] LG hop count: 3.5
[Stretch] HG stretch: 1.181
[Stretch] HG hop count: 11.0
Total simulation time: 2.44m
To run the unit tests, follow the instructions in tests.
Here is the quick overview simulating an LEO constellation network of Starlink.
First, import the LEOCraft modules.
from LEOCraft.attenuation.fspl import FSPL
from LEOCraft.constellations.LEO_constellation import LEOConstellation
from LEOCraft.dataset import GroundStationAtCities
from LEOCraft.satellite_topology.plus_grid_shell import PlusGridShell
from LEOCraft.user_terminals.ground_station import GroundStation
Create an instance of the atmospherics path loss model.
loss_model = FSPL(
28.5*1000000000, # Frequency in Hz
98.4, # Tx power dBm
0.5*1000000000, # Bandwidth Hz
13.6 # G/T ratio
)
loss_model.set_Tx_antenna_gain(gain_dB=34.5)
To create a LEO constellation of Starlink, create an object of LEO constellation, add ground stations, and then add the first shell of Starlink of +Grid topology.
leo_con = LEOConstellation('Starlink')
leo_con.add_ground_stations(
GroundStation(
GroundStationAtCities.TOP_100
)
)
leo_con.add_shells(
PlusGridShell(
id=0,
orbits=72,
sat_per_orbit=22,
altitude_m=550000.0,
inclination_degree=53.0,
angle_of_elevation_degree=25.0,
phase_offset=50.0
)
)
leo_con.set_time(second=3) # Time passed after epoch
leo_con.set_loss_model(loss_model)
leo_con.build()
leo_con.create_network_graph()
leo_con.generate_routes()
You will see this on the execution.
[LEOConstellation] Building ground stations...
[LEOConstellation] Building shells...
[LEOConstellation] Building ground to satellite links...
[LEOConstellation] GSLs generated in: 0.11m
[LEOConstellation] Adding satellites into network graph...
[LEOConstellation] Adding ISLs into network graph...
[LEOConstellation] Routes generated in: 2.83m
To measure the throughput of the above Starlink constellation, import the following modules.
from LEOCraft.dataset import InternetTrafficAcrossCities
from LEOCraft.performance.basic.throughput import Throughput
Create the instance of throughput, then add the instance of Starlink constellation and traffic matrics across the ground stations to compute the throughput.
th = Throughput(
leo_con,
InternetTrafficAcrossCities.ONLY_POP_100
)
th.build()
th.compute()
The output will be as follows.
[Throughput] Building throughput...
[Throughput] Computing throughput...
LP formation...Set parameter Username
Set parameter LicenseID to value XXXXXXX
Academic license - for non-commercial use only - expires 20XX-XX-XX
[Throughput] Optimized in: 0.02m
[Throughput] Throughput: 2820.032 Gbps
[Throughput] Total accommodated flow: 15.209 %
[Throughput] NS path selection: 1.77 %
[Throughput] EW path selection: 1.455 %
[Throughput] NESW path selection: 1.916 %
[Throughput] HG path selection: 0.999 %
[Throughput] LG path selection: 6.945 %
To measure stretch, import the following module.
from LEOCraft.performance.basic.stretch import Stretch
Create an instance of stretch and add the instance of Starlink constellation to compute stretch.
sth = Stretch(leo_con)
sth.build()
sth.compute()
The output will be as follows.
[Stretch] Building stretch...
[Stretch] Computing stretch...
[Stretch] NS stretch: 1.868
[Stretch] NS hop count: 8.0
[Stretch] EW stretch: 1.668
[Stretch] EW hop count: 8.0
[Stretch] NESW stretch: 1.285
[Stretch] NESW hop count: 6.0
[Stretch] LG stretch: 1.479
[Stretch] LG hop count: 4.0
[Stretch] HG stretch: 1.263
[Stretch] HG hop count: 12.0
To measure the coverage of the constellation, import the following module.
from LEOCraft.performance.basic.stretch import Stretch
Create an instance of coverage and add the instance of Starlink constellation to compute coverage.
cov = Coverage(leo_con)
cov.build()
cov.compute()
The output will be as follows.
[Coverage] Building coverage...
[Coverage] Computing coverage...
[Coverage] Out of coverage GS: 0
[Coverage] GS coverage metric: 111.9799753395037
The LEOCraft provides excellent 2D and 3D interactive visualization capabilities to intuitively understand the LEO network topology and the transition of topology with LEO dynamics.
To visualize Starlink constellation in 2D, use the SatView2D
module. Add the components (satellites, ground stations, routes, satellite coverage, etc.) for rendering, as shown below.
from LEOCraft.visuals.sat_view_2D import SatView2D
view = SatView2D(leo_con, default_zoom=2.0)
view.add_all_satellites()
view.add_coverages('S0-0', 'S0-1', 'S0-40', 'S0-31', 'S0-30')
view.add_routes('G-0_G-1', 'G-1_G-2', 'G-2_G-3', 'G-30_G-33', k=1)
view.build()
view.export_html('docs/html/Starlink_2D.html')
The output will be as follows.
[SatView2D] Building view 2D...
[SatView2D] Exporting HTML...
The interactive 2D visualization Starlink_2D.html.
To visualize the Starlink constellation in 3D, use the SatView3D
module. Add the add the components (satellites, ground stations, routes, satellite coverage, etc) for rendering as shown in the following.
from LEOCraft.visuals.sat_view_3D import SatView3D
view = SatView3D(leo_con)
view.add_all_satellites()
view.add_routes('G-0_G-1', 'G-1_G-2', 'G-2_G-3', 'G-30_G-33', k=1)
view.build()
view.export_html('docs/html/Starlink_3D.html')
The output will be as follows.
[SatView3D] Building raw view 3D...
[SatView3D] Exporting HTML...
The interactive 2D visualization Starlink_3D.html.
To visualize the Starlink constellation in 3D but without maps and satellites at elevation, use the SatRawView3D
module. Add the components (satellites, ground stations, routes, satellite coverage, etc.) for rendering, as shown below.
from LEOCraft.visuals.sat_raw_view_3D import SatRawView3D
view = SatRawView3D(
leo_con,
lat=16.80528,
long=96.15611,
elevation_m=550000
)
view.add_all_satellites()
view.add_routes('G-0_G-1', k=1)
view.build()
view.export_html('docs/html/Starlink_RAW_3D.html')
The output will be as follows.
[SatRawView3D] Building raw view 3D...
[SatRawView3D] Exporting HTML...
The interactive 2D visualization Starlink_RAW_3D.html.
Following are some examples of interactive LEO network visualisation. A few videos of LEO dynamics are also available at LEOCraft Playlist.
A handful of examples of Python scripts for programming the LEO network simulation and generating interactive visuals are available in examples.
LEOCraft is designed with modularity and extensibility at its core. Whether you’re exploring custom satellite constellations, novel inter-satellite routing schemes, new traffic models, or advanced performance metrics, LEOCraft provides the scaffolding to implement and test your ideas quickly and rigorously.
Dive into the API documentation to understand the architecture and core components of LEOCraft—from constellation modeling and link computation to routing and performance evaluation.
Check out the traffic dataset source to learn how Internet demand between cities is modeled and how you can plug in your own demand matrices or traffic sources.
This work is licensed under the MIT License.
Basak, S., Pal, A. and Bhattacherjee, D., 2025. {LEOCraft}: Towards Designing Performant {LEO} Networks. In 2025 USENIX Annual Technical Conference (USENIX ATC 25) (pp. 789-813).
@inproceedings{LEOCraft,
title={$\{$LEOCraft$\}$: Towards Designing Performant $\{$LEO$\}$ Networks},
author={Basak, Suvam and Pal, Amitangshu and Bhattacherjee, Debopam},
booktitle={2025 USENIX Annual Technical Conference (USENIX ATC 25)},
pages={789--813},
year={2025}
}
For executing the experiments and regenerating the figures in the paper, straightforward steps are given in ARTIFACT EVALUATION.
Contributors whose support and expertise have been invaluable in the development of LEOCraft: