Skip to content
RFrftools.io
Satellite Communications30. April 20264 Min. Lesezeit

Erstellung eines Fahrplans für Bodenstations-Pässe mit Skyfield

Ansys STK ist bereit für den Sonnenuntergang: Berechnen Sie mithilfe von Skyfield SGP4-Passvorhersagen für Ihr Amateurfunkgerät oder Ihre CubeSat-Bodenstation.

Inhalt

Warum brauchst du einen lokalen Passplaner

Wenn Sie eine SatNOGS-Station, eine Amateurfunkhütte, die AO-91/ISS/NOAA verfolgt, oder ein Cubesat-Bodensegment im Frühstadium betreiben, benötigen Sie automatische Passvorhersagen. Kommerzielle Tools (STK, NOVA) sind übertrieben. Die kostenlosen Web-Prädiktoren (AMSAT, Heavens-Above) schreiben nicht gut. Da STK Cloud im März 2026 untergeht, ist Skyfield — der moderne Python-Nachfolger von PyEphem — die sauberste kostenlose Alternative.

In diesem Beitrag wird ein vollständiger Bodenstationsplaner in etwa 80 Python-Zeilen beschrieben: Holen Sie sich neue TLEs, berechnen Sie die Pässe der nächsten 24 Stunden für eine Satellitenliste, filtern Sie nach Mindesthöhe, berechnen Sie den Doppler für Ihre Downlink-Frequenz und senden Sie iCalendar aus, sodass Pässe in Ihrer Kalender-App erscheinen.

Installieren

pip install skyfield requests icalendar

Das war's. Skyfield ruft beim ersten Durchlauf seine eigenen Ephemeriden (DE421, IERS) ab — etwa 17 MB werden lokal zwischengespeichert.

Schritt 1: Aktuelle TLEs abrufen

TLEs driften — benutze sie innerhalb von 7 Tagen nach der Epoche. Ruft den aktuellen Elementsatz von Celestrak ab:

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')

Wählen Sie Ihre Ziele nach Namen aus (in der Celestrak-Datei wird zwischen Groß- und Kleinschreibung unterschieden):

targets = [
    by_name['AO-91 (FOX-1B)'],
    by_name['ISS (ZARYA)'],
    by_name['NOAA 19'],
    by_name['GreenCube (IO-117)'],
]

Schritt 2: Definiere deine Bodenstation

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

Verwenden Sie den Parameter elevation_m— er wirkt sich erheblich auf den Neigungsbereich bei niedrigen Höhenwinkeln aus.

Schritt 3: Finden Sie Ereignisse, die auf-, kulminieren und untergehen

Satellite.find_events() gibt eine einfache Liste von Ereignissen zurück (0 = Anstieg, 1 = Höhepunkt, 2 = Beginn). Verarbeite sie dreifach:
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')

Ignoriere Satelliten, die sich bereits über dem Horizont bei t0 befinden (die Eventliste beginnt mit einem Kulminat-/Satzpaar).

Schritt 4: Doppler-Shift über einen Pass

Bei Amateur-UHF (435 MHz) kann ein Durchgang Ihren Mobilfunkanbieter um ±10 kHz verschieben — Ihr Receiver muss das verfolgen. Berechnung des Momentan-Dopplers anhand der Reichweitenrate:

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')

Bei einem typischen 6-minütigen AO-91-Overhead-Pass werden Sie einen Doppler-Sweep von etwa +10 kHz (Anstieg) über 0 (Zenit) bis −10 kHz (eingestellt) sehen. Verfolgen Sie dies auf dem Haupt-VFO des Funkgeräts, damit Sie kein Signal verlieren.

Schritt 5: Verknüpfen Sie das Budget für jeden Pass

Sobald Sie den Neigungsbereich ermittelt haben, geben Sie ihn in den rftools Free-Space Path Loss Calculator ein oder berechnen Sie ihn direkt:

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

Für ein vollständiges Monte-Carlo-Link-Budget mit ITU-R-Ausbreitungsmodellen verwenden Sie den Satellite Link Budget Analyzer und teilen Sie die Szenario-URL mit Ihrem Stationslogbuch.

Schritt 6: Senden Sie iCalendar aus, damit die Pässe in Ihrem Kalender erscheinen

Hier wird der Scheduler für Menschen nützlich:

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')

