kerbal.ruвики сборки «Оператор»
Оператор / Вики / Автоматика

Скрипт вывода на орбиту: разбор ошибок

Инженерный журнал четырёх попыток вывести спутник скриптом kOS: почему ракета кувыркалась, куда делись 1500 м/с, отчего сломались антенны и как чинится каждая из этих бед.

Эта статья — не рецепт, а разбор реальных отказов. Скрипт вывода спутника на орбиту 4758 × 4592 км писался в четыре захода, и каждый заход упирался в отдельную проблему. Ошибки типовые: на них наступит любой, кто попробует автоматизировать подъём.

Готовые рабочие куски — в kOS: готовые рецепты, отладка языка — в kOS: отладка и лимиты.

Заход 1: ракета кувыркается

Симптом. На подъёме угол атаки уходит за 90°, аппарат теряется.

Что было в скрипте. Разворот начинался с высоты 250 м, тангаж задавался формулой от высоты, без оглядки на то, куда аппарат летит.

Разбор. Две ошибки, обе мои:

  1. Разворот по высоте, а не по скорости. На 250 м скорость ещё мизерная, рули и подвес не работают — команда наклона просто разворачивает корпус боком к потоку.
  2. Нет ограничения угла атаки. Скрипт командовал абсолютный тангаж независимо от вектора скорости. Это и есть способ сломать ракету.

Лечение. Разворот начинать по скорости (70 м/с) и никогда не отходить от вектора скорости дальше допуска:

LOCAL vp IS 90 - VANG(SHIP:UP:VECTOR, SHIP:VELOCITY:SURFACE).  // тангаж потока
SET cmd TO MAX(vp - AOA, MIN(vp + AOA, want)).                  // зажали

Это и есть настоящий гравитационный разворот: аппарат не спорит с набегающим потоком.

Заход 2: кувыркается снова, до 147°

Ограничение угла атаки помогло не полностью. Причина оказалась не в коде.

Аэродинамическая неустойчивость. На аппарате стояли рули — и стояли они на верхней ступени. Центр давления оказался впереди центра масс. Такая ракета неустойчива принципиально: отклонение растёт само, а не гасится. Ни маховики, ни подвес, ни РСУ в плотном воздухе этого не удержат.

Правило: аэродинамические поверхности ставятся ниже центра масс. Оперение сверху — это дротик, воткнутый наоборот.

Скрипт может лишь смягчить последствия:

  • держать угол атаки около нуля;
  • ограничить скоростной напор — чем меньше напор, тем меньше валящий момент;
  • держать РСУ включённым на атмосферном участке;
  • смягчить рулевой менеджер: SET STEERINGMANAGER:MAXSTOPPINGTIME TO 4. — жёсткие команды сами раскачивают неустойчивый аппарат.

Отдельная ошибка режима восстановления. При срабатывании сторожа я ронял тягу до 0,25 — и вместе с ней пропадала управляющая сила подвеса. Восстанавливаться становилось нечем. Правильно — резать тягу не ниже 0,45.

Заход 3: не хватило топлива

Управление наконец сработало, ракета вышла на орбиту — и встала с пустыми баками, не добрав перицентр.

Телеметрия говорит точно:

 t=16с   1,2 км   167 м/с   тяга 0.65
 t=40с   7,1 км   308 м/с   тяга 0.54
 t=88с  28,1 км   672 м/с   тяга 0.39
 t=112с 45,4 км   811 м/с   апоцентр 80 км

Разбор. Ограничитель перегрузки держал TWR = 2,0 и душил тягу до 0,36–0,65 всю дорогу. Ракета лезла вверх слишком круто и медленно: на 36 км всего 807 м/с при наклоне 66°. К апоцентру она подошла с горизонтальной скоростью 460 м/с вместо нужных 2280.

Итог — циркуляризация в 1816 м/с вместо нормальных 250. Полторы тысячи метров в секунду выброшено, ровно их и не хватило.

Урок. Перестраховка в управлении оплачивается топливом. Ограничитель перегрузки нужен только в плотном воздухе; выше 20 км он вредит.

Лечение — расписание тангажа, а не следование за потоком:

 1 км → 85°     10 км → 55°     30 км → 25°
 5 км → 70°     20 км → 40°     45 км → 12°   →   60 км → 5°

При этом ограничение угла атаки остаётся: расписание задаёт цель, а зажим не даёт с ней воевать.

Ошибки, всплывшие попутно

Автостейджер вис на ступени-переходнике

// БЫЛО — ловит только выгорание зажжённого двигателя
FOR e IN el { IF e:IGNITION AND e:FLAMEOUT { RETURN TRUE. } }

Ступень, где двигателя нет вообще — только разделитель или обтекатель, — так не отрабатывает никогда. Аппарат зависал без тяги, и снаружи это выглядело как «почему мы не жжём двигатель».

