Запуски

Раздел /launches/ — афиша и дашборд запусков. Он отвечает на три вопроса: какие запуски ждёт сеть, что она услышала после прошлых и что ещё стоит в мировом календаре. На странице два раздела, переключатель под заголовком: «Отслеживаемые сетью» (сегменты «Сеть ждёт» и «Прошедшие») и «Календарь пусков». Без ?scope открывается «Сеть ждёт», а если сеть ничего не ждёт — «Прошедшие». Страница запуска показывает состав, отсчёт до старта и раскрытие — как аппараты запуска проходят стадии от манифеста до первого принятого кадра.

Два вида запусков

Launch.is_tracked — галочка администратора, а не вычисляемый признак.

Отслеживаемый запуск (is_tracked=True) — тот, что интересен сети. У него ведётся состав (SatelliteLaunch и Satellite.launch), до старта состав и TLE берутся из предстартового файла CelesTrak, после старта по номеру COSPAR приходят настоящие номера каталога, работает планировщик наблюдений на старте и считается воронка раскрытия. На /launches/ такие запуски живут в сегментах «Сеть ждёт» и «Прошедшие», на главной блок «Запуски» показывает только их.

Календарный запуск (is_tracked=False) — «просто информация». Страница есть, аппаратов в базе нет, планировщика нет. Все предстоящие орбитальные пуски мира заводятся из Launch Library 2 автоматически; после старта запись выпадает из раздела «Календарь пусков», но остаётся в базе и открывается по прямой ссылке.

Предупреждение

Галочка — предохранитель, а не фильтр витрины. Launch Library 2 проставляет номер COSPAR каждому мировому пуску после старта, и без is_tracked сигнал post_save и задача fetch_satellite_from_tle_source_for_all_launches завели бы в Satellite содержимое всех этих пусков — по два десятка Starlink за раз. Оба пути фильтруются по is_tracked=True.

Галочка ставится в админке (поле, фильтр и действие «Отметить отслеживаемыми») и кнопкой «Отслеживать» в шапке страницы запуска — она видна is_staff. Решать нужно до старта: COSPAR приходит после, и импорт срабатывает сразу за ним.

Launch Library 2

Источник календаря — Launch Library 2 (TheSpaceDevs). Клиент — network/base/ll2_client.py, синхронизация — задача sync_launches_from_ll2 в network/base/tasks.py.

Что хранится

Настоящие колонки — только то, по чему сортируем, фильтруем и считаем: ll2_id, ll2_slug, launch_id (COSPAR), launch_name, launch_date (LL2 называет его net), net_precision, status, rocket_name, provider_name, pad_name, orbit, mission_type, mission_description, country. Всё остальное — агентство, ступени и посадка ускорителя, координаты площадки, лента обновлений, трансляции, циклограмма — лежит в Launch.ll2 (JSON-снимок ответа LL2) и читается шаблоном напрямую. Новое поле LL2 доступно странице без миграции.

Три перечисления переводятся словарями в models.py: статус пуска (LAUNCH_STATUSES, ключ — id LL2), орбита (LAUNCH_ORBITS, id LL2) и тип миссии (LAUNCH_MISSION_TYPES, ключ — английское название, как отдаёт LL2). Имена собственные — носитель, площадка, оператор — остаются по-английски.

net_precision — точность T-0 по LL2. Launch.net_display переводит её в «сколько печатать»: до часа включительно — время, до недели — день, до полугодия — месяц, иначе год. Отсчёт до старта рисуется только при точном времени.

Человек главнее импорта

Импорт пишет только через apply_facts (network/base/importers.py) со списком LAUNCH_LOCKABLE_FIELDS — тем же механизмом, что паспортные данные спутника. Поле из Launch.locked_fields не перезаписывается никогда, пустое значение не затирает заполненное, равное значение — не запись. В админке это блок галочек «Не перезаписывать».

Изображение

Скачивается одно изображение — главное фото запуска, — если LL2 называет для него лицензию; с Unknown картинка не берётся вовсе. Рядом сохраняются image_credit и image_license и печатаются подписью под фотографией. image_source_url — адрес, откуда взято: второй прогон узнаёт свою картинку и не качает её снова, а загруженную вручную (без image_source_url) импорт не трогает. Логотипы, инфографика и нашивки не скачиваются и не показываются.

