Автор: Pand5461 Категория: Kerbal Space Program » Гайды

KerboScript в примерах и задачах. Часть 1. Выход на орбиту

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

Использованные моды:


При ручном управлении вывод ракеты на орбиту состоит из четырёх основных этапов:
  1. Вертикальный подъём
  2. Разворот по тангажу (gravity turn)
  3. Построение апоцентра
  4. Скругление орбиты


Те же этапы сохраняются и с выводом при помощи kOS. Напишем, что делается на этих этапах.
1. Вертикальный подъём
Летим вертикально вверх, пока не достигли высоты начала разворота

2. Разворот по тангажу
Держим курс на восток, плавно меняем тангаж с 90 до 0 градусов.
Стараемся, чтобы нос не уходил далеко от вектора скорости.

3. Построение апоцентра
В горизонтальном полёте не отключаем тягу до тех пор, 
пока не достигли желаемой высоты апоцентра.
По достижении нужной высоты апоцентра вырубаем тягу.

4. Скругление орбиты
В апоцентре или недалеко от него делаем прожиг в направлении орбитальной скорости,
пока орбита не скруглится

5*. 
Запускаем новые ступени по необходимости


Эти этапы будем оформлять в виде функций. Функция задаётся следующим синтаксисом:
 function HelloName {
  parameter Name is "World".
  print "Hello, " + Name + "!".
}

Здесь задана функция с именем HelloName, которая имеет один аргумент и печатает его, присоединив впереди "Hello, " и в конце восклицание. В данном случае, аргумент функции необязателен, его значение по умолчанию "World".
Примеры использования:
HelloName("Kerbin"). // выведет "Hello, Kerbin!"
HelloName(). // выведет "Hello, World!"

Теперь напишем функции для контроля ориентации ракеты на всех этапах выхода на орбиту. Для начала идём по простейшему пути - взлетаем строго на восток, орбита получается экваториальная.

1. С вертикальным взлётом всё просто
function VertAscent {
  lock steering to heading(90,90).
}

2. Разворот по тангажу - самый сложный вопрос. Тут нужно соблюсти тонкий баланс между потерями на борьбу с силой тяжести и трением об атмосферу. Поэтому летим вверх до 15 км, потом ставим тангаж на 45. Я сам при ручном выводе до тангажа 45 градусов руководствовался величиной скорости, дальше - высотой апоцентра. Поэтому для скрипта выбрал ту же стратегию.
function GravityTurn {
  parameter vstart. // скорость, при которой начинается разворот
  parameter AP45. // апоцентр при тангаже 45 градусов
  parameter APstop is 60000. // апоцентр, по достижении которого ракета ложится горизонтально
  parameter v45 is 500. // скорость, при которой угол тангажа должен быть 45 градусов
  
  local vsm to velocity:surface:mag. // величина скорости относительно поверхности
  local pitch to 0.
  if ( vsm < v45 ) {
    set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). // линейно менять тангаж от скорости оказалось плохо, по арктангенсу довольно неплохо получается
  }
  else {
    set pitch to max(0, (apoapsis - APstop) / (AP45 - APstop) ). // линейно меняем тангаж, на APstop укладываем ракету горизонтально
  }
  lock steering to heading( 90, pitch ).
  // возложим на kOS функции Kerbal Engineer
  print "Apoapsis: " + round( apoapsis/1000, 2 ) + " km    " at (0,30).
  print "Periapsis: " + round( periapsis/1000, 2 ) + " km    " at (0,31).
  print " Altitude: " + round( altitude/1000, 2 ) + " km    " at (24,30).
  print " Pitch: " + round( pitch ) + " deg  " at (24,31).
}

Переменные здесь вводятся ключевым словом local - это означает, что область видимости этих переменных ограничивается тем блоком кода, где они заданы. Это делается потому, что во внешней программе уже могут быть определены переменные с тем же именем, которые мы не хотим случайно поменять. Если же инициализировать переменную через set, то по умолчанию она инициализируется как глобальная, что в итоге может привести к интересным побочным эффектам. Аргументы функции по умолчанию рассматриваются как локальные имена.
Заметим, что функция держит нужное направление не только во время разворота, но и держит ракету горизонтально после него.
3. Отключить двигатель, когда апоцентр достиг нужного значения - опять просто.
function ShutdownAfterMaxAP {
  parameter APmax is body:atm:height + 10000. // по умолчанию считаем, что хотим подняться на 10 км выше атмосферы
  if apoapsis > APmax { lock throttle to 0. }
}

4. Чтобы закруглить орбиту, потребуется немного математики.
Предположим, мы находимся на эллиптической орбите на высоте h < HAp. Для перехода на круговую орбиту на той же высоте, нужно нашу текущую скорость V превратить в скорость круговой орбиты Vcirc (рис. 1).
Как скруглить орбиту

Рисунок 1. Схема перехода с эллиптической орбиты на круговую.