// СТАЛО — ступень нужна, когда живых двигателей не осталось
FUNCTION needStage {
  IF STAGE:NUMBER = 0 { RETURN FALSE. }
  IF NOT STAGE:READY { RETURN FALSE. }
  RETURN liveEngines() = 0.
}

Антенны сорвало потоком

Скрипт снимал науку и сразу передавал её на подъёме. В KSP складная антенна раскрывается сама, когда через неё идёт передача. HG-5 и зонд Zebulon раскрылись на скорости в плотном воздухе и были сорваны.

Правило: в атмосфере науку только собираем, данные лежат в приборах. Передаём в вакууме, раскрыв антенны штатно.

То же касается панелей: PANELS ON только после выхода за границу атмосферы.

Один прибор — два эксперимента

p:GETMODULE("ModuleScienceExperiment")     // вернёт только ПЕРВЫЙ

У мачты CA-AMA два научных модуля в одной детали — магнитометр и датчик радиации. Поиск по имени видел один, половина науки терялась. Перебирать надо по индексу:

LOCAL i IS 0.
UNTIL i >= p:MODULES:LENGTH {
  IF p:MODULES[i] = "ModuleScienceExperiment" {
    LOCAL m IS p:GETMODULEBYINDEX(i).
    ...
  }
  SET i TO i + 1.
}

Перицентр круговой орбиты не определён

Классическая схема «круговая опорная → разгон из перицентра» опирается на ETA:PERIAPSIS. У круговой орбиты перицентра фактически нет, и значение шумит.

Лучше один совмещённый прожиг прямо в апоцентре подъёма: эта точка сама становится перицентром переходной орбиты. По топливу то же самое (Гоман есть Гоман), но на один прожиг и одну неопределённость меньше.

Азимут без поправки на вращение

Наивная формула sin(A) = cos(i) / cos(широта) для наклонения 8,5° даёт азимут 81,5°. Но планета уже везёт аппарат на восток со скоростью 175 м/с:

восток = 2279·sin(81,5°) − 175 = 2081 м/с
север  = 2279·cos(81,5°)       =  337 м/с
азимут = atan2(2081, 337)      = 80,8°

Скрипт душил сам себя

Два эффекта, которые легко проглядеть:

  • Лимит инструкций. CONFIG:IPU по умолчанию 200. Рулевой закон с векторной математикой в LOCK STEERING не успевает считаться каждый физический тик, и управление отстаёт. На время полёта поднимаем до 800.
  • Лог на каждом тике. Один полёт записал 9738 строк CSV. Файловый ввод-вывод отъедал у цикла управления больше, чем сам расчёт. Пишем раз в полсекунды.

Левая система координат: ошибка ровно на 180°

Контракт требовал аргумент перицентра 29,6° — то есть чтобы низшая точка орбиты стояла под определённым углом от восходящего узла. Мы вышли на 209,52°. Апоцентр, перицентр, наклонение и долгота узла при этом попали в допуск.

Разница ровно 180° — верный признак перепутанного знака, а не накопленной погрешности.

Причина: в учебниках вектор восходящего узла считается как n⃗ = ẑ × h⃗, где ẑ — ось вращения тела, h⃗ — момент импульса орбиты. Но KSP и kOS работают в левой системе координат, унаследованной от Unity. Векторное произведение там меняет знак, и школьная формула честно указывает на нисходящий узел.

LOCAL n IS VCRS(kNorth, h).   // ✗ нисходящий узел — ошибка на 180°
LOCAL n IS VCRS(h, kNorth).   // ✓ восходящий

Проверяется мгновенно, если знать, с чем сравнивать: сумма ARGUMENTOFPERIAPSIS + TRUEANOMALY и есть аргумент широты. Свою функцию сверяешь с ней — расхождение либо 0°, либо 180°, третьего не дано.

Правило: любую векторную геометрию в kOS сверяй со штатными элементами орбиты, прежде чем закладывать в манёвр. Знак в левой системе — не то, что стоит выводить в уме.

Чек-лист скрипта вывода

  1. Разворот начинать по скорости, не по высоте.
  2. Угол атаки зажат: 3–5° в плотном воздухе.
  3. Расписание тангажа, а не «лечу по потоку» — иначе заплатишь топливом.
  4. Ограничитель перегрузки — только ниже 20 км.
  5. Автостейдж по отсутствию живых двигателей.
  6. Раскрытие панелей и антенн — только в вакууме.
  7. Передача науки — только в вакууме.
  8. Приборы перебирать по индексу модуля.
  9. CONFIG:IPU поднять, лог придушить.
  10. Аэродинамика важнее кода: оперение ниже центра масс.
  11. Векторную геометрию сверять с эталоном: система координат левая.

Всё перечисленное собрано в готовые модули — структура и правила в kOS: библиотека модулей.

Связанные статьи