Creación de un cronograma de pases para estaciones terrestres con Skyfield
Preparado para el Ansys STK al atardecer: calcula las predicciones de pases del SGP4 para tu estación terrestre de radio amateur o cubesat con Skyfield.
Contenido
- Por qué necesitas un programador de pases local
- Instalar
- Paso 1: Obtenga los TLE actuales
- Paso 2: Defina su estación terrestre
- Paso 3: Encuentra eventos de ascenso, culminación o descenso
- Paso 4: cambio Doppler durante una pasada
- Paso 5: Vincula el presupuesto de cada pase
- Paso 6: Emite iCalendar para que los pases aparezcan en tu calendario
- Paso 7: ejecútalo en cron
- Sustituir a STK Cloud, pieza por pieza
- Lecturas adicionales
Por qué necesitas un programador de pases local
Si tienes una emisora SatNogs, una choza de radioaficionados que rastrean el AO-91/ISS/NOAA o un segmento terrestre con cubesat en las primeras etapas, necesitas hacer predicciones de pases automatizadas. Las herramientas comerciales (STK, NOVA) son exageradas. Los predictores web gratuitos (AMSAT, Heavens-Above) no se escriben bien. Con STK Cloud a finales de marzo de 2026, la alternativa gratuita más limpia es Skyfield, el sucesor moderno de PyEphem en Python.
Esta publicación describe un programador completo de estaciones terrenas en unas 80 líneas de Python: busca TLE nuevos, calcula las próximas 24 horas de pases para una lista de satélites, filtra por elevación mínima, calcula el Doppler para la frecuencia de enlace descendente y emite iCalendar para que los pases aparezcan en tu aplicación de calendario.
Instalar
pip install skyfield requests icalendar
Eso es todo. Skyfield extrae sus propias efemérides (DE421, IERS) en la primera ejecución: unos 17 MB en caché localmente.
Paso 1: Obtenga los TLE actuales
Los TLE están a la deriva: úsalos dentro de los 7 días de la época. Extrae el conjunto de elementos actual 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')
Elija sus objetivos por nombre (distinguen mayúsculas de minúsculas en el archivo Celestrak):
targets = [
by_name['AO-91 (FOX-1B)'],
by_name['ISS (ZARYA)'],
by_name['NOAA 19'],
by_name['GreenCube (IO-117)'],
]
Paso 2: Defina su estación terrestre
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
Utilice el parámetro elevation_m: afecta materialmente al rango de inclinación en ángulos de elevación bajos.
Paso 3: Encuentra eventos de ascenso, culminación o descenso
Satellite.find_events() devuelve una lista plana de eventos (0 = ascenso, 1 = culminación, 2 = conjunto). Procésalos en triples:
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')
Ignora los satélites que ya están por encima del horizonte en el punto t0(la lista de eventos comienza con un par de culminación y conjunto).
Paso 4: cambio Doppler durante una pasada
En el caso de los aficionados a la frecuencia UHF (435 MHz), un pase puede desplazar el operador en ± 10 kHz; el receptor debe rastrear. Calcula el Doppler instantáneo a partir de la velocidad de rango:
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')
En una pasada aérea típica del AO-91 de 6 minutos, verás un barrido Doppler desde aproximadamente +10 kHz (subida) pasando por 0 (cenit) hasta −10 kHz (conjunto). Síguelo en el VFO principal de la radio para no perder la señal.
Paso 5: Vincula el presupuesto de cada pase
Cuando tengas el rango de inclinación, introdúcelo en la calculadora de pérdidas por trayectoria en espacios libres de rftools o calcula en línea:
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
Para obtener un presupuesto completo de enlaces de Montecarlo con los modelos de propagación de la UIT-R, utilice el Satellite Link Budget Analyzer y comparta la URL del escenario con el libro de registro de la estación.
Paso 6: Emite iCalendar para que los pases aparezcan en tu calendario
Aquí es donde el planificador se vuelve útil para los humanos:
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')
Importa passes.ics a Apple Calendar, Google Calendar o Outlook y recibirás notificaciones push 5 minutos antes de cada pase.
Paso 7: ejecútalo en cron
Coloca el script en ~/bin/station-passes.py y córtalo una vez al día:
# Refresh pass schedule nightly at 03:00 local
0 3 * * * /usr/bin/python3 ~/bin/station-passes.py > ~/passes.ics 2>> ~/station.log
Combínalo con curl --upload-file a un calendario webdav y tu teléfono verá todos los pases automáticamente.
Sustituir a STK Cloud, pieza por pieza
Para pequeñas operaciones comerciales de aficionados, cubesats y pequeñas, el conjunto de herramientas combinado reemplaza las funciones diarias de STK Cloud:
| Función STK Cloud | Reemplazo gratuito |
|---|---|
| Predicción de pases | Skyfield |
| Presupuesto de enlace | Analizador presupuestario rftools Satellite Link |
| Doppler/curvas de rango | Velocidad de alcance de Skyfield |
| Máscaras de elevación y terreno | Skyfield + DEM local (SRTM) |
| Visualización 3D | Cesium.js |
| Detección de conjunciones | SOCRATES |
Lecturas adicionales
- Documentación de Skyfield
- Catálogos Celestrak TLE
- rftools Satellite Pass Predictor: versión alojada de este planificador para los satélites aficionados más comunes
- Migrar desde STK Cloud: alternativas gratuitas: el artículo complementario sobre cómo reemplazar el flujo de trabajo completo de STK
- Cómo calcular el presupuesto de un enlace UHF CubeSat: ejemplo práctico de principio a fin
Preguntas Frecuentes
Artículos Relacionados
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 abr 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 abr 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 abr 2026