Élaboration d'un calendrier de pass pour les stations terrestres avec Skyfield
Ansys STK Sunset-ready : calculez les prévisions de passage SGP4 pour votre radio amateur ou votre station au sol Cubesat à l'aide de Skyfield.
Sommaire
- Pourquoi avez-vous besoin d'un planificateur de passes local
- Installer
- Étape 1 : récupérer les TLE actuels
- Étape 2 : Définissez votre station au sol
- Étape 3 : Trouvez les événements qui augmenter/culminer/définir
- Étape 4 : décalage Doppler sur une passe
- Étape 5 : Lier le budget pour chaque pass
- Étape 6 : Émettez iCalendar pour que les passes apparaissent dans votre calendrier
- Étape 7 : Exécutez-le sur cron
- Remplacer STK Cloud, pièce par pièce
- Lectures complémentaires
Pourquoi avez-vous besoin d'un planificateur de passes local
Si vous gérez une station SatNOGS, une cabine de radioamateur qui suit l'AO-91/ISS/NOAA, ou un segment sol Cubesat à un stade précoce, vous avez besoin de prévisions de passes automatisées. Les outils commerciaux (STK, NOVA) sont excessifs. Les prédicteurs Web gratuits (AMSAT, Heavens-Above) ne scriptent pas bien. STK Cloud expirant en mars 2026, l'alternative gratuite la plus propre est Skyfield, le successeur Python moderne de PyEphem.
Cet article présente un planificateur complet de stations terrestres en environ 80 lignes de Python : récupérez de nouveaux TLE, calculez les prochaines 24 heures de passes pour une liste de satellites, filtrez par altitude minimale, calculez le Doppler pour la fréquence de votre liaison descendante et émettez iCalendar pour que les passes apparaissent dans votre application de calendrier.
Installer
pip install skyfield requests icalendar
C'est ça. Skyfield extrait ses propres éphémérides (DE421, IERS) lors de la première exécution, soit environ 17 Mo mis en cache localement.
Étape 1 : récupérer les TLE actuels
Les TLE dérivent : utilisez-les dans les 7 jours suivant l'époque. Extrayez l'ensemble d'éléments actuel de Celestrak :
from skyfield.api import load
stations_url = 'https://celestrak.org/NORAD/elements/gp.php?GROUP=amateur&FORMAT=tle'
sats = load.tle_file(stations_url)
by_name = {s.name: s for s in sats}
print(f'Loaded {len(sats)} amateur-radio satellites')
Choisissez vos cibles par leur nom (elles sont sensibles aux majuscules et minuscules dans le fichier Celestrak) :
targets = [
by_name['AO-91 (FOX-1B)'],
by_name['ISS (ZARYA)'],
by_name['NOAA 19'],
by_name['GreenCube (IO-117)'],
]
Étape 2 : Définissez votre station au sol
from skyfield.api import wgs84, load
ts = load.timescale()
my_station = wgs84.latlon(40.0150, -105.2705, elevation_m=1624) # Boulder, CO
min_elevation_deg = 10 # horizon mask to skip low passes
Utilisez le paramètre elevation_m : il affecte sensiblement la plage d'inclinaison à des angles de faible altitude.
Étape 3 : Trouvez les événements qui augmenter/culminer/définir
Satellite.find_events() renvoie une liste plate d'événements (0 = hausse, 1 = point culminant, 2 = défini). Traitez-les en trois étapes :
from datetime import timedelta
t0 = ts.now()
t1 = ts.from_datetime(t0.utc_datetime() + timedelta(hours=24))
for sat in targets:
t, events = sat.find_events(my_station, t0, t1,
altitude_degrees=min_elevation_deg)
# Group into rise/peak/set triples
triples = zip(t[0::3], t[1::3], t[2::3])
for rise, culm, setting in triples:
# Peak elevation
topo = (sat - my_station).at(culm)
alt, az, dist = topo.altaz()
print(f'{sat.name:30s} {rise.utc_iso():20s} peak {alt.degrees:4.1f}° slant {dist.km:4.0f} km')
Ignorez les satellites déjà au-dessus de l'horizon au t0(la liste des événements commence par une paire culminant/set).
Étape 4 : décalage Doppler sur une passe
Pour l'UHF amateur (435 MHz), une passe peut décaler votre porteuse de ±10 kHz ; votre récepteur doit suivre. Calculez le Doppler instantané à partir de la plage de fréquence :
import numpy as np
FREQ_HZ = 435_800_000 # AO-91 downlink
C = 299_792_458.0 # m/s
def doppler_shift(sat, observer, t):
"""Positive when satellite approaching (received frequency is higher)."""
# Numerical range rate from 1s apart
dt = 1.0 # seconds
t_next = ts.from_datetime(t.utc_datetime() + timedelta(seconds=dt))
r0 = (sat - observer).at(t).distance().m
r1 = (sat - observer).at(t_next).distance().m
range_rate = (r1 - r0) / dt # m/s, positive = moving away
return -FREQ_HZ * range_rate / C # Hz, positive = approaching
# Sample across a pass
for pct in [0, 25, 50, 75, 100]:
t_sample = ts.from_datetime(
rise.utc_datetime() + (setting.utc_datetime() - rise.utc_datetime()) * pct / 100
)
d = doppler_shift(sat, my_station, t_sample)
print(f' {pct:3d}% pass: doppler = {d:+8.0f} Hz')
Pour un passage aérien typique de 6 minutes avec l'AO-91, vous verrez un balayage Doppler d'environ +10 kHz (hausse) à 0 (zénith) et −10 kHz (réglage). Suivez-le sur le VFO principal de la radio pour ne pas perdre le signal.
Étape 5 : Lier le budget pour chaque pass
Une fois que vous avez défini la plage d'inclinaison, introduisez-la dans le calculateur de perte de trajectoire en espace libre rftools ou calculez en ligne :
def fspl_db(distance_m, freq_hz):
return 20 * np.log10(4 * np.pi * distance_m * freq_hz / C)
# At zenith of an AO-91 pass (~800 km slant at 40° elevation from Boulder)
fspl = fspl_db(800_000, FREQ_HZ)
print(f'FSPL = {fspl:.1f} dB') # ~143 dB
Pour obtenir un budget complet des liaisons Monte-Carlo avec des modèles de propagation UIT-R, utilisez le Satellite Link Budget Analyzer et partagez l'URL du scénario avec le journal de bord de votre station.
Étape 6 : Émettez iCalendar pour que les passes apparaissent dans votre calendrier
C'est là que le planificateur devient utile pour les humains :
from icalendar import Calendar, Event
from datetime import datetime
import pytz
cal = Calendar()
cal.add('prodid', '-//rftools ground station//')
cal.add('version', '2.0')
for sat in targets:
t, events = sat.find_events(my_station, t0, t1, altitude_degrees=10)
triples = zip(t[0::3], t[1::3], t[2::3])
for rise, culm, setting in triples:
topo = (sat - my_station).at(culm)
alt, az, _ = topo.altaz()
ev = Event()
ev.add('summary', f'{sat.name} (peak {alt.degrees:.0f}°)')
ev.add('dtstart', rise.utc_datetime())
ev.add('dtend', setting.utc_datetime())
ev.add('description', f'Culminate at {culm.utc_iso()}, AZ {az.degrees:.0f}°')
cal.add_component(ev)
with open('passes.ics', 'wb') as f:
f.write(cal.to_ical())
print('Wrote passes.ics — import into Google Calendar / Apple Calendar / Outlook')
Importez le passes.ics dans Apple Calendar/Google Calendar/Outlook et vous recevrez des notifications push 5 minutes avant chaque passe.
Étape 7 : Exécutez-le sur cron
Déposez le script au ~/bin/station-passes.py et crénez-le une fois par jour :
# Refresh pass schedule nightly at 03:00 local
0 3 * * * /usr/bin/python3 ~/bin/station-passes.py > ~/passes.ics 2>> ~/station.log
Associez-le au curl --upload-file à un calendrier Webdav et votre téléphone verra automatiquement chaque passe.
Remplacer STK Cloud, pièce par pièce
Pour les activités amateurs, cubesats et petites entreprises commerciales, la boîte à outils combinée remplace les fonctionnalités quotidiennes de STK Cloud :
| Fonctionnalité STK Cloud | Remplacement gratuit |
|---|---|
| Prédiction de passes | Skyfield |
| Budget du lien | Analyseur de budget de liaison satellite rftools |
| Courbes Doppler/plage | Range-rate Skyfield |
| Masques d'élévation + terrain | Skyfield + DEM local (SRTM) |
| Visualisation 3D | Cesium.js |
| Dépistage conjonctif | SOCRATES |
Lectures complémentaires
- Documentation Skyfield
- Catalogues Celestrak TLE
- rftools Satellite Pass Predictor — version hébergée de ce planificateur pour les satellites amateurs les plus courants
- Migration depuis STK Cloud : alternatives gratuites — article complémentaire sur le remplacement du flux de travail STK complet
- Dimensionnement d'un budget de liaison UHF CubeSat — exemple travaillé de bout en bout
Foire Aux Questions
Articles connexes
Scripting Satellite Link Budgets with ITU-Rpy (Python Examples)
STK-free link budgets: sweep frequency, rain availability, and elevation in pure Python with ITU-Rpy, the reference implementation of P.618/P.676/P.840.
30 avr. 2026
Satellite CommunicationsSizing a 9600-baud UHF Downlink for a 3U CubeSat: Full Walkthrough
End-to-end link budget for an amateur-band 3U cubesat: EIRP, slant range, ground-station G/T, propagation losses and Monte Carlo margin.
29 avr. 2026
Satellite CommunicationsMigrating from STK Cloud: Free Alternatives for Link Budget and Orbit Analysis
Ansys is sunsetting STK Cloud in March 2026. Here are free open-source replacements for what it did best: ITU-R link budgets and orbital pass prediction.
29 avr. 2026