Con una cuenta desbloqueas el cuestionario, el foro de dudas y el tutor con IA de esta lección, además del registro de progreso y el certificado verificable al terminar «Python para Ingeniería Espacial».
Un script de misión es una herramienta pequeña que responde una pregunta operativa concreta con datos reales. El nuestro responde esta: dado el TLE de un satélite y la lista de elevaciones máximas de sus próximos pases, ¿cuál es su periodo, a qué altitud vuela y cuáles de esos pases merecen que la estación se despierte?
No es un ejercicio. Es exactamente la clase de utilidad que se escribe la primera semana en cualquier equipo de segmento terreno, y que después crece hasta convertirse en el planificador de la estación. Lo relevante es que ya sabes escribir cada una de sus piezas:
Etapa
Lección
Qué aporta
Extraer el mean motion por columnas fijas
7
Rebanado linea2[52:63] y conversión con float()
Calcular el periodo y la altitud
6
Funciones con docstring y composición
Recorrer la lista de pases
4–5
Listas y bucles for
Clasificar por máscara de elevación
3
Condicionales if / elif / else
Sobrevivir a un TLE corrupto
8
try / except con excepciones específicas
El proyecto consiste en juntarlas. Esa es toda la idea de un curso de programación: al final, lo nuevo no es ninguna pieza, sino el ensamblaje.
Arquitectura del script
Cuatro funciones puras y un bloque principal que las orquesta. Puras significa que cada una recibe sus datos por parámetro y devuelve un resultado, sin imprimir ni leer variables globales: así se pueden probar una por una.
Paso 1 · Del TLE al mean motion
La línea 2 llega como una cadena de 69 caracteres y el mean motion ocupa las columnas 53 a 63, es decir el rebanado linea2[52:63]. Con la línea que usarás en el laboratorio:
el rebanado devuelve la cadena "15.50000000", y float() la convierte en n=15.5 rev/día. Dos comprobaciones baratas antes de seguir: que la línea empiece por "2 " y que el valor esté en un rango razonable, porque un mean motion de 0 produce una división entre cero tres líneas más abajo.
Paso 2 · Del mean motion al periodo
T[min]=n1440=15.51440=92.90min
Noventa y dos minutos con noventa centésimas, es decir 92 minutos y 54 segundos. La ISS completa 15.5 vueltas al día.
Paso 3 · Del periodo a la altitud
Aquí invertimos la tercera ley de Kepler que usamos en la lección 6. Si T=2πa3/μ, despejando el semieje mayor:
a=3μ(2πT)2,h≈a−RT
con Ten segundos, μ=398600.4418km3/s2 y RT=6371 km. Trabajemos el número. Primero pasamos el periodo a segundos:
T=92.9032×60=5574.19s
Dividimos entre 2π y elevamos al cuadrado:
(6.283195574.19)2=887.162=787053s2
Multiplicamos por μ y extraemos la raíz cúbica:
a=3787053×398600.4418=33.1372×1011=6794.9km
Y finalmente restamos el radio terrestre:
h≈6794.9−6371=423.9km
Compáralo con el valor de referencia de la ISS, que ronda los 420 km: coincide dentro del 1 %. Y la aproximación tiene dos límites que conviene enunciar en lugar de esconder. El primero es que h=a−RT solo es la altitud real si la órbita es circular; con una excentricidad de 0.00067 la ISS está lo bastante cerca de serlo, pero para una órbita elíptica esa resta da una altitud media, no la de un instante. El segundo es que la Tierra no es una esfera: su radio ecuatorial mide 6378 km y el polar 6357 km, así que usar el radio medio de 6371 introduce hasta 7 km de incertidumbre. Una aproximación con sus límites escritos es ingeniería; sin ellos, es una cifra suelta.
En Python, la raíz cúbica se escribe como una potencia fraccionaria: a = (MU * (T_seg / (2 * math.pi)) ** 2) ** (1 / 3). Cuidado con los paréntesis del exponente: ** 1 / 3 se evalúa como (** 1) / 3 y da un resultado absurdo.
Paso 4 · Clasificar los pases
Un pase con elevación máxima baja apenas asoma sobre el horizonte: la señal atraviesa mucha más atmósfera, el contacto dura poco y cualquier árbol o edificio lo bloquea. Por eso toda estación define una máscara de elevación, típicamente 10°, por debajo de la cual no vale la pena intentarlo. Con tres categorías:
Elevación máxima
Categoría
Decisión operativa
<10°
descartado
No se agenda
10° a 30°
marginal
Se agenda si no compite con uno mejor
≥30°
bueno
Se agenda con prioridad
Sobre una lista de seis pases con elevaciones máximas [47.0,8.1,3.2,61.4,25.9,12.7] grados: dos son buenos (47.0 y 61.4), dos marginales (25.9 y 12.7) y dos se descartan (8.1 y 3.2). El aprovechamiento es:
η=64=0.667=66.7%
Cuatro oportunidades de contacto en 24 horas. Ese número, y no el periodo orbital, es el que decide si una misión de recogida de datos es viable desde una sola estación.
Paso 5 · Sobrevivir a los datos malos
La última pieza es la de la lección 8. Un script de misión que muere con un traceback porque una línea del TLE venía recortada es un script que no sirve. Las tres defensas mínimas:
Envolver la extracción y conversión en un try que capture ValueError e IndexError — los dos errores que produce una línea corta o un campo no numérico.
Validar el rango del mean motion antes de dividir, para que un n=0 no provoque un ZeroDivisionError.
Registrar cada descarte con su motivo y continuar con el resto, en lugar de abortar el lote entero.
Prueba el módulo de clasificación de pases antes de montarlo todo:
Playground · python
Laboratorio
El laboratorio de esta lección es distinto de los playgrounds que has usado hasta ahora: tu código se envía al servidor, se ejecuta en un contenedor aislado y sin red, y devuelve la salida. Es el mismo mecanismo con el que se evalúan los laboratorios de código del resto de la academia, y el motivo por el que conviene que tu script imprima resultados claros: la salida es la prueba de que funciona.
La consigna es la primera mitad del script de misión. Recibes la línea 2 del TLE de la ISS como una cadena y tienes que llegar al periodo orbital en minutos con tres pasos: extraer el mean motion de las columnas 53 a 63 con el rebanado que aprendiste en la lección 7, aplicar T=1440/n y presentar el resultado con dos decimales. El valor correcto es 92.90 minutos; si te sale 92.88 estás usando el TLE de la lección 7, que trae un mean motion ligeramente distinto, y también está bien mientras sepas por qué.
Lo que conviene observar mientras trabajas es qué ocurre en cada frontera. Si te equivocas en un carácter del rebanado — linea2[51:63] en lugar de linea2[52:63] — arrastrarás un espacio inicial que float() tolera sin protestar, y el resultado seguirá siendo correcto; pero si te equivocas por el otro lado, linea2[52:64], capturarás el primer dígito del número de revolución y obtendrás un valor absurdo sin que salte ningún error. Ese es el modo de fallo característico de los formatos de columnas fijas: silencioso. La defensa es siempre la misma, comprobar el resultado contra un valor conocido.
Tres retos concretos sobre el laboratorio. Primero: encapsula los tres TODO en una función periodo_desde_tle(linea2) con docstring, para que la pieza sea reutilizable en lugar de un script de un solo uso. Segundo: añade el cálculo de la altitud aproximada con a=3μ(T/2π)2 y comprueba que obtienes unos 424 km. Tercero: mete la extracción en un try / except ValueError, prueba con una línea recortada a 40 caracteres y verifica que tu script informa del problema en lugar de morir con un traceback.
1 de 7
Comprueba el punto que más veces rompe este script:
Al calcular la altitud escribes a = (MU * (T_seg / (2 * math.pi)) ** 2) ** 1 / 3. ¿Qué ocurre?
Cuando termines el laboratorio y el proyecto, habrás cerrado el círculo: entraste sin saber programar y sales con una herramienta que produce un número que puedes defender. Lo que sigue — mecánica orbital, señales, redes satelitales — ya no te pedirá aprender a programar: te pedirá programar.
Laboratorio: Script de misión · Periodo orbital desde un TLE