KerboScript в примерах и задачах. Часть 5-ε. ПИД-регуляторы.

Kerbal Space Program » Гайды

Предыдущие части демонстрируют впечатляющие возможности kOS для вывода на орбиту, довольно сложного маневрирования и трансферов. Разобранные примеры, в основном, демонстриро управление без обратной связи, т.е. программировалось воздействие в надежде, что оно приведёт к желаемому результату. Однако во многих случаях лучше добавить обратную связь - грубо говоря, сделать так, чтобы система знала, какого результата и корректировала введённое воздействие для более корректного его достижения.

Разберём подробнее, что имеется в виду под наличием и отсутствием обратной связи.

Пример системы, в которой управление организовано без обратной связи, - это духовка. Установка определённого уровня подачи газа (или сопротивления реостата на электрических) определяет температуру духовки, таймер - время работы. Работа устройства в режиме "180° на 10 минут" будет абсолютно одинаковой что при пустой духовке, что при поставленном туда стакане воды, что при поставленной замороженной курице.

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

При управлении с обратной связью управляющее воздействие представляет собой задание желаемого результата. В качестве примера можно привести современные электрические чайники. Целью является закипание налитой воды. Можно было сделать управление без обратной связи - например, установить таймер работы на фиксированное время, достаточное для закипания максимально возможного объёма налитой в чайник воды. Понятно, что это приведёт к лишнему расходу электричества, если кипятятся небольшие объёмы или начальная температура уже близка к 100°C. Поэтому там стоит датчик пара, по срабатыванию которого отключается питание. Благодаря этой обратной связи, реальное время работы зависит от начального состояния системы. Заодно корректно обрабатываются не вполне штатные ситуации - к примеру, если в налитую воду досыпали лёд.

Система без обратной связи обычно условно представляется следующей схемой:
Рисунок 1. Блок-схема системы управления без обратной связи.

На систему подаётся управляющее воздействие X(t), на что она реагирует изменением состояния Y(t).

В систему с обратной связью подаётся не управляющее воздействие как таковое, а желаемый закон изменения состояния G(t), и добавляется дополнительный элемент - регулятор (контроллер), который преобразует сигнал рассогласования (разницу реального и желаемого состояний) E(t) = G(t) - Y(t) в собственно управляющее воздействие X(t).

Рисунок 2. Блок-схема системы управления с обратной связью

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

Менее очевидное, но не менее важное преимущество - это стабилизация системы. Если целевое состояние системы неустойчиво, но управляющее воздействие выполняется быстрее, чем развивается неустойчивость, то в некоторых случаях это состояние таки можно стабилизировать. К примеру, велосипед без наездника неустойчив и тся набок даже в движении. При наличии контроллера в виде человека он замечательно едет, никуда не заваясь. Но если посмотреть на траекторию переднего колеса (после проезда по луже она хорошо отпечатывается на асфальте), то видно, что она не ровная, а колеблется вокруг нужного положения.

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

ПИД означает Пропорционально-Интегрально-Дифференцирующий регулятор. В нём управляющее воздействие рассчитывается из сигнала рассогласования по формуле

где KP, KIKD - коэффициенты, подбираемые исходя из желаемых характеристик отклика.

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

Сток использует такую форму контроллера для стабилизации аппарата с помощью САС, в kOS есть встроенный ПИД для контроля ориентации (через lock steering to), а также есть общая структура, которая позволяет прицепить контроллер такого вида для произвольного управления.



В kOS используется дискретный вариант регулятора:

где ti - моменты времени, в которые вычисляется ошибка управления.

Регулятор реализован через структуру PIDLOOP, имеющую следующие поля:
LASTSAMPLETIME     // время последнего обновления
KP             // коэффициент усиления пропорциональной компоненты
KI             // коэффициент усиления интегральной компоненты
KD             // коэффициент усиления дифференцирующей компоненты
INPUT             // последнее входное значение
SETPOINT     // текущее заданное значение, G(t)
ERROR             // последнее значение ошибки E(t)
OUTPUT             // последнее выходное значение Y(t)
MAXOUTPUT     // максимальное выходное значение
MINOUTPUT     // минмальное выходное значение
ERRORSUM     // интегральная компонента до домножения на KI
PTERM             // пропорциональная компонента KP*ERROR
ITERM             // интегральная компонента KI*ERRORSUM
DTERM             // дифференцирующая компонента KD*CHANGERATE
CHANGERATE     // скорость изменения ошибки dE/dt
RESET             // обнулить значение интеграла
UPDATE(time, input) // обновить выходное значение регулятора на основе момента времени и входного значения

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