Скорость на круговой орбите известна - она направлена по нормали к поверхности в плоскости орбиты, а величина её равна
KerboScript в примерах и задачах. Часть 1. Выход на орбиту

Здесь RKerbin - это вектор из начала координат (в kOS, как помним, центр вселенной - это наш корабль) к центру Кербина. Нужное приращение ΔV равно разности Vcirc - V. Таким образом, если делать прожиг, постоянно направляя нос ракеты на вектор оставшейся скорости до круговой, то орбита будет в итоге скруглена (если хватит топлива). Реализуем это в коде:
function circularize {
  local th to 0. // в этой переменной будет необходимый уровень тяги
  local Vcircdir to vxcl( up:vector, velocity:orbit ):normalized. // направление круговой скорости такое же, как у горизонтальной компоненты орбитальной скорости
  local Vcircmag to sqrt(body:mu / body:position:mag). // mu - это гравитационный параметр планеты, произведение массы на гравитационную постоянную
  local Vcirc to Vcircmag*Vcircdir.
  local deltav to Vcirc - velocity:orbit.
  
  // начинаем прожиг, поворачивая ракету постоянно в сторону маневра
  lock steering to lookdirup( deltav, up:vector).
  wait until vang( facing:vector, deltav ) < 1. // убеждаемся, что прожиг начинается в нужной ориентации
  lock throttle to th.
  until deltav:mag < 0.05 {
    set Vcircdir to vxcl( up:vector, velocity:orbit ):normalized.
    set Vcircmag to sqrt(body:mu / body:position:mag).
    set Vcirc to Vcircmag*Vcircdir.
    set deltav to Vcirc - velocity:orbit.
    if vang( facing:vector, deltav ) > 5 { 
      set th to 0. // если сильно не туда смотрим, надо глушить двигатель
    }
    else {
      set th to min( 1, deltav:mag * ship:mass / ship:availablethrust ). // снижаем тягу, если приращение скорости нужно небольшое
    }
    wait 0.1.
  }
  set th to 0.
  set ship:control:pilotmainthrottle to 0.
  unlock throttle.
}

Теперь напишем программу, которая объединяет всё это в скрипт вывода.
function gettoorbit {
  parameter Horb to body:atm:height + 10000.
  parameter GTstart to 1000. // высота начала разворота
  parameter GTendAP to 60000. // заканчиваем разворот, когда апоцентр на этой высоте
  // запомним, как ракета стоит на столе, в этом положении взлетаем
  lock throttle to 1.
  local initialpos to ship:facing.
  lock steering to initialpos.
  startnextstage().
  until altitude > GTstart {
    VertAscent().
    if ship:availablethrust = 0 startnextstage().
    wait 0.01.
  }
  
  // запомним параметры для функции гравиразворота:
  local GTStartSpd to velocity:surface:mag. // при какой скорости начали разворот
  local Apo45 to apoapsis. // какой апоцентр был при тангаже 45 градусов
  local lock pitch to 90 - vang( up:vector, velocity:surface ). // переменная с тем же именем, что и в другой функции
  // т.к. объявлена локально, конфликта имён возникать не должно
  until altitude > body:atm:height {
    if pitch >= 45 { set Apo45 to apoapsis. } // перестанет обновляться после тангажа 45 градусов - то, что требуется
    GravityTurn(GTStartSpd,Apo45,GTendAP).
    ShutdownAfterMaxAP(Horb).
    startnextstage().
    wait 0.01.
  }
  // ждём, пока не подобрались к апоцентру
  until altitude > Horb - 500 {
    lock steering to prograde.
    wait 0.01.
  }
  // скругляем (функция внутри не проверяет, хватит ли на это топлива - должен быть запас!)
  circularize().
  print "We are in orbit: " + round(apoapsis,2) + "x" + round(periapsis,2) + " km. Releasing the payload. ".
  
  lock steering to prograde.
  stage.
  wait 1.
  stage.
}

Пришло время протестировать предлагаемый метод вывода.
Для этого я сделал простой крафт:
Тестовый крафт для вывода на орбиту

Рисунок 2. Аппарат для тестирования вывода на орбиту.

Все функции нужно скопировать в файл (пусть будет KSPutnik.ks), который поместить в папку Ships/Script. После определения всех функций не забыть написать
gettoorbit().

для запуска собственно полёта. На стартовом столе открываем kOS терминал, пишем
copypath("0:/KSPutnik.ks","KSPutnik.ks").
runpath("KSPutnik.ks").

Наслаждаемся мультиком.
В полёте

Рисунок 3. Разворот надо бы сделать чуть менее агрессивным.

К сожалению, в конце антенны спутника оказываются свёрнутыми. Чтобы это исправить, после сброса обтекателя надо добавить следующий код:

  set alist to ship:partsnamed("longAntenna").
  for an in alist {
    set d to an:getmodule("ModuleRTAntenna").
    d:doevent("activate").
  }

Первая строчка создаёт список всех частей аппарата с заданным именем (имя можно посмотреть в ЦВС по ПКМ на часть - "Change Name Tag"). Далее проходим циклом по всем антеннам и раскрываем их. Сам я пока эту чёрную магию не совсем понимаю, интересующиеся могут почитать официальное руководство .

С обновлённой циклограммой запуска спутник выходит на орбиту, разворачивает антенны и отделяется от носителя и работает как ретранслятор для последующих запусков. Сброшенная ступень остаётся космическим мусором. Спутник в этом тоже к ней присоединится когда у него закончится электричество.

Итак, теперь написан достаточно универсальный скрипт для вывода спутника на экваториальную орбиту. В следующей части - простейшее орбитальное маневрирование и развёртывание группировки спутников-ретрансляторов.

Крафт и скрипт вывода (переименовать .ks.txt в .ks):

- + +23
У Вас НЕТ прав на выставление оценки для этой новости.
Для выставлени оценки необходимо пройти регистрацию на сайте.
Если Вы уже зарегистрировались, то войдите на сайт.
  1. 0
    Это Soul Soul - #10 0
    0
    А файлы/листинги примеров будут?
    »
    Написано:
    Группа: Посетители, Публ/Комм: 0/18
     
    1. 7
      Это Pand5461 Pand5461 - #20 0
      +1
      Под спойлером в самом конце.
      »
      Написано:
      Группа: Хорошие люди, Публ/Комм: 10/36 [Онлайн]
       
      1. 0
        Это Soul Soul - #30 0
        0
        Цитата: Pand5461
        Под спойлером в самом конце.

        Спасибо за ответ, сразу не увидел, пардон.
        »
        Написано:
        Группа: Посетители, Публ/Комм: 0/18
         
  2. 0
    Это Nexsius Nexsius - #40 0
    0
    Хм. Я видимо совсем неудачник... Скачал крафт и скрипт, а оно не летает...
    Стартовать стартует, но в последствии начинает переворачиваться и крутиться :( что я делаю не так?
    »
    Написано:
    Группа: Посетители, Публ/Комм: 0/1
     
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
Чат
  • Трансляции
  • Информация
    На какой стороне Силы Вы?
Последние комментарии
  • Rudolf Rudolf написал в
    The Grand Tour Кербин - Муна - ... (всего 7 комм.)
    Огромное спасибо!
    Я уже убедился, что в изначальной концепции крафта до Дюны добраться труда не составит, но вот вернуться на Кербен...
  • Lynx Lynx написал в
    The Grand Tour Кербин - Муна - ... (всего 7 комм.)
    Так-то нормально для новичка, но Кербен?
  • Marschig Marschig написал в
    The Grand Tour Кербин - Муна - ... (всего 7 комм.)
    По доработке.
    Надо выкинуть лишние детали: ТТУ, крылышки, RCS двигатели, бак с монотопливом, LV-T30 с лендера (для Дюны всё равно хватит одного LV-909). Тем самым снизим TWR на старте до подходящего уровня и увеличим запас dV на 1300 м/с.

    Векторинга двигателей для управления достаточно, носитель взлетает баллистической кривой в прогрейд за ~3200 м/с, на низкой орбите остаётся ~7 км/с.



    Аппарат, безусловно, избыточен для заявленных целей, что на Муну-Минмус, что на Дюну. Но что от него требуется делает, и статья оформлена пристойно для первого раза. Поставил плюс :)
  • Rudolf Rudolf написал в
    The Grand Tour Кербин - Муна - ... (всего 7 комм.)
    Последовательность исправлена, перезалил крафт в оригинальной версии, без парашютов. Спасибо, буду дорабатывать cold_sweat
  • TAL TAL написал в
    The Grand Tour Кербин - Муна - ... (всего 7 комм.)
    Конструктивную критику? Ок, это мы могем :)
    1 В файле сохранения нарушена последовательность срабатывания ступеней
    2 Паращюты 1-й и 2-й "возвращаемой" ступени несработают на той высоте и с той скоростью - убрать
    3 РН неустойчив и болтается как сосиска - смог вывести на орбиту только "буквой Г"
    4 Монопропилен ненужен - поставить один большой САС
    5 Слишком много посадочных ног
    6 Излишне мощные боковые движки лендера - Терьеры 909 самое то
    7 Боковые баки лендера соединить с центральным шлангами, а движки убрать
    8 Лендер неустойчив при посадке - схема с тремя боковыми баками надежнее

    До Дюны дотянул, но избыточные боковые движки весь взлет испортили.
  • Rudolf Rudolf написал в
    The Grand Tour Кербин - Муна - ... (всего 7 комм.)
    Спасибо, это я недоглядел, всё исправил cold_sweat
Все комментарии
Обновления на форуме
180 Всего
9 Польз.
171 Гостей
Онлайн список
Новостей на страницу:
Наверх