Бюджет запросов

Анонимному клиенту боевой хост даёт 15 запросов в час на IP, считая по скользящему часу. Бюджет один на весь сервер, поэтому тратит его только задача sync_launches_from_ll2 (каждые 5 минут), по приоритетам:

  1. Живое окно — отслеживаемый запуск от T−1 ч до T+72 ч опрашивается в каждый тик (mode=detailed), пока бюджет выше резерва в 4 запроса. Один запуск в окне — 12 запросов в час; два — по 6 на каждый.

  2. Календарь — раз в час на резерв: страницы launches/upcoming/ (mode=normal, по 100), одна страница launches/previous/ (чтобы статус чужого запуска сменился с «Готов к пуску» на «Успешный пуск») и один отслеживаемый запуск с самым старым снимком — в mode=detailed.

Отметки времени запросов живут в кэше (ll2_request_stamps); на холодном кэше задача спрашивает api-throttle/, сколько уже потрачено. HTTP 429 останавливает задачу на час. Тик страницы в LL2 не ходит никогда: живой режим бьёт в /launches/<id>/live/, который читает базу и кэш.

Переменные: LL2_API_URL (по умолчанию боевой хост; для локальной работы — https://lldev.thespacedevs.com/2.3.0, без лимита, но с усечёнными данными) и LL2_HOURLY_BUDGET. См. Конфигурация.

Состав до старта: SupGP

За несколько дней до группового пуска CelesTrak публикует предстартовый файл SupGP — элементы каждого объекта начального развёртывания, посчитанные по векторам состояния от оператора. Эпоха этих элементов — момент отделения, то есть в будущем.

Администратор вписывает имя файла в поле supgp_file запуска в админке (transporter-18 из sup-gp.php?FILE=transporter-18). Задача fetch_launch_supgp (network/base/launch_supgp.py) раз в два часа опрашивает файлы отслеживаемых запусков, у которых даты ещё нет или после старта прошло не больше 14 суток. Ждать двух часов не обязательно: сохранение файла в админке само ставит задачу в очередь, и её можно запустить со страницы «Система». Там же, в строке задачи, видно, что она сделала или почему ничего не сделала: rate_limited: True — CelesTrak ответил 403/429 кому-то из читателей портала, и два часа его не спрашивают.

На каждый объект файла:

  1. Ищется спутник — по имени и алиасам (name и «Другие названия», без регистра и знаков) среди аппаратов этого запуска и аппаратов со статусом future без запуска. Так находятся аппараты, заранее заведённые руками или пришедшие из SatNOGS DB под другим временным номером.

  2. Если спутника нет, заводится заглушка — Satellite со статусом future, unknown=True, source="CelesTrak" и свободным временным номером из диапазона 70000–100000. Как и объекты, заведённые импортом по COSPAR, заглушка не утверждена (approved=False): в общем списке спутников её нет, на странице запуска и по прямой ссылке — есть.

  3. Спутник получает TLE с источником Celestrak SupGP. Строки пишутся с номером спутника в портале: CelesTrak нумерует эти объекты девятью цифрами, в строку TLE такой номер не помещается (сам CelesTrak в формате TLE эти данные не отдаёт), и нигде в портале он не хранится.

Повторный опрос того же файла ничего не пишет; изменившиеся элементы — новый набор, на который будущие наблюдения переедут сами (см. Орбитальные данные (TLE)).

Ручная привязка

Имена совпадают не всегда. Чтобы привязать спутник к объекту файла, впишите имя объекта в «Другие названия» спутника и, если у спутника статус не future, поставьте ему этот запуск. При следующем опросе:

  • заглушка, заведённая импортом под этим именем, сливается в спутник: её TLE и наблюдения переезжают, сама она удаляется. Заглушкой считается спутник с source="CelesTrak" без передатчиков; заглушка, которой дали передатчик, — уже самостоятельный спутник, и её импорт не трогает;

  • два аппарата, которые выходят из диспенсера сцепленными и значатся у CelesTrak одним объектом, получают его элементы оба — достаточно вписать имя объекта в алиасы каждого.

Предупреждение

Имя заглушки — её связь с файлом. Переименовывая заглушку, оставьте исходное имя в «Других названиях», иначе следующий опрос заведёт под этим именем новую.

Чего импорт не делает: не удаляет аппарат, пропавший из файла или переименованный CelesTrak (он остаётся с прежним TLE, убирает администратор), и не передвигает уже запланированные наблюдения при сдвиге пуска — TLE у них обновится, окна нет.

После старта

Когда Launch Library 2 ставит отслеживаемому запуску «Успешный пуск», его аппараты переходят из future в in orbit, и один раз запускается планировщик наблюдений на старте с настройками по умолчанию (см. Планирование наблюдений). Это не зависит от того, откуда у аппаратов TLE — из SupGP или заведён руками.

Настоящие номера NORAD приходят импортом по COSPAR. У запуска, в котором уже есть аппараты, он новых не заводит, а ищет по имени те, что ещё под временным номером, и записывает им номер каталога; имена-заглушки вида OBJECT X не сопоставляются. Задача возвращается к такому запуску раз в сутки в течение 90 суток после пуска. С настоящим номером аппарат начинает получать TLE от Space-Track и CelesTrak, и они вытесняют предстартовый по приоритету. Аппарат, имя которого в каталоге оказалось другим, опознаётся так же, как привязывается: алиасом или номером вручную.

Раскрытие запуска

Запуск — когорта аппаратов, которая проходит стадии:

Стадия

Условие

заявлен

строка манифеста SatelliteLaunch или Satellite под временным номером (70000–100000) — аппарат известен только по имени

опознан

у Satellite настоящий номер каталога или задан norad_follow_id

услышан

у аппарата заполнен first_signal_at

передаёт

есть DemodData за последние 7 дней

молчит

услышан, кадров за 7 дней нет

Satellite.first_signal_at и first_signal_station заполняются задачей record_launch_first_signals (каждые 15 минут, по первому наблюдению со статусом good) один раз и не пересчитываются — момент первого сигнала не меняется. Живой режим страницы вызывает ту же функцию для своего запуска, чтобы не ждать тика задачи. Стадия «передаёт/молчит» считается на запрос; набор передающих аппаратов кэшируется на 5 минут по ключу launch-transmitting-<id>.

Строка манифеста и спутник каталога склеиваются по sat_id или NORAD, так что аппарат — одна строка, сколько бы таблиц его ни знали.

Страница запуска

Три состояния (launch_state в views/launch.py):

  • до старта — крупный отсчёт, сколько наблюдений уже запланировано и на скольких станциях, сколько аппаратов заявлено и у скольких известны частоты. Рядом с отсчётом — фотография, а если у аппаратов уже есть TLE — карта их расчётных орбит;

  • живой режим — от T−1 ч до T+72 ч у отслеживаемого запуска: карта аппаратов (если есть TLE), «сейчас слушает», воронка и стадии обновляются раз в минуту скриптом launch_live.js из /launches/<id>/live/. Для проверки без пуска: ?live=1 под is_staff включает окно принудительно;

  • архив — воронка и время/станция первого сигнала.

В таблице состава у каждого аппарата — эпоха и источник TLE, над ней — ссылка «Скачать TLE запуска» (/launches/<id>/tle/, текст в формате 3LE).

Вкладки: «Обзор», «Состав и раскрытие», «Носитель и площадка» (из снимка LL2; площадка рисуется своей картой по координатам), «Хроника» (лента обновлений, циклограмма T-минус, трансляции, ссылки) и «Планирование» — форма планировщика наблюдений на старте, только is_staff и только у отслеживаемого запуска. См. Планирование наблюдений.

Миграция 0053

rocket_type → rocket_name, space_port → pad_name (данные сохранены, справочники choices сняты). Свободный текст status сопоставлен со статусами LL2 по основам слов («успе» → успешный пуск, «неуда»/«авари» → авария, «частич» → частичная неудача, «отлож» → отложен, «ожида»/«план» → дата не определена и т. д.); значение, которое не подошло ни к одной основе, сбрасывается и печатается в лог миграции. is_tracked=True проставлен запускам, у которых уже есть аппараты или строки манифеста.