Создание ПИД-регулятора возможно несколькими конструкторами:
set pid to pidloop(). // создаётся регулятор по умолчанию с KP=1, KD=KI=0
set pid to pidloop(KP).
set pid to pidloop(KP, KI, KD).
set pid to pidloop(KP, KI, KD, MINOUTPUT, MAXOUTPUT). // min и max в конструкторе должны обязательно встречаться парой

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

Рассмотрим работу с ПИД-регулятором на примере программирования ховеркрафта. Для демонстрации разницы настройки на одной и той же платформе сделаем ховеркрафт с ракетным двигателем (быстрый отклик на управление тягой) и с ВРД (медленный отклик).

Аппарат делаем в виде простейшего ховерборда:
Рисунок 3. Ховерборд - версия с воздушно-реактивными двигателями

Логика скрипта проста до неприличия. Задаётся PIDLOOP с выбранными коэффициентами усиления. Задаётся желаемая высота зависания. Затем в цикле выполняются функции LOCK THROTTLE TO PIDLOOP и PIDLOOP:UPDATE.
Для удобства пользователя в скрипт также добавлены функции изменения высоты зависания с шагом 1 метр, которые повешены на группы действия.
Тяга устанавливается как LOCK THROTTLE TO T_HOVER + PIDLOOP, где T_HOVER - уровень тяги, компенсирующий вес аппарата. Такая форма регулировки увеличивает устойчивость управления. Выходные значения регулятора ограничены значениями от -0,2×T_HOVER до 0,2×T_HOVER, чтобы аппарат слишком быстро не взмывал вверх и не впечатывался в землю.
clearscreen.
sas on.
function teleprint {
// выводит в терминал текущее состояние ПИД-регулятора
  parameter pid.
  print "Error: " + round(pid:error,2) at (0,5).
  print "PTerm: " + round(pid:pterm,2) at (0,6).
  print "ITerm: " + round(pid:iterm,2) at (0,7).
  print "DTerm: " + round(pid:dterm,2) at (0,8).
  print "Output: " + round(pid:output,2) at (0,9).
}
local dt to 0.1. // время между двумя обновлениями
// коэффициенты усиления
local Kp to 0.5.
local Ki to 0.1.
local Kd to 1.
local thrustpid to pidloop(Kp, Ki, Kd, -1, 1).
// задаём желаемую высоту зависания и ставим её как setpoint для регулятора
local wantedalt to 5.
set thrustpid:setpoint to wantedalt.
local da to 1.
// на группы 8 и 9 повесим уменьшение/увеличение высоты зависания
on AG9 {
  set thrustpid:setpoint to thrustpid:setpoint + da.
  local message2 to "Setpoint: " + round(thrustpid:setpoint,2) + " m".
  hudtext(message2, 2, 2, 22, Yellow, false).
  preserve.
}
on AG8 {
  set thrustpid:setpoint to thrustpid:setpoint - da.
  local message2 to "Setpoint: " + round(thrustpid:setpoint,2) + " m".
  hudtext(message2, 2, 2, 22, Yellow, false).
  preserve.
}
// на группу посадочных ног повесим вывод на экран текущих значений
on gear {
  local message1 to "Increment: " + round(da,2) + " m".
  local message2 to "Setpoint: " + round(thrustpid:setpoint,2) + " m".
  hudtext(message1, 2, 2, 22, Yellow, false).
  hudtext(message2, 2, 2, 22, Yellow, false).
  preserve.
}
wait until stage:number = 0.
thrustpid:update(time:seconds, alt:radar).
until false {
  local cosang to vdot(ship:facing:upvector,up:vector).
  local thhover to ship:mass*Kerbin:mu / (Kerbin:radius+altitude)^2 / ship:maxthrust / cosang. // тяга, которая уравновешивает вес
  set thrustpid:minoutput to -thhover*0.2.
  set thrustpid:maxoutput to thhover*0.2.
  lock throttle to thhover + thrustpid:update(time:seconds, alt:radar).
  log "Time: " + round(missiontime,2) + "  Altitude: " + round(alt:radar,2) to "hover.txt".
  teleprint(thrustpid).
  wait dt.
}
Этот скрипт работает с версией ховеркрафта на ракетных двигателях (например, если поставить 4 "Искры"). С воздушно-реактивными двигателями он будет вызывать сильные колебания высоты. Это происходит потому, что логика программы не учитывает большую инертность тяги ВРД. Грубо говоря, для устойчивости нужно подобрать коэффициенты таким образом, чтобы характерный период колебаний стал больше характерного времени разгона реактивных двигателей.

Для этого аппарата опытным путём установлены следующие коэффициенты, которые дают относительно неплохой результат с ВРД версией:
KP = 0.01
KI = 0.005
KD = 0.08..0.1

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