Importiere passes.ics in Apple-Kalender/Google-Kalender/Outlook und du erhältst 5 Minuten vor jedem Durchgang Push-Benachrichtigungen.

Schritt 7: Starte es auf Cron

Fügen Sie das Skript in ~/bin/station-passes.py ein und cronieren Sie es einmal täglich:

# Refresh pass schedule nightly at 03:00 local
0 3 * * * /usr/bin/python3 ~/bin/station-passes.py > ~/passes.ics 2>> ~/station.log

Verbinde es mit curl --upload-file mit einem Webdav-Kalender und dein Handy sieht jeden Pass automatisch.

STK Cloud Stück für Stück ersetzen

Für Amateur-/Cubesat-/kleine kommerzielle Unternehmen ersetzt das kombinierte Toolkit die täglichen Treiberfunktionen von STK Cloud:

STK Cloud-FunktionKostenloser Ersatz
Vorhersage bestehenSkyfield
Budget verknüpfenrftools Satellite Link Budgetanalysator
Doppler/EntfernungskurvenSkyfield-Reichweitenrate
Höhenmasken + GeländeSkyfield + lokales DEM (SRTM)
3D-VisualisierungCesium.js
VerbindungsscreeningSOCRATES
Für Missionsdesign-Handelsstudien oder institutionelle Programme benötigen Sie immer noch Desktop-STK oder NASA GMAT. Für alles andere — einschließlich der AMSAT-Designüberprüfungen — ist der Skyfield + rftools-Stack vollständig.

Weiterführende Literatur

— Größe eines UHF-CubeSat-Link-Budgets — ein durchgängig funktionierendes Beispiel

Häufig gestellte Fragen

Für Passvorhersagen, Doppler-Kurven, Höhenzeitlinien und geplante Downloads — ja. Skyfield implementiert SGP4 mit Ephemeriden, die anhand von JPL Horizons validiert wurden, und entspricht den Passzeitvorhersagen von STK innerhalb weniger Sekunden über einen Zeithorizont von 30 Tagen. Es ersetzt nicht die 3D-Visualisierung, die integrierte Berichterstattung oder die Konjunktionsanalyse von STK — verwenden Sie dafür Cesium.js oder SOCRATES.
Innerhalb von 7 Tagen nach der Epoche für eine Positionsgenauigkeit von unter 1 km für LEO-Satelliten. TLEs, die älter als 14 Tage sind, können auf einer langen Strecke um mehr als 10 km driften, wodurch sich die Überholzeiten um mehr als 30 Sekunden verschieben — genug, um ein 6-minütiges Passfenster zu verpassen. Holen Sie sich vor jedem Planungslauf neue TLEs von Celestrak.
Drei mögliche Ursachen: (1) Ihre Bodenstationskoordinaten weichen um Dutzende Meter ab — überprüfen Sie dies mit GPS, (2) Sie verwenden eine ältere TLE-Epoche als den AMSAT-Prädiktor, (3) Sie berücksichtigen nicht die Stationshöhe über dem Meeresspiegel (verwenden Sie elevation_m in wgs84.latlon). Abweichungen unter 10 Sekunden werden erwartet und wirken sich nicht auf den praktischen Betrieb aus.
Numerisch: Berechne den Neigungsbereich zum Zeitpunkt t und t+1s, dividiere, um die Entfernungsrate in m/s zu erhalten, dann doppler_shift_hz = -frequency_hz * range_rate / c (positiv, wenn sich der Satellit nähert). Skyfield hat keine eingebaute Doppler-Funktion, da sie von Ihrer Downlink-/Uplink-Frequenz abhängt — berechnen Sie sie selbst. Ein typischer 435-MHz-LEO-Pass überträgt ±10 kHz über einen Zeitraum von ~6 Minuten.
Für GEO (geostationär) ja — aber die SGP4/TLE-Präzision verschlechtert sich oberhalb von ~6000 km. Verwenden Sie einen Kepleran-Element-Solver oder eine vollständige Ephemeride (DE440) für GEO. Verwenden Sie für Weltraummissionen die kernbasierten Ephemeriden von Skyfield mit SPICE-Kerneln der NASA. Für Mondumlaufbahnen laden Sie die Ephemeriden DE440 oder Jup365 über skyfield.api.load ('de440.bsp').

Verwandte Artikel