Python implementation of the parametric data handling evaluation framework for autonomous lunar networks.
This repository provides an open-source Python implementation of the algorithm and case study presented in:
Rimani, J., Mascolo, L. & Fraire, J.A. "A parametric data handling evaluation framework for autonomous lunar networks." CEAS Space Journal 14, 365–376 (2022). https://doi.org/10.1007/s12567-021-00390-4
If you use this code in your research, please cite the original paper:
@article{rimani2022lunar,
title = {A parametric data handling evaluation framework for autonomous lunar networks},
author = {Rimani, Jasmine and Mascolo, Luigi and Fraire, Juan A.},
journal = {CEAS Space Journal},
volume = {14},
pages = {365--376},
year = {2022},
publisher = {Springer},
doi = {10.1007/s12567-021-00390-4}
}As space agencies race back to the Moon, selecting the right communication architecture for a lunar mission is critical. This framework evaluates three data-handling strategies for a lunar satellite network:
| Architecture | Description |
|---|---|
| Bent-Pipe (BP) | Satellite must have simultaneous line-of-sight to the lunar site AND an Earth ground station |
| Store-and-Forward (S&F) | Full data volume fits within a single contact window |
| Store-Carry-and-Forward (SC&F) | Data is stored onboard and forwarded across multiple contact windows (DTN-style) |
The framework evaluates all three over a 365-day simulation and identifies the inflection point where SC&F becomes preferable to S&F as a function of data volume D.
The paper applies the framework to a robotic mission to explore the Marius Hills skylight on the Moon, supported by a 6-satellite constellation and 3 DSN ground stations (Goldstone, Canberra, Madrid).
git clone https://github.com/JasmineRimani/lunar-network-framework.git
cd lunar-network-framework
pip install -r requirements.txtFor orbital mechanics (regenerating access windows from scratch):
pip install -r requirements.txt "astropy>=5.3" "poliastro>=0.17"from lunar_framework import (
LunarNetworkScheduler,
generate_synthetic_access_windows,
BEST_SATELLITES,
)
# Load or generate access windows
upload_windows, download_windows = generate_synthetic_access_windows(duration_days=365)
# Run the evaluation framework
scheduler = LunarNetworkScheduler(
upload_windows=upload_windows,
download_windows=download_windows,
data_volume_gbit=160.0, # D from paper baseline
satellite_filter=[s.name for s in BEST_SATELLITES], # S1_0, S2_0, S3_0
gs_filter=["Goldstone"],
)
results = scheduler.run()
print(results)
# → SimulationResults(D=160.0 Gbit | transferred=... | S&F=... (%) | SC&F=...)Run the main analysis script to regenerate Figures 5, 6, and 7 and Tables 4–6:
# Using pre-generated access windows (fastest, included in repo)
python run_analysis.py
# Using synthetic access windows (no CSV files needed)
python run_analysis.py --synthetic
# Regenerate access windows with poliastro (slow, ~30–60 min)
python run_analysis.py --regenerate
# Custom data volume sweep
python run_analysis.py --d 160 500 1000 2000 4000 8000Output figures are saved to the outputs/ directory.
lunar-network-framework/
│
├── lunar_framework/ # Main Python package
│ ├── __init__.py # Public API
│ ├── config.py # Orbital parameters (Table 2), GS coords (Table 3)
│ ├── models.py # Data models: AccessWindow, SimulationResults, …
│ ├── scheduler.py # Algorithm 1 & 2 – the core evaluation engine
│ ├── orbital_mechanics.py # poliastro-based access window generation
│ ├── io.py # CSV I/O + synthetic window generator
│ └── plots.py # Reproduce Figs 5, 6, 7
│
├── data/
│ └── access_windows/
│ ├── lunar_site_access.csv # Marius Hills ↔ satellite windows
│ └── ground_station_access.csv # DSN ↔ satellite windows
│
├── tests/
│ └── test_framework.py # 20 unit tests (pytest)
│
├── run_analysis.py # End-to-end paper reproduction script
├── requirements.txt
├── setup.py
└── README.md
All parameters are taken directly from the paper:
| Satellite | a [km] | e | i [°] | Ω [°] | ν₀ [°] |
|---|---|---|---|---|---|
| S1_0 | 6500 | 0 | 40 | 0 | 0 |
| S2_0 | 6500 | 0 | 40 | 0 | 120 |
| S3_0 | 6500 | 0 | 40 | 0 | 240 |
| S1_90 | 6500 | 0 | 40 | 90 | 0 |
| S2_90 | 6500 | 0 | 40 | 90 | 120 |
| S3_90 | 6500 | 0 | 40 | 90 | 240 |
| Station | Lat [°] | Lon [°] | Alt [m] |
|---|---|---|---|
| Goldstone | 35.4267 | −116.8900 | 1002 |
| Canberra | −35.4014 | 148.9817 | 688 |
| Madrid | 40.4314 | −4.2481 | 864 |
| Parameter | Value |
|---|---|
| Payload band | X-Band |
| Telemetry band | S-Band |
| Data rate | 150 Mbit/s |
| Compression ratio | 15:1 |
| Packet size | 6400 bits |
| Safety factor | 20 s |
The evaluation framework (Section 3.3, Fig. 2 of the paper) is implemented in scheduler.py:
- Spurious access removal – discard windows shorter than the safety threshold (Fig. 3).
- Upload phase – for each time-sorted upload opportunity (Marius Hills → satellite), assign the satellite data and classify the upload as S&F or SC&F.
- Algorithm 2 (bi-directional check) – test whether the loaded satellite can begin a download in the same window immediately after the upload completes.
- Download phase – greedy search for the earliest download window; prioritises contacts that finish soonest ("reward process").
- SC&F accumulation – if a single window is insufficient, data is carried across multiple windows until
D_rem = 0. - Satellite recycling – once a satellite completes its download, it re-enters the eligible pool for the next upload.
- Bent-Pipe covers less than 10% of available windows.
- The S&F → SC&F inflection point occurs at approximately 1.5 Tbit (single GS) and shifts to ~2.5 Tbit when all three DSN stations are used simultaneously.
- Satellites with RAAN = 0° consistently outperform those with RAAN = 90° in terms of GS access opportunities.
The original paper used STK (Systems Tool Kit) by AGI to generate satellite access windows. This repository provides two alternatives:
Statistically calibrated synthetic access windows are included in data/access_windows/. No extra dependencies needed.
from lunar_framework.orbital_mechanics import generate_all_access_windows
upload_windows, download_windows = generate_all_access_windows(
output_dir="data/access_windows",
cadence_min=10.0, # sampling cadence
duration_days=365,
)Note: Full-year computation at 10-minute cadence takes approximately 30–60 minutes. Reduce
cadence_minorduration_daysfor faster runs.
If you have access to STK and generate your own access reports, save them as CSV with columns:
t_start_s, t_end_s, satellite, partner, partner_type
Then load with:
from lunar_framework.io import load_access_windows
windows = load_access_windows("my_stk_export.csv")pytest tests/ -vAll 20 unit tests should pass in under 10 seconds.
The framework is designed to be easily adapted to new missions:
from lunar_framework import LunarNetworkScheduler
from lunar_framework.models import AccessWindow
# Custom access windows for a different mission
my_upload = [AccessWindow(...), ...]
my_download = [AccessWindow(...), ...]
scheduler = LunarNetworkScheduler(
upload_windows=my_upload,
download_windows=my_download,
data_volume_gbit=500.0,
satellite_filter=["MySat1", "MySat2"],
gs_filter=["MyGroundStation"],
)
results = scheduler.run()Changing the mission simply requires providing new access windows and configuration — no code modifications needed.
MIT License. See LICENSE for details.
The original algorithm and all mission parameters are © the paper authors (Rimani, Mascolo, Fraire 2022). This Python implementation is provided for reproducibility and community use.
For questions about the original paper, please refer to the published article.