Для разнообразия в скрипте также использована функция HUDTEXT, которая выводит сообщения не в kOS терминал, а непосредственно на экран игры (по типу игровых сообщений об изменении перемотки времени). Подробную документацию по этой функции предлагаю посмотреть в официальном руководстве.

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

 
KerboScript в примерах и задачах. Часть 3.5. Предсказание положения на орбите.
16 апр 2017 в 01:45, Гайды
KerboScript в примерах и задачах. Часть 3. Предсказание орбиты. Летим на Муну.
5 апр 2017 в 21:21, Гайды
  1. alexoff

    alexoff @Александр 4 июня 2017 13:35

    видеоответ

    Почему в комментах нельзя поставить видео?

  2. Grobers

    Grobers @Grobers 6 июня 2017 17:10

    Прошу совета по моду kOS: установил его последнюю версию на стим-версию KSP (1.3) - но в игре, что называется, ни ответа, ни привета. Модули контроля-управления (детали) в базе есть, но в сборке они, почему-то не активны: по щелчку правой кнопки мыши никакие новые окна управления/редактирования/запуска скриптов не появляются. Может что не так делаю?

    1. Pand5461

      Pand5461 6 июня 2017 18:56 Автор

      Под 1.3 пока не обновили

    2. Pand5461

      Pand5461 6 июня 2017 19:07 Автор

      В стиме можно откатиться на 1.2.2, если что - ПКМ по игре, Свойства -> Бета-версии -> выбрать previous_1.2.2. Если хочется играть в последнюю версию, то её перед откатом невозбранно можно скопировать в надёжное место в другую папку на диске.

  3. Басила

    Басила 6 июня 2017 17:10

    А я знаю, почему у таких качественных и познавательных постов так мало плюсов. Большинство не осиливают и не долистывают до плюсатора)

    1. alexoff

      alexoff @Александр 6 июня 2017 17:24

      Может, потому что тут качественно рассказывается про то, что никому особо и не нужно, а плюсики ставят за старания? С таким же успехом можно хорошо и обстоятельно рассказать на форуме о контрстрайке про ассемблер.
      Ну правда - в огромных постах с матаном описывается, как напрограммировать полет к Муне и заставить крафт зависать в воздухе.

      1. Pand5461

        Pand5461 6 июня 2017 19:04 Автор

        Цитата: alexoff
        в огромных постах с матаном описывается, как напрограммировать полет к Муне и заставить крафт зависать в воздухе.

        Вот именно от этого поста я сам офигел, потому как должна была быть маленькая вводная статейка по поводу того, что за PIDLOOP, который дальше будет в скрипте вывода на наклонную орбиту. Но что-то Остапа немного понесло...
        А в полёте к Муне-то чего плохого?

        1. Басила

          Басила 6 июня 2017 19:41

          Ну это. Алекс жеж яростный противник реализма. Даже в РСС на стоке играет. Так что ему непонятная вот эта вся автоматизация того, что можно сделать руками)

          1. alexoff

            alexoff @Александр 6 июня 2017 19:48

            Тащем-та я уже не помню, когда последний раз ракету вручную выводил, жаба работает - ладно. Если не работает - придется менять ракету

  4. Давид Восканян

    Давид Восканян @Давид 27 декабря 2017 22:34

    Лайк от АТПП-шника

{login}
  • bowtiesmilelaughingblushsmileyrelaxedsmirk
    heart_eyeskissing_heartkissing_closed_eyesflushedrelievedsatisfiedgrin
    winkstuck_out_tongue_winking_eyestuck_out_tongue_closed_eyesgrinningkissingstuck_out_tonguesleeping
    worriedfrowninganguishedopen_mouthgrimacingconfusedhushed
    expressionlessunamusedsweat_smilesweatdisappointed_relievedwearypensive
    disappointedconfoundedfearfulcold_sweatperseverecrysob
    joyastonishedscreamtired_faceangryragetriumph
    sleepyyummasksunglassesdizzy_faceimpsmiling_imp
    neutral_faceno_mouthinnocent
Последние сообщения с форума
  • Автор
    Тема в разделе: Технические вопросы
    Просмотров: 24251
    Ответов: 68
  • Автор
    Тема в разделе: Моды
    Просмотров: 1457
    Ответов: 2
  • Автор
    Тема в разделе: В ангаре у Боба
    Просмотров: 206146
    Ответов: 1484
  • Автор
    Тема в разделе: Игровой процесс
    Просмотров: 1640
    Ответов: 1
  • Автор
    Тема в разделе: Модераторский раздел
    Просмотров: 7604
    Ответов: 21
    Все сообщения..
    Полный список последних сообщений
    Loading...

    Нашли ошибку?
    Вы можете сообщить об этом администрации.
    Выделив текст нажмите Ctrl+Alt