Автор: 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):

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

        Спасибо за ответ, сразу не увидел, пардон.
        »
        Написано:
        Группа: Посетители, Публ/Комм: 0/23 [Онлайн]
         
  2. 0
    Это Nexsius Nexsius - #40 0
    0
    Хм. Я видимо совсем неудачник... Скачал крафт и скрипт, а оно не летает...
    Стартовать стартует, но в последствии начинает переворачиваться и крутиться :( что я делаю не так?
    »
    Написано:
    Группа: Посетители, Публ/Комм: 0/1
     
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
Чат
  • Трансляции
  • Информация
    На какой стороне Силы Вы?
Последние комментарии
  • Secairus12 Secairus12 написал в
    ТАКР Адмирал Кузнецов (всего 13 комм.)
    Судя по деталям крыльев, картон.
    (автор, если что - мне очень даже нра)
  • lllypa lllypa написал в
    ΔVcalculator (ОБНОВЛЕНИЕ 1.1) (всего 12 комм.)
    О! это мысль. пожалуй сделаю.

    Кинь в меня, пожалуйста, конфигом РСС. Делов по его вкорячиванию на час-полтора.. Зато хорошее дело.
  • Soul Soul написал в
    ΔVcalculator (ОБНОВЛЕНИЕ 1.1) (всего 12 комм.)
    Тоже вариант, чёта не подумал... И правится быстро, и доступно всем без скачивания.
  • Басила Басила написал в
    ΔVcalculator (ОБНОВЛЕНИЕ 1.1) (всего 12 комм.)
    А что мешает на гугульдокс запихнуть табличку и юзать её из бравзера?) мне дома офис лень ставить, в тех редких случаях, когда он нужен - так и делаю)
  • KTO_TO KTO_TO написал в
    ТАКР Адмирал Кузнецов (всего 13 комм.)
    а броня хорошая? (у реплики)
  • KTO_TO KTO_TO написал в
    Мод SSTO Parts Plus - тест (всего 6 комм.)
    ладно, ты мне нурсы сделал
Все комментарии
Обновления на форуме
131 Всего
5 Польз.
126 Гостей
Яндекс, Google, aleksei1, Rsa, KTO_TO, Secairus12, Alexa, SpacePixel
Онлайн список
Новостей на страницу:
Наверх