Анализ точности системы автоматического управления
Одним
из показателей качества САУ является
точность, которая определяется величиной
ошибки e(t)
в
различных режимах работы системы, Однако
из-за
сложности
определения e(t)
в
любой момент времени точность принято
оценивать по величине установившейся
ошибки:
.
Поведение
системы изучается при подаче управляющего
воздействия g(t)=g0
1(t),
изображение которого:
|
(6) |
Определение
установившейся ошибки:
Установившаяся
ошибка системы согласно теореме о
конечном значении преобразования
Лапласа вычисляется по формуле:
|
(7) |
где
;
—
передаточная функция системы относительно
ошибки:
|
(8) |
Подставляя
(8) в (7) и учитывая (6) найдем выражение
для установившейся ошибки:
|
(9) |
В
зависимости от наличия установившейся
ошибки в системе различают статические
и астатические САУ.
Статическими
называют такие САУ, в которых регулируемая
величина при различных постоянных
внешних воздействиях на объект принимает
по окончании переходного процесса
различные значения, зависящие от величины
внешнего воздействия.
Астатическими
называют такие САУ, в которых при
различных постоянных значениях внешнего
воздействия на объект управления,
отклонение регулируемой величины от
требуемого значения по окончании
переходного процесса становится равным
нулю.
Для
астатической системы передаточную
функцию всегда можно представить в
виде:
,
где
ν=1,2,… порядок астатизма системы (число
нулевых корней), а
не содержит нулевых корней.
Вычислим установившуюся ошибку для
объекта, заданного выражением (1) и
регуляторов:
—
для ПИ-регулятора:
;
—
для И-регулятора:
;
—
для П-регулятора:
.
Подставив
выражения передаточных функций в (5),
получим еуст
для различных регуляторов:
Для
ПИ и И-регулятора
,
то есть система астатическая.
Для
П-регулятора
.
Следовательно,
при ступенчатом воздействии система
является астатической, если ее передаточная
функция содержит хотя бы одно интегрирующее
звено. Поэтому с точки зрения точности
системы с И и ПИ-регуляторами
предпочтительнее системы с П-регулятором.
Таким
образом, требования к САУ по устойчивости
и точности противоречивы. Задачей
синтеза САУ является выбор таких
параметров, которые при выполнении
условий устойчивости обеспечивали бы
заданную точность системы.
Интегральная оценка качества
Интегральная
оценка качества относится к аналитическим
методам исследования качества системы
и дает общую оценку скорости затухания
и отклонения управляемой величины в
совокупности, без определения данных
параметров в отдельности.
Простейшей
интегральной квадратичной оценкой
является оценка вида:
,
где
е(t)=g(t)-y(t)
—
ошибка системы; g(t)
—
задающее воздействие; y(t)
— регулируемая величина.
Если
е(t)
имеет
постоянную составляющую в виде
установившегося значения eуст,
то интеграл J0
будет
расходящимся, поэтому в качестве ошибки
берут динамическую ошибку системы
e1(t),
т.е. отклонение регулируемой величины
y(t)
от
ее установившегося значения:
e1(t)=
yуст
—y1(t)=
g(t)-
eуст
—y(t)=
e(t)-
eуст
.
Интегральная
квадратичная оценка может быть определена
по изображению ошибки:
|
(10) |
Для
практических целей более удобной
является формула Релея, которая получается
заменой р
(10) на jω:
|
(11) |
Если подынтегральное выражение
представить в виде:
,
где
A(jω)=a0(jω)n+ |
(12) |
B(jω)= |
(13) |
то
интеграл (10) будет вычисляться по формуле:
|
(14) |
где
—
старший определитель Гурвица;
.
Выбор оптимальных
параметров управляющего устройства по
минимуму интегральной оценки
При
заданной структуре САУ задача выбора
параметров сводится к следующему.
Необходимо отыскать такие значения
изменяемых параметров, при которых
квадратичная интегральная оценка
становится минимальной.
В
системе автоматического управления,
исследуемой в лабораторной работе,
переменным параметром является постоянная
времени интегратора Tu.
Все постоянные времени и коэффициенты
передачи заданы константами. Следовательно,
задача состоит в определении оптимального
значения Tu
опт,
при котором J0=min.
В
качестве управляемого устройства
рассматривается И- или ПИ-регулятор.
Запишем
изображения ошибки Е1(р)
при
T1=
T2
:
—
для И-регулятора:
;
—
для ПИ-регулятора:
.
Составим
выражение для квадратичной интегральной
оценки в виде (11) в случае ПИ-регулятора.
Определим полиномы Α(jω)
и
B(jω)
соглаcно
уравнениям (12) и (13):
|
(15) |
|
|
(16) |
Из
выражений (15) и (16) найдем коэффициенты
аi
и bi:
|
|
|
|
|
|
|
|
|
|
При
подстановке данных коэффициентов в
(14) получим выражение интегральной
квадратичной оценки для ПИ-регулятора:
|
(17) |
Выражение
для J0
в
случае И-регулятора получается из (17)
как частный случай подстановкой kп=
0
для И-регулятора:
|
(18) |
Искомое
значение Tu
опт,
при
котором квадратичная оценка имеет
минимум, найдем, дифференцируя (17) и (18)
по Tu
и приравнивая производную к нулю.
Окончательно имеем
—
для ПИ-регулятора:
|
(19) |
—
для И-регулятора:
|
(20) |
При
схемотехнической и программной реализации
рассмотренных регуляторов, удобнее
пользоваться коэффициентом передачи
интегрирующего блока, который является
обратной величиной по отношению к
постоянной
времени:
.
Исходя
из выражений (19) и (20), получим значение
оптимального суммарного коэффициента
передачи интегрирующего блока. При
использовании ПИ-регулятора он равен:
.
Для
И-регулятора оптимальный коэффициент
передачи интегрирующего блока составляет:
.
Соседние файлы в папке лр
- #
- #
- #
- #
- #
- #
Интегральная квадратичная ошибка
Cтраница 1
Интегральная квадратичная ошибка определяется как интеграл квадратов мгновенных ( текущих) значений рассогласования. При возведении в квадрат текущих значении рассогласования отрицательные величины не компенсируют положительные, поэтому с возрастанием рассогласования интегральная квадратичная ошибка растет очень быстро.
[1]
Эти коэффициенты соответствуют минимуму интегральной квадратичной ошибки между f ( t) и апроксимирующей функцией, что вытекает из (9.81), если Г оо. Полная функция f ( t) подбирается так, чтобы при этом значении Т получить наилучшую апроксимацию.
[2]
В этом разделе в качестве критерия оценки точности апроксимации применяется интегральная квадратичная ошибка. Выбор этого критерия диктуется главным образом удобством его применения; вместе с тем во многих конкретных случаях он служит весьма хорошей оценкой точности апроксимации. В нем одинаково учитываются как положительные, так и отрицательные ошибки. Критерий интегральной квадратичной ошибки достаточно хорошо оценивает большие и длительные ошибки, а малые и кратковременные ошибки слабо сказываются на его величине.
[3]
Экспоненциальные функции не являются ортогональными в любом интервале, так что критерий минимума интегральной квадратичной ошибки к такому ряду функций приложить нелегко.
[4]
С усилением интегрального воздействия ( уменьшение времени интегрирования) процесс из апериодического переходит в колебательный со все более уменьшающейся степенью затухания; при этом динамическая ошибка регулирования уменьшается, а время регулирования и интегральная квадратичная ошибка регулирования возрастают.
[5]
Для выбора наиболее рациональных с точки зрения технологии переходных процессов по каналам регулирования обычно выполняются расчеты для четырех процессов регулирования: без перерегулирования, с 20 % — ным перерегулированием, с минимальным временем регулирования и с минимальной интегральной квадратичной ошибкой.
[7]
Интегральные ошибки этих трех переходных процессов равны, так как настройки диапазона пропорциональности и времени изо-дрома регулятора во всех случаях одинаковы. Интегральная квадратичная ошибка последнего переходного процесса меньше, чем у первых двух, так как он имеет меньшую динамическую ошибку.
[9]
В частности, это имеет место для систем с симметричными и кососимметрич-ньгми матрицами А в силу ортогональности их канонических базисов. Эквивалентные сепаратные системы равноправны с точки зрения квадратичной оценки для системы в целом: значения их интегральных квадратичных ошибок входят в сумму ( ИЗ) с одинаковым весом.
[10]
Интегральная квадратичная ошибка определяется как интеграл квадратов мгновенных ( текущих) значений рассогласования. При возведении в квадрат текущих значении рассогласования отрицательные величины не компенсируют положительные, поэтому с возрастанием рассогласования интегральная квадратичная ошибка растет очень быстро.
[11]
Для большинства методов решения задачи синтеза оптимальных виброзащитных систем характерны следующие принципы: используется линейная динамическая модель с одной степенью свободы; для системы с двумя степенями свободы рассматриваются лишь частные случаи синтеза; учитывается не более одного ограничения; для одной и той же модели изменение спектральной плотности воздействия приводит к необходимости повторения процесса решения задачи. Например, для синтеза оптимальной системы с активным динамическим гасителем колебаний ( судовых механизмов и машин) был выбран метод минимально-квадратичной оптимизации, позволяющий синтезировать системы с наименьшим значением интегральной квадратичной ошибки при учете ограничений, накладываемых объектом.
[12]
На практике наиболее широкое распространение при оценке качества работы ристем регулирования получили интегральная и интегральная квадратичная ошибки. Принципиальное отличие между ними состоит в том, что вторая учитывает абсолютное значение ошибки. Например, две кривые переходного процесса с различными амплитудами колебаний параметра могут иметь одинаковые интегральные ошибки, но разные интегральные квадратичные ошибки.
[13]
В этом разделе в качестве критерия оценки точности апроксимации применяется интегральная квадратичная ошибка. Выбор этого критерия диктуется главным образом удобством его применения; вместе с тем во многих конкретных случаях он служит весьма хорошей оценкой точности апроксимации. В нем одинаково учитываются как положительные, так и отрицательные ошибки. Критерий интегральной квадратичной ошибки достаточно хорошо оценивает большие и длительные ошибки, а малые и кратковременные ошибки слабо сказываются на его величине.
[14]
Страницы:
1
2
характеристике Переходный
режим вызван тем, что система инерционна
и должна некоторое время приспосабливаться
к поступающим на нее воздействиям. В
этих условиях оценку качества удобно
вести при наиболее тяжелом с точки
зрения воспроизведения системой
воздействии, таком, как ступенчатая
функция А*l(t).
Реакция системы на единичную ступенчатую
функцию является переходным процессом h(t),
по форме которого в простейшем случае
и можно судить о качестве переходного
режима.
На рис.
52.
изображены переходные характеристики
колебательного и монотонного типов,
оценка которых проводится с помощью
локальных критериев, называемых
показателями качества переходной
характеристики.
Рис.
52. Показатели качества переходной
характеристики
Для
характеристик колебательного типа
обычно используются следующие
показатели: Hm —
перерегулирование, которое определяет
относительное максимальное отклонение;
время установления tу —
момент достижения первого максимума;
время регулирования tр,
которое определяет длительность процесса
по уровню + 0,05 относительно установившегося
значения; период колебаний T.
Для
монотонных характеристик наиболее
употребительным является показатель
длительности переходного процесса tр. В
общем случае точное построение переходных
характеристик и, следовательно,
определение качества затруднительно.
Существует ряд методов, позволяющих
приближенно строить переходные
характеристики, однако эти методы сложны
и приводят к громоздким вычислительным
работам. Найти точные значения указанных
выше величин удается только для простейших
систем первого и второго порядков. Для
более сложных следящих систем существуют
приближенные формулы их нахождения.
В
основе формул лежит знание двух
параметров: частоты среза разомкнутой
следящей системы w с
и запаса по фазе. Эти параметры могут
быть найдены аналитически или по
логарифмическим частотным характеристикам.
Сводка вычислительных соотношений
приводится в табл.
П. 2.
2.2.3. Интегральный квадратичный критерий качества переходного режима
Локальные
критерии качества обычно наглядны, но
трудно вычисляются аналитически.
Примером тому служат показатели
переходной характеристики, рассмотренные
выше. Интегральные критерии, особенно
квадратичные, достаточно легко
вычисляются, однако не так наглядны,
как локальные. Обратимся к рис.53,
на котором изображены два монотонных
переходных процесса. Процесс 1 наименьшей
длительности. Об этом может свидетельствовать
такой косвенный фактор, как площадь
между кривой h(t)
и уровнем установившегося значения
выходного процесса. Отсюда для оценки
качества можно ввести критерий
где
через eп (t)
обозначена ошибка переходного режима,
представляющая разность между текущим
и установившемся значениями переходной
характеристики. Чем меньше Q, тем выше
качество САУ.
Причем
подынтегральная квадратичная функция
потерь eп(t)
будет неотрицательной как для монотонных,
так и для колебательных процессов.
Очевидно,
что описанные критерии можно использовать
не только для случая переходной
характеристики, но и при произвольных
воздействиях.
Рис.53.
Сравнение качества переходных
характеристик
Рассмотрим
методику нахождения интегрального
квадратичного критерия переходного
режима для регулярного воздействия x(t).
Изображение
динамической ошибки можно записать в
виде произведения
e(p) = |
(29) |
Не
прибегая к нахождению оригинала eх(t), можно
найти установившееся значение ошибки
управления
,
или
.
Если
из полной ошибки eх(t)
вычесть ошибку установившегося
режима eх уст,
то получим составляющую, которая равна
ошибке переходного режима
еп(t) =
eх (t) —
eх уст.
Очевидно,
что
еп(t) 0
при t ,
так как eх (t) eх уст.
Интегральный
квадратичный критерий качества
переходного режима определим как
величину
На
основании известной теоремы Парсеваля,
нахождение интегрального квадратичного
критерия качества Q переходного
режима сводится к вычислению интеграла
Парсеваля
(30) |
Чтобы
вычислить конкретное значение этого
интеграла, функцию eп(p)
записывают в виде отношения полиномов
.
Тогда
интеграл будет функцией параметров a ,
и b . Значения функций табулированы
и для n <
4 приведены в табл.
П.3.
Изображение
ошибки переходного режима получаем из
формулы:
где
учтено, что изображение от
постоянной ex уст равно e x уст /p.
Пример.
Найдем
интегральный квадратичный критерий
качества переходного процесса в системе
управления антенной.
Передаточная
функция разомкнутой системы
,
Передаточная
функция ошибки по задающему воздействию
равна
.
Так
как рассматривается переходный процесс,
то воздействием является единичная
функция
x(t) = 1 (t)
с
изображением
x(p)=1/p .
Изображение
ошибки управления
.
Установившееся
значение ошибки
В
итоге получим, что изображение ошибки
переходного режима равно
где
a 0 =
1+K;
a 1 =
T; b 0 =
K; b 1 =
1+K; b 2 =
T.
Согласно
формуле (30)
интегральный квадратичный критерий
качества переходного режима равен
интегралу Парсеваля
Q
= I
[e п (p)].
Используя
данные табл.
П.3. для n =
2, находим значение интеграла
.
Из
этого результата видно, что изменением
параметров системы можно в широких
пределах изменить величину критерия.
Особенно характерны в этом отношении
два параметра: Rи T.
На
практике для регулировки показателей
переходного процесса широко используют
коэффициент преобразования К элемента,
не охваченного внутренней обратной
связью. В то же время постоянную
времени T усилителя
следует подбирать так, чтобы величина
первого слагаемого критерия не превышала
допустимого уровня.
252
Точность САУ
Точность
САУ оценивается в установившемся режиме
по величине установившейся ошибки при
типовых воздействиях. При анализе
точности систем рассматривается
установившийся режим, так как текущее
значение ошибки резко меняется вследствие
наличия переходных процессов и не может
быть мерой точности.
Рассмотрим
систему представленную на рис. 1.
На
схеме приняты следующие обозначения:
Kу(p)
– передаточная функция устройства
управления; K0(p)
– передаточная функция объекта
управления; f
–
возмущающее воздействие; x
–
задающее воздействие; y
– регулируемая величина.
Ошибка
по задающему воздействию равна (t)
= x(t) – y(t).
Изображение
ошибки равно
(1)
Установившееся
значение ошибки определяется с помощью
теоремы о конечном значении функции
(2)
Ошибка
по возмущению воздействию равна (t)
= – y(t),
т.е. равна изменению регулируемой
величины под действием возмущения при
отсутствии входного воздействия.
В общем
случае как задающее, так и возмущающее
воздействия являются сложными функциями
времени. При определении ошибок пользуются
типовыми воздействиями, которые с одной
стороны соответствуют наиболее тяжелым
режимам работы системы и, вместе с тем,
достаточно просты для аналитических
исследований.
Кроме
того, типовые воздействия удобны для
сравнительного анализа различных
систем, и соответствуют наиболее часто
применяемым законам изменения управляющих
и возмущающих воздействий.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
- #
04.08.2019142.76 Кб022.rtf
- #
- #
- #
- #
- #
- #
04.08.2019112.25 Кб126.rtf
- #
- #
- #
- #
Интегральная квадратичная ошибка
Cтраница 1
Интегральная квадратичная ошибка определяется как интеграл квадратов мгновенных ( текущих) значений рассогласования. При возведении в квадрат текущих значении рассогласования отрицательные величины не компенсируют положительные, поэтому с возрастанием рассогласования интегральная квадратичная ошибка растет очень быстро.
[1]
Эти коэффициенты соответствуют минимуму интегральной квадратичной ошибки между f ( t) и апроксимирующей функцией, что вытекает из (9.81), если Г оо. Полная функция f ( t) подбирается так, чтобы при этом значении Т получить наилучшую апроксимацию.
[2]
В этом разделе в качестве критерия оценки точности апроксимации применяется интегральная квадратичная ошибка. Выбор этого критерия диктуется главным образом удобством его применения; вместе с тем во многих конкретных случаях он служит весьма хорошей оценкой точности апроксимации. В нем одинаково учитываются как положительные, так и отрицательные ошибки. Критерий интегральной квадратичной ошибки достаточно хорошо оценивает большие и длительные ошибки, а малые и кратковременные ошибки слабо сказываются на его величине.
[3]
Экспоненциальные функции не являются ортогональными в любом интервале, так что критерий минимума интегральной квадратичной ошибки к такому ряду функций приложить нелегко.
[4]
С усилением интегрального воздействия ( уменьшение времени интегрирования) процесс из апериодического переходит в колебательный со все более уменьшающейся степенью затухания; при этом динамическая ошибка регулирования уменьшается, а время регулирования и интегральная квадратичная ошибка регулирования возрастают.
[5]
Для выбора наиболее рациональных с точки зрения технологии переходных процессов по каналам регулирования обычно выполняются расчеты для четырех процессов регулирования: без перерегулирования, с 20 % — ным перерегулированием, с минимальным временем регулирования и с минимальной интегральной квадратичной ошибкой.
[7]
Интегральные ошибки этих трех переходных процессов равны, так как настройки диапазона пропорциональности и времени изо-дрома регулятора во всех случаях одинаковы. Интегральная квадратичная ошибка последнего переходного процесса меньше, чем у первых двух, так как он имеет меньшую динамическую ошибку.
[9]
В частности, это имеет место для систем с симметричными и кососимметрич-ньгми матрицами А в силу ортогональности их канонических базисов. Эквивалентные сепаратные системы равноправны с точки зрения квадратичной оценки для системы в целом: значения их интегральных квадратичных ошибок входят в сумму ( ИЗ) с одинаковым весом.
[10]
Интегральная квадратичная ошибка определяется как интеграл квадратов мгновенных ( текущих) значений рассогласования. При возведении в квадрат текущих значении рассогласования отрицательные величины не компенсируют положительные, поэтому с возрастанием рассогласования интегральная квадратичная ошибка растет очень быстро.
[11]
Для большинства методов решения задачи синтеза оптимальных виброзащитных систем характерны следующие принципы: используется линейная динамическая модель с одной степенью свободы; для системы с двумя степенями свободы рассматриваются лишь частные случаи синтеза; учитывается не более одного ограничения; для одной и той же модели изменение спектральной плотности воздействия приводит к необходимости повторения процесса решения задачи. Например, для синтеза оптимальной системы с активным динамическим гасителем колебаний ( судовых механизмов и машин) был выбран метод минимально-квадратичной оптимизации, позволяющий синтезировать системы с наименьшим значением интегральной квадратичной ошибки при учете ограничений, накладываемых объектом.
[12]
На практике наиболее широкое распространение при оценке качества работы ристем регулирования получили интегральная и интегральная квадратичная ошибки. Принципиальное отличие между ними состоит в том, что вторая учитывает абсолютное значение ошибки. Например, две кривые переходного процесса с различными амплитудами колебаний параметра могут иметь одинаковые интегральные ошибки, но разные интегральные квадратичные ошибки.
[13]
В этом разделе в качестве критерия оценки точности апроксимации применяется интегральная квадратичная ошибка. Выбор этого критерия диктуется главным образом удобством его применения; вместе с тем во многих конкретных случаях он служит весьма хорошей оценкой точности апроксимации. В нем одинаково учитываются как положительные, так и отрицательные ошибки. Критерий интегральной квадратичной ошибки достаточно хорошо оценивает большие и длительные ошибки, а малые и кратковременные ошибки слабо сказываются на его величине.
[14]
Страницы:
1
2
Интегральные оценки качества являются интегралами по времени от некоторых функций переходного процесса свободной составляющей выходной величины или ошибки Цель использования таких критериев состоит в том, чтобы получить общую оценку быстродействия и отклонения регулируемой величины от установившегося значения. Широко используются линейные и квадратичные интегральные оценки. Линейные оценки вычисляются по формуле
Рис. 4.19
Рис. 4.20
Однако чаще используют моменты порядка, т. е. оценки вида
Простейшей из этих оценок является Если система устойчива, то интеграл стремится к конечному значению, равному площади под кривой (рис. 4.19). Чем выше быстродействие системы, тем меньше величина поэтому параметры системы следует выбирать так, чтобы стремился к минимуму, т. е. где А — варьируемый параметр системы. Недостатком этой оценки является то, что она применима к монотонным или апериодическим процессам. При колебательном процессе (рис. 4.20) площади, ограниченные складывают алгебраически и минимуму может соответствовать процесс с большим числом колебаний т. е., с малым быстродействием и даже с незатухающими колебаниями.
Для изображение по Лапласу
Сравнивая это выражение с (4.47) для можно записать
Разложим в ряд по степеням
Подставим (4.51) в выражение для определения т. е.
Если разложить степеням s в ряд:
то, сопоставляя (4.52) и (4.53), можно сделать следующее заключение, приравнивая выражения при равных степенях
Если сравнить результаты (4.50), с коэффициентами ошибок, приведенными в § 4.2, то где коэффициенты ошибок.
Квадратичные интегральные оценки вычисляются по формулам
где — постоянные величины.
Оценки называют обобщенными квадратичными ценками.
Геометрический смысл интегральной квадратичной оценки ояснен на рис. 4.21. Выбирая параметры системы по минимуму квадратичной интегральной оценки приближаем кривую к осям
Методы вычисления этих оценок предложены А. И. Манелыптамом и Н. Д. Папалекси в 1909 г. В 1937 г. акад. А. А. [аркевич применил эту оценку для исследования режимов аботы усилителей, в 1948 г. А. А. Красовский и А. А. Фельдаум использовали ее для исследования качества линейных истем автоматического регулирования.
Рассмотрим методы вычисления квадратичных интегральных оценок По определению,
По теореме о предельных переходах,
педовательно,
Поскольку — дробно-ациональная функция, то и можно записать в виде дробно-рациональной функции:
Рис. 4.21
При оценку можно вычислить, используя коэффициенты по формулам, приведенным ниже без вывода [4]:
где — определитель Гурвица, составленный из коэффициентов:
в котором все коэффициенты с меньшим индексом 0 и большим заменяют нулями. Определители получают из (4.62) заменой столбца столбцом .
Коэффициенты определяют как
Интегральную квадратичную оценку можно вычислять по заданной частотной характеристике замкнутой системы.
Пусть — изображение Фурье для функции на основании теоремы свертки в комплексной области для можно записать [7] при
где комплексный коэффициент усиления замкнутой системы.
Таким образом, по (4.64) и (4.65) можно вычислить Выражение (4.64) есть формула Рэлея.
Существуют таблицы расчета интеграла в функции коэффициентов изображения по Лапласу сигнала ошибки для и до . В табл. 4.1 приведены формулы для при
Таблица 4.1
где
При выборе параметров системы по минимуму оценки часто получают нежелательную колебательность процесса, так как приближение процесса к идеальному скачку вызывает резкое увеличение начальной скорости, что, в свою очередь, может вызвать высокое перерегулирование, уменьшив
при этом запас устойчивости. В обобщенных квадратичных оценках накладывают ограничение не только на величину отклонения но и на скорость отклонения а также и на производные второго, третьего и высших порядков в что означает приближение кривой не к ступенчатой функций, а к экспоненте в случае и к более плавной, но сложной кривой в случае использования При выборе параметров САУ по минимуму существен выбор постоянных определяющих вес производных в обобщенных квадратичных оценках (4.58), (4.59). Значительное увеличение приводит к отсутствию перерегулирования, но увеличивает время регулирования. При малых уменьшение колебательности будет незначительным. Выбор осуществляется с учетом постоянной времени экстремали, к которой целесообразно приближать процесс.
Остановимся на методике расчета системы по минимуму обобщенной квадратичной оценки:
Этот интеграл можно представить в виде суммы двух интегралов:
Если система устойчива, то тогда
Кроме того, интеграл будет иметь минимально возможное значение
при
Если
то решение дифференциального уравнения (4.68)
является оптимальным по минимуму (экстремальным) переходным процессом (где — постоянная времени этого процесса).
При выборе параметров системы по минимуму обычно имеет место отклонение от наименьшего значения
А. А. Фельдбаумом [10] было показано, что переходный процесс будет отличаться от экстремального на величину, меньшую , т. е.
По величине 6 можно оценить отклонение истинного переходного процесса от экстремального (рис. 4.22). При увеличении порядка системы увеличивается и ширина зоны при этом уменьшается точность оценки качества системы (приближения переходного процесса к экстремали); во избежание этого используют оценки вида (4.59). Величину задают по требуемому времени регулирования
Следует заметить, что задача выбора параметров по минимуму или решается аналитически лишь в несложных случаях для САУ невысокого порядка. В противном случае расчеты существенно усложняются и задачу следует решать численно на ЦВМ.
Рассмотрим примеры выбора оптимального значения какого-либо параметра системы по минимуму
Пример 4.4. Вычислить значение коэффициента усиления системы, минимизирующие
Рис. 4.22
мизирующее квадратичную интегральную оценку Известна передаточная, функция разомкнутой системы
где
Входной сигнал — единичная функция Изображение отклонения по Лапласу
где
Воспользуемся формулами для вычисления приведенными в табл. 4.1 для
Определим частную производную:
Определим из Подставляя числовые значения коэффициентов, получим
откуда
Пример 4.5. Определить оптимальное значение коэффициента усиления к, соответствующее минимуму обобщенной квадратичной оценки
Передаточная функция разомкнутой системы .
Входной сигнал — единичная функция Можно представить в виде суммы:
Изображение отклонения по Лапласу
где
Воспользуемся данными табл. 4.1 и определим значение для
Определим изображение производной из свойства преобразований Лапласа:
По теореме о предельном переходе,
Тогда
где
Теперь можно определить интеграл
пользуясь формулой для из табл. 4.1 для
Итак,
Определим из т. е.
откуда
Оптимальный переходный процесс описывается в соответствии с формулой (4.69) выражением
Так как то по (4.66) наименьшее значение оценки Следовательно Согласно (рис. 4.2).
Интегральные оценки качества широко используются при синтезе оптимальных САУ в качестве критерия оптимальности.
Широкое
распространение среди косвенных методов
исследования качества процессов
регулирования получили интегральные
оценки. Это оценки качества переходной
характеристики, а именно: быстроты
затухания ее колебаний и величины
отклонения регулируемого параметра от
установившегося значения. Рассмотрим
наиболее употребительные интегральные
оценки.
Недостатки двух первых
интегральных оценок преодолеваютсяквадратичной
интегральной оценкой(формула
Рэлея)
На
рис.5.6 представлена геометрическая
интерпретация квадратичной интегральной
оценки качества, численно равная площади
, заключенной между осью времени и
квадратом динамической ошибки
регулирования e2(t).
Этот
интеграл находится также по виду
передаточной функции замкнутой САУ.
Целесообразность же ее применения
обусловлена тем, что существуют готовые
формулы для расчета численных значений
I2.
Следует однако заметить, что
минимизация оценки I2приближает
кривую переходного процесса к 1(t), что,
в свою очередь, вызывает значительное
увеличение скорости отработки сигнала
в начальный момент времени. Чтобы
получить быстро затухающий и достаточно
плавный процесс, вводятулучшенные
квадратичные интегральные оценки
качества, например
где
τ назначается в соответствии с заданием
желаемых свойств переходного процесса.
В этом случает предельной переходной
характеристикой будет экспонента е+τ=0
с желаемой постоянной времени τ,
получившая название экстремаль. Удобство
интегральных оценок состоит в том, что
они дают единый числовой критерий
качества. Недостатком является то, что
одному и тому же значению интегральной
оценки могут отвечать разные формы
переходного процесса, что создает
недостаточную определенность решения
задачи.
Квадратичная
интегральная оценка.
Может
применяться для оценки как монотонных,
так и колебательных переходных процессов.
Если
выбирать параметры системы исходя из
минимума квадратичной интегральной
оценки
,
то переходный процесс может оказатьсясильноколебательным.
Данный факт ограничивает использование
квадратичных интегральных оценок при
анализе и синтезе систем автоматического
управления
11 Метод гармонической линеаризации
Метод
гармонической линеаризации является
приближенным методом исследования
режима автоколебаний нелинейных систем.
Этим методом можно определить условия
возникновения и параметры автоколебаний,
как в системах второго порядка, так и в
более сложных системах.
Метод
заключается в замене существенно
нелинейного элемента с
характеристикой эквивалентным
линейным звеном с коэффициентом.
В замкнутой автоматической системе,
работающей в режиме автоколебаний,
условием эквивалентности служит
равенство амплитуд и фаз выходного
сигнала эквивалентного звена и первой
гармоники выходного сигнала реального
нелинейного элемента. При этом
предполагается, что сигнал на входе
нелинейного элемента является
синусоидальным. Такое предположение
справедливо во всех случаях, когда
линейная часть системы достаточно
инерционна и не пропускает высшие
гармоники.
12
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
Вместо введения
Системы автоматического управления (САУ) предназначены для автоматического изменения одного или нескольких параметров объекта управления с целью установления требуемого режима его работы. САУ обеспечивает поддержание постоянства заданных значений регулируемых параметров или их изменение по заданному закону либо оптимизирует определенные критерии качества управления. Например, к таким системам относятся:
- системы стабилизации,
- системы программного управления,
- следящие системы
Это достаточно широкий класс систем, которые можно найти где угодно. Но какое это отношение имеет к Unity3D и вероятно к играм в частности? В принципе прямое: в любой игре так или иначе использующей симуляцию как элемент геймплея реализуются САУ, к таким играм относятся, например, Kerbal Space Programm, Digital Combat Simulator (бывший Lock On), Strike Suit Zero и т.д. (кто знает еще примеры — пишите в комментариях). В принципе любая игра, моделирующая реальные физические процессы, в том числе и просто кинематику с динамикой движения, может реализовывать те или иные САУ — этот подход проще, естественнее, а у разработчика уже есть есть набор готовых инструментов, предоставленных всякими Вышнеградскими, Ляпуновыми, Калманами, Чебышевами и прочими Коломогоровами, поэтому можно обойтись без изобретения велосипеда, т.к. его уже изобрели, да так, что получилась отдельная наука: Теория автоматического управления. Главное тут не переусердствовать. Одна тут только проблема: рассказывают про ТАУ не везде, не всем, зачастую мало и не очень понятно.
Немножко теории
Классическая система автоматического управления представленная на следующем рисунке:
Ключевым элементом любой САУ является регулятор представляющий из себя устройство, которое следит за состоянием объекта управления и обеспечивает требуемый закон управления. Процесс управления включает в себя: вычисление ошибки управления или сигнала рассогласования e(t) как разницы между желаемой уставкой (set point или SP) и текущей величиной процесса (process value или PV), после чего регулятор вырабатывает управляющие сигналы (manipulated value или MV).
Одной из разновидностью регуляторов является пропорционально-интегрально-дифференцирующий (ПИД) регулятор, который формирует управляющий сигнал, являющийся суммой трёх слагаемых: пропорционального, интегрального и дифференциального.
Где, ошибка рассогласования, а также, — пропорциональная, — интегральная, — дифференциальная составляющие (термы) закона управления, который в итоговом виде описывается следующими формулами
Пропорциональная составляющая P — отвечает за т.н. пропорциональное управление, смысл которого в том, что выходной сигнал регулятора, противодействует отклонению регулируемой величины (ошибки рассогласования или еще это называют невязкой) от заданного значения. Чем больше ошибка рассогласования, тем больше командное отклонение регулятора. Это самый простой и очевидный закон управления. Недостаток пропорционального закона управления заключается в том, что регулятор никогда не стабилизируется в заданном значении, а увеличение коэффициента пропорциональности всегда приводит к автоколебаниям. Именно поэтому в довесок к пропорциональному закону управления приходиться использовать интегральный и дифференциальный.
Интегральная составляющая I накапливает (интегрирует) ошибку регулирования, что позволяет ПИД-регулятору устранять статическую ошибку (установившуюся ошибку, остаточное рассогласование). Или другими словами: интегральное звено всегда вносит некоторое смещение и если система подвержена некоторыми постоянным ошибкам, то оно их компенсирует (за счет своего смещения). А вот если же этих ошибок нет или они пренебрежительно малы, то эффект будет обратным — интегральная составляющая сама будет вносить ошибку смещения. Именно по этой причине её не используют, например, в задачах сверхточного позиционирования. Ключевым недостатком интегрального закона управления является эффект насыщения интегратора (Integrator windup).
Дифференциальная составляющая D пропорциональна темпу изменения отклонения регулируемой величины и предназначена для противодействия отклонениям от целевого значения, которые прогнозируются в будущем. Примечательно то, что дифференциальная компонента устраняет затухающие колебания. Дифференциальное регулирование особенно эффективно для процессов, которые имеют большие запаздывания. Недостатком дифференциального закона управления является его неустойчивость к воздействую шумов (Differentiation noise).
Таким образом, в зависимости от ситуации могут применятся П-, ПД-, ПИ- и ПИД-регуляторы, но основным законом управления в основном является пропорциональный (хотя в некоторых специфических задачах и могут использоваться исключительно только звенья дифференциаторов и интеграторов).
Казалось бы, вопрос реализации ПИД-регуляторов уже давно избит и здесь на Хабре есть парочка неплохих статей на эту тему в том числе и на Unity3D, также есть неплохая статья PID Without a PhD (перевод) и цикл статей в журнале «Современные технологии автоматизации» в двух частях: первая и вторая. Также к вашим услугам статья на Википедии (наиболее полную читайте в английском варианте). А на форумах коммьюнити Unity3D нет-нет, да и всплывет PID controller как и на gamedev.stackexchange
При вопрос по реализации ПИД-регуляторов несколько глубже чем и кажется. Настолько, что юных самоделкиных, решивших, реализовать такую схему регулирования ждет немало открытий чудных, а тема актуальная. Так что надеюсь сей опус, кому-нибудь да пригодиться, поэтому приступим.
Попытка номер раз
В качестве примера попытаемся реализовать схему регулирования на примере управления поворотом в простенькой космической 2D-аркаде, по шагам, начиная с самого начала (не забыли, что это туториал?).
Почему не 3D? Потому что реализация не измениться, за исключением того, что придется воротить ПИД-регулятор для контроля тангажа, рысканья и крена. Хотя вопрос корректного применения ПИД-регулирования вместе с кватернионами действительно интересный, возможно в будущем его и освящу, но даже в NASA предпочитают углы Эйлера вместо кватернионов, так что обойдемся простенькой моделью на двухмерной плоскости.
Для начала создадим сам объект игровой объект космического корабля, который будет состоять из собственно самого объекта корабля на верхнем уровне иерархии, прикрепим к нему дочерний объект Engine (чисто спецэффектов ради). Вот как это выглядит у меня:
А на сам объект космического корабля накидаем в инспекторе всяческих компонент. Забегая вперед, приведу скрин того, как он будет выглядеть в конце:
Но это потом, а пока в нем еще нет никаких скриптов, только стандартный джентльменский набор: Sprite Render, RigidBody2D, Polygon Collider, Audio Source (зачем?).
Собственно физика у нас сейчас самое главное и управление будет осуществляться исключительно через неё, в противном случае, применение ПИД-регулятора потеряло бы смысл. Масса нашего космического корабля оставим также в 1 кг, а все коэффициенты трения и гравитации равны нулю — в космосе же.
Т.к. помимо самого космического корабля есть куча других, менее умных космических объектов, то сначала опишем родительский класс BaseBody, который в себе будет содержать ссылки на на наши компоненты, методы инициализации и уничтожения, а также ряд дополнительных полей и методов, например для реализации небесной механики:
BaseBody.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Assets.Scripts.SpaceShooter.Bodies
{
[RequireComponent(typeof(SpriteRenderer))]
[RequireComponent(typeof(AudioSource))]
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Collider2D))]
public class BaseBody : MonoBehaviour
{
readonly float _deafultTimeDelay = 0.05f;
[HideInInspector]
public static List<BaseBody> _bodies = new List<BaseBody>();
#region RigidBody
[HideInInspector]
public Rigidbody2D _rb2d;
[HideInInspector]
public Collider2D[] _c2d;
#endregion
#region References
[HideInInspector]
public Transform _myTransform;
[HideInInspector]
public GameObject _myObject;
/// <summary>
/// Объект, который появляется при уничтожении
/// </summary>
public GameObject _explodePrefab;
#endregion
#region Audio
public AudioSource _audioSource;
/// <summary>
/// Звуки, которые проигрываются при получении повреждения
/// </summary>
public AudioClip[] _hitSounds;
/// <summary>
/// Звуки, которые проигрываются при появлении объекта
/// </summary>
public AudioClip[] _awakeSounds;
/// <summary>
/// Звуки, которые воспроизводятся перед смертью
/// </summary>
public AudioClip[] _deadSounds;
#endregion
#region External Force Variables
/// <summary>
/// Внешние силы воздйствующие на объект
/// </summary>
[HideInInspector]
public Vector2 _ExternalForces = new Vector2();
/// <summary>
/// Текущий вектор скорости
/// </summary>
[HideInInspector]
public Vector2 _V = new Vector2();
/// <summary>
/// Текущий вектор силы гравитации
/// </summary>
[HideInInspector]
public Vector2 _G = new Vector2();
#endregion
public virtual void Awake()
{
Init();
}
public virtual void Start()
{
}
public virtual void Init()
{
_myTransform = this.transform;
_myObject = gameObject;
_rb2d = GetComponent<Rigidbody2D>();
_c2d = GetComponentsInChildren<Collider2D>();
_audioSource = GetComponent<AudioSource>();
PlayRandomSound(_awakeSounds);
BaseBody bb = GetComponent<BaseBody>();
_bodies.Add(bb);
}
/// <summary>
/// Уничтожение персонажа
/// </summary>
public virtual void Destroy()
{
_bodies.Remove(this);
for (int i = 0; i < _c2d.Length; i++)
{
_c2d[i].enabled = false;
}
float _t = PlayRandomSound(_deadSounds);
StartCoroutine(WaitAndDestroy(_t));
}
/// <summary>
/// Ждем некоторое время перед уничтожением
/// </summary>
/// <param name="waitTime">Время ожидания</param>
/// <returns></returns>
public IEnumerator WaitAndDestroy(float waitTime)
{
yield return new WaitForSeconds(waitTime);
if (_explodePrefab)
{
Instantiate(_explodePrefab, transform.position, Quaternion.identity);
}
Destroy(gameObject, _deafultTimeDelay);
}
/// <summary>
/// Проигрывание случайного звука
/// </summary>
/// <param name="audioClip">Массив звуков</param>
/// <returns>Длительность проигрываемого звука</returns>
public float PlayRandomSound(AudioClip[] audioClip)
{
float _t = 0;
if (audioClip.Length > 0)
{
int _i = UnityEngine.Random.Range(0, audioClip.Length - 1);
AudioClip _audioClip = audioClip[_i];
_t = _audioClip.length;
_audioSource.PlayOneShot(_audioClip);
}
return _t;
}
/// <summary>
/// Получение урона
/// </summary>
/// <param name="damage">Уровень урона</param>
public virtual void Damage(float damage)
{
PlayRandomSound(_hitSounds);
}
}
}
Вроде описали все что надо, даже больше чем нужно (в рамках этой статьи). Теперь отнаследуем от него класс корабля Ship, который должен уметь двигаться и поворачивать:
SpaceShip.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Assets.Scripts.SpaceShooter.Bodies
{
public class Ship : BaseBody
{
public Vector2 _movement = new Vector2();
public Vector2 _target = new Vector2();
public float _rotation = 0f;
public void FixedUpdate()
{
float torque = ControlRotate(_rotation);
Vector2 force = ControlForce(_movement);
_rb2d.AddTorque(torque);
_rb2d.AddRelativeForce(force);
}
public float ControlRotate(Vector2 rotate)
{
float result = 0f;
return result;
}
public Vector2 ControlForce(Vector2 movement)
{
Vector2 result = new Vector2();
return result;
}
}
}
Пока в нем нет ничего интересно, на текущий момент это просто класс-заглушка.
Также опишем базовый(абстрактный) класс для всех контроллеров ввода BaseInputController:
BaseInputController.cs
using UnityEngine;
using Assets.Scripts.SpaceShooter.Bodies;
namespace Assets.Scripts.SpaceShooter.InputController
{
public enum eSpriteRotation
{
Rigth = 0,
Up = -90,
Left = -180,
Down = -270
}
public abstract class BaseInputController : MonoBehaviour
{
public GameObject _agentObject;
public Ship _agentBody; // Ссылка на компонент логики корабля
public eSpriteRotation _spriteOrientation = eSpriteRotation.Up; //Это связано с нестандартной
// ориентации спрайта "вверх" вместо "вправо"
public abstract void ControlRotate(float dt);
public abstract void ControlForce(float dt);
public virtual void Start()
{
_agentObject = gameObject;
_agentBody = gameObject.GetComponent<Ship>();
}
public virtual void FixedUpdate()
{
float dt = Time.fixedDeltaTime;
ControlRotate(dt);
ControlForce(dt);
}
public virtual void Update()
{
//TO DO
}
}
}
И наконец, класс контроллера игрока PlayerFigtherInput:
PlayerInput.cs
using UnityEngine;
using Assets.Scripts.SpaceShooter.Bodies;
namespace Assets.Scripts.SpaceShooter.InputController
{
public class PlayerFigtherInput : BaseInputController
{
public override void ControlRotate(float dt)
{
// Определяем позицию мыши относительно игрока
Vector3 worldPos = Input.mousePosition;
worldPos = Camera.main.ScreenToWorldPoint(worldPos);
// Сохраняем координаты указателя мыши
float dx = -this.transform.position.x + worldPos.x;
float dy = -this.transform.position.y + worldPos.y;
//Передаем направление
Vector2 target = new Vector2(dx, dy);
_agentBody._target = target;
//Вычисляем поворот в соответствии с нажатием клавиш
float targetAngle = Mathf.Atan2(dy, dx) * Mathf.Rad2Deg;
_agentBody._targetAngle = targetAngle + (float)_spriteOrientation;
}
public override void ControlForce(float dt)
{
//Передаем movement
_agentBody._movement = Input.GetAxis("Vertical") * Vector2.up
+ Input.GetAxis("Horizontal") * Vector2.right;
}
}
}
Вроде бы закончили, теперь наконец можно перейти к тому, ради чего все это затевалось, т.е. ПИД-регуляторам (не забыли надеюсь?). Его реализация кажется простой до безобразия:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Assets.Scripts.Regulator
{
[System.Serializable] // Этот атрибут необходим для того что бы поля регулятора
// отображались в инспекторе и сериализовывались
public class SimplePID
{
public float Kp, Ki, Kd;
private float lastError;
private float P, I, D;
public SimplePID()
{
Kp = 1f;
Ki = 0;
Kd = 0.2f;
}
public SimplePID(float pFactor, float iFactor, float dFactor)
{
this.Kp = pFactor;
this.Ki = iFactor;
this.Kd = dFactor;
}
public float Update(float error, float dt)
{
P = error;
I += error * dt;
D = (error - lastError) / dt;
lastError = error;
float CO = P * Kp + I * Ki + D * Kd;
return CO;
}
}
}
Значения коэффициентов по умолчанию возьмем с потолка: это будет тривиальный единичный коэффициент пропорционального закона управления Kp = 1, небольшое значение коэффициента для дифференциального закона управления Kd = 0.2, который должен устранить ожидаемые колебания и нулевое значение для Ki, которое выбрано потому, что в нашей программной модели нет никаких статичных ошибок (но вы всегда можете их внести, а потом героически побороться с помощью интегратора).
Теперь вернемся к нашему классу SpaceShip и попробуем заюзать наше творение в качестве регулятора поворота космического корабля в методе ControlRotate:
public float ControlRotate(Vector2 rotate)
{
float MV = 0f;
float dt = Time.fixedDeltaTime;
//Вычисляем ошибку
float angleError = Mathf.DeltaAngle(_myTransform.eulerAngles.z, targetAngle);
//Получаем корректирующее ускорение
MV = _angleController.Update(angleError, dt);
return MV;
}
ПИД-регулятор будет осуществлять точное угловое позиционировая космического корабля только за счет крутящего момента. Все честно, физика и САУ, почти как в реальной жизни.
И без этих ваших Quaternion.Lerp
if (!_rb2d.freezeRotation)
rb2d.freezeRotation = true;
float deltaAngle = Mathf.DeltaAngle(_myTransform.eulerAngles.z, targetAngle);
float T = dt * Mathf.Abs( _rotationSpeed / deltaAngle);
// Трансформируем угол в вектор
Quaternion rot = Quaternion.Lerp(
_myTransform.rotation,
Quaternion.Euler(new Vector3(0, 0, targetAngle)),
T);
// Изменяем поворот объекта
_myTransform.rotation = rot;
Получившейся исходный код Ship.cs под спойлером
using UnityEngine;
using Assets.Scripts.Regulator;
namespace Assets.Scripts.SpaceShooter.Bodies
{
public class Ship : BaseBody
{
public GameObject _flame;
public Vector2 _movement = new Vector2();
public Vector2 _target = new Vector2();
public float _targetAngle = 0f;
public float _angle = 0f;
[Header("PID")]
public SimplePID _angleController = new SimplePID();
public void FixedUpdate()
{
float torque = ControlRotate(_targetAngle);
Vector2 force = ControlForce(_movement);
_rb2d.AddTorque(torque);
_rb2d.AddRelativeForce(force);
}
public float ControlRotate(float rotate)
{
float MV = 0f;
float dt = Time.fixedDeltaTime;
_angle = _myTransform.eulerAngles.z;
//Вычисляем ошибку
float angleError = Mathf.DeltaAngle(_angle, rotate);
//Получаем корректирующее ускорение
MV = _angleController.Update(angleError, dt);
return MV;
}
public Vector2 ControlForce(Vector2 movement)
{
Vector2 MV = new Vector2();
//Кусок кода спецэффекта работающего двигателя ради
if (movement != Vector2.zero)
{
if (_flame != null)
{
_flame.SetActive(true);
}
}
else
{
if (_flame != null)
{
_flame.SetActive(false);
}
}
MV = movement;
return MV;
}
}
}
Все? Расходимся по домам?
WTF! Что происходит? Почему корабль поворачивается как-то странно? И почему он так резко отскакивает от других объектов? Неужели этот глупый ПИД-регулятор не работает?
Без паники! Давайте попробуем разобраться что происходит.
В момент получения нового значения SP, происходит резкий (ступенчатый) скачок рассогласования ошибки, которая, как мы помним, вычисляется вот так: соответственно происходит резкий скачок производной ошибки , которую мы вычисляем в этой строчке кода:
D = (error - lastError) / dt;
Можно, конечно, попробовать другие схемы дифференцирования, например, трехточечную, или пятиточечную, или… но все равно это не поможет. Ну вот не любят производные резких скачков — в таких точках функция не является дифференцируемой. Однако поэкспериментировать с разными схемами дифференцирования и интегрирования стоит, но потом и не в этой статье.
Думаю что настал момент построить графики переходного процесса: ступенчатое воздействие от S(t) = 0 в SP(t) = 90 градусов для тела массой в 1 кг, длинной плеча силы в 1 метр и шагом сетки дифференцирования 0.02 с — прям как в нашем примере на Unity3D (на самом деле не совсем, при построении этих графиков не учитывалось, что момент инерции зависит от геометрии твердого тела, поэтому переходный процесс будет немножко другой, но все же достаточно похожий для демонстрации). Все величены на грифике приведены в абсолютных значениях:
Хм, что здесь происходит? Куда улетел отклик ПИД-регулятора?
Поздравляю, мы только что столкнулись с таким явлением как «удар» (kick). Очевидно, что в момент времени, когда процесс еще PV = 0, а уставка уже SP = 90, то при численном дифференцировании получим значение производной порядка 4500, которое умножится на Kd=0.2 и сложится с пропорциональным теромом, так что на выходе мы получим значение углового ускорения 990, а это уже форменное надругательство над физической моделью Unity3D (угловые скорости будут достигать 18000 град/с… я думаю это предельное значение угловой скорости для RigidBody2D).
- Может стоит подобрать коэффициенты ручками, так чтобы скачок был не таким сильным?
- Нет! Самое лучше чего мы таким образом сможем добиться — небольшая амплитуда скачка производной, однако сам скачок как был так и останется, при этом можно докрутиться до полной неэффективности дифференциальной составляющей.
Впрочем можете поэкспериментировать.
Попытка номер два. Сатурация
Логично, что привод (в нашем случае виртуальные маневровые двигатели SpaceShip), не может отрабатывать сколько угодно большие значения которые может выдать наш безумный регулятор. Так что первое что мы сделаем — сатурируем выход регулятора:
public float ControlRotate(Vector2 rotate, float thrust)
{
float CO = 0f;
float MV = 0f;
float dt = Time.fixedDeltaTime;
//Вычисляем ошибку
float angleError = Mathf.DeltaAngle(_myTransform.eulerAngles.z, targetAngle);
//Получаем корректирующее ускорение
CO = _angleController.Update(angleError, dt);
//Сатурируем
MV = CO;
if (MV > thrust) MV = thrust;
if (MV< -thrust) MV = -thrust;
return MV;
}
А очередной раз переписанный класс Ship полностью выглядит так
namespace Assets.Scripts.SpaceShooter.Bodies
{
public class Ship : BaseBody
{
public GameObject _flame;
public Vector2 _movement = new Vector2();
public Vector2 _target = new Vector2();
public float _targetAngle = 0f;
public float _angle = 0f;
public float _thrust = 1f;
[Header("PID")]
public SimplePID _angleController = new SimplePID(0.1f,0f,0.05f);
public void FixedUpdate()
{
_torque = ControlRotate(_targetAngle, _thrust);
_force = ControlForce(_movement);
_rb2d.AddTorque(_torque);
_rb2d.AddRelativeForce(_force);
}
public float ControlRotate(float targetAngle, float thrust)
{
float CO = 0f;
float MV = 0f;
float dt = Time.fixedDeltaTime;
//Вычисляем ошибку
float angleError = Mathf.DeltaAngle(_myTransform.eulerAngles.z, targetAngle);
//Получаем корректирующее ускорение
CO = _angleController.Update(angleError, dt);
//Сатурируем
MV = CO;
if (MV > thrust) MV = thrust;
if (MV< -thrust) MV = -thrust;
return MV;
}
public Vector2 ControlForce(Vector2 movement)
{
Vector2 MV = new Vector2();
if (movement != Vector2.zero)
{
if (_flame != null)
{
_flame.SetActive(true);
}
}
else
{
if (_flame != null)
{
_flame.SetActive(false);
}
}
MV = movement * _thrust;
return MV;
}
public void Update()
{
}
}
}
Итоговая схема нашего САУ тогда станет уже вот такой
При этом уже становится понятно, что выход контроллера CO(t) немного не одно и тоже, что управляемая величина процесса MV(t).
Собственно с этого места можно уже добавлять новую игровую сущность — привод, через которую и будет осуществляться управление процессом, логика работы которой может быть более сложной, чем просто Mathf.Clamp(), например, можно ввести дискретизацию значений (дабы не перегружать игровую физику величинами идущими шестыми после запятой), мертвую зону (опять таки не имеет смысл перегружать физику сверхмалыми реакциями), ввести задержку в упраление и нелинейность (например, сигмоиду) привода, после чего посмотреть, что из этого получится.
Запустив игру, мы обнаружим, что космический корабль стал наконец управляемым:
Если построить графики, то можно увидеть, что реакция контроллера стала уже вот такой:
Здесь уже используются нормированные величены, углы поделены на значение SP, а выход контроллера отнормирован относительно максимального значения на котором уже происходит сатурация.
Теперь на графике видно наличие ошибки перерегулирования (overshooting) и затухающие колебания. Уменьшая Kp и увеличивая Kd можно добиться уменьшения колебаний, но зато увеличится время реакции контроллера (скорость поворота корабля). И наоборот, увеличивая Kp и уменьшая Kd — можно добиться увеличения скорости реакции контроллера, но появятся паразитные колебания, которые при определенных (критических) значениях, перестанут быть затухающими.
Ниже приведена известна таблица влияния увеличения параметров ПИД-регулятора (как уменьшить шрифт, а то таблица безе переносов не лезет?):
А общий алгоритм ручной настройки ПИД-регулятора следующий:
- Подбираем пропорциональный коэффициенты при отключенных дифференциальных и интегральных звеньях до тех пор пока не начнутся автоколебания.
- Постепенно увеличивая дифференциальную составляющую избавляемся от автоколебаний
- Если наблюдается остаточная ошибка регулирования (смещение), то устраняем её за счет интегральной составляющей.
Каких-то общих значений параметров ПИД-регулятора нет: конкретные значения зависят исключительно от параметров процесса (его передаточной характеристики): ПИД-регулятор отлично работающий с одним объектом управления окажется неработоспособным с другим. Более того, коэффициенты при пропорциональной, интегральной и дифференциальной составляющих еще и взаимозависимы.
В общем не будем о грустном, дальше нас ждет самое интересное…
Попытка номер три. Еще раз производные
Приделав костыль в виде ограничения значений выхода контроллера мы так и не решили самую главную проблему нашего регулятора — дифференциальная составляющая плохо себя чувствует при ступенчатом изменении ошибки на входе регуляторе. На самом деле есть множество других костылей, например, в момент скачкообразного изменения SP «отключать» дифференциальную составляющую или же поставить фильтры нижних частот между SP(t) и операцией за счет которого будет происходить плавное нарастание ошибки, а можно совсем развернуться и впендюрить самый настоящий фильтр Калмана для сглаживания входных данных. В общем костылей много, и добавить наблюдателя конечно хотелось бы, но не в этот раз.
Поэтому снова вернемся к производной ошибки рассогласования и внимательно на неё посмотрим:
Ничего не заметили? Если хорошенько присмотреться, то можно обнаружить, что вообще-то SP(t), не меняется во времени (за исключением моментов ступенчатого изменения, когда регулятор получает новую команду), т.е. её производная равна нулю:
тогда
Иными словами, вместо производной ошибки, которая дифференцируема не везде мы можем использовать производную от процесса, который в мире классической механики как правило непрерывен и дифференцируем везде, а схема нашей САУ уже приобретет следующий вид:
Модифицируем код регулятора:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Assets.Scripts.Regulator
{
[System.Serializable]
public class SimplePID
{
public float Kp, Ki, Kd;
private float P, I, D;
private float lastPV = 0f;
public SimplePID()
{
Kp = 1f;
Ki = 0f;
Kd = 0.2f;
}
public SimplePID(float pFactor, float iFactor, float dFactor)
{
this.Kp = pFactor;
this.Ki = iFactor;
this.Kd = dFactor;
}
public float Update(float error, float PV, float dt)
{
P = error;
I += error * dt;
D = -(PV - lastPV) / dt;
lastPV = PV;
float CO = Kp * P + Ki * I + Kd * D;
return CO;
}
}
}
И немного изменим метод ControlRotate:
public float ControlRotate(Vector2 rotate, float thrust)
{
float CO = 0f;
float MV = 0f;
float dt = Time.fixedDeltaTime;
//Вычисляем ошибку
float angleError = Mathf.DeltaAngle(_myTransform.eulerAngles.z, targetAngle);
//Получаем корректирующее ускорение
CO = _angleController.Update(angleError, _myTransform.eulerAngles.z, dt);
//Сатурируем
MV = CO;
if (CO > thrust) MV = thrust;
if (CO < -thrust) MV = -thrust;
return MV;
}
И-и-и-и… если запустить игру, то обнаружиться, что на самом деле ничего ничего не изменилось с последней попытки, что и требовалось доказать. Однако, если убрать сатурацию, то график реакции регулятора будет выглядеть вот так:
Скачок CO(t) по прежнему присутствует, однако он уже не такой большой как был в самом начале, а самое главное — он стал предсказуемым, т.к. обеспечивается исключительно пропорциональной составляющей, и ограничен максимально возможной ошибкой рассогласования и пропорциональным коэффициентом ПИД-регулятора (а это уже намекает на то, что Kp имеет смысл выбрать все же меньше единицы, например, 1/90f), но не зависит от шага сетки дифференцирования (т.е. dt). В общем, я настоятельно рекомендую использовать именно производную процесса, а не ошибки.
Думаю теперь никого не удивит, но таким же макаром можно заменить на , однако останавливаться на этом мы не будем, можете сами поэкспериментировать и рассказать в комментариях, что из этого получилось (самому интересно)
Попытка номер четыре. Альтернативные реализации ПИД-регулятор
Помимо описанного выше идеального представления ПИД-регулятора, на практике часто применяется стандартная форма, без коэффициентов Ki и Kd, вместо которых используются временные постоянные.
Такой подход связан с тем, что ряд методик настройки ПИД-регулятора основан на частотных характеристиках ПИД-регулятора и процесса. Собственно вся ТАУ и крутится вокруг частотных характеристик процессов, поэтому для желающих углубиться, и, внезапно, столкнувшихся с альтернативной номенклатурой, приведу пример т.н. стандартной формы ПИД-регулятора:
где, — постоянная дифференцирования, влияющая на прогнозирование состояния системы регулятором,
— постоянная интегрирования, влияющая на интервал усреднения ошибки интегральным звеном.
Основные принципы настройки ПИД-регулятора в стандартной форме аналогичны идеализированному ПИД-регулятору:
- увеличение пропорционального коэффициента увеличивает быстродействие и снижает запас устойчивости;
- с уменьшением интегральной составляющей ошибка регулирования с течением времени уменьшается быстрее;
- уменьшение постоянной интегрирования уменьшает запас устойчивости;
- увеличение дифференциальной составляющей увеличивает запас устойчивости и быстродействие
Исходный код стандартной формы, вы можете найти под спойлером
namespace Assets.Scripts.Regulator
{
[System.Serializable]
public class StandartPID
{
public float Kp, Ti, Td;
public float error, CO;
public float P, I, D;
private float lastPV = 0f;
public StandartPID()
{
Kp = 0.1f;
Ti = 10000f;
Td = 0.5f;
bias = 0f;
}
public StandartPID(float Kp, float Ti, float Td)
{
this.Kp = Kp;
this.Ti = Ti;
this.Td = Td;
}
public float Update(float error, float PV, float dt)
{
this.error = error;
P = error;
I += (1 / Ti) * error * dt;
D = -Td * (PV - lastPV) / dt;
CO = Kp * (P + I + D);
lastPV = PV;
return CO;
}
}
}
В качестве значений по умолчанию, выбраны Kp = 0.01, Ti = 10000, Td = 0.5 — при таких значениях корабль поворачивается достаточно быстро и обладает некоторым запасом устойчивости.
Помимо такой формы ПИД-регулятора, часто используется т.н. реккурентная форма:
Не будем на ней останавливаться, т.к. она актуальна прежде всего для хардверных программистов, работающих с FPGA и микроконтроллерами, где такая реализация значительно удобнее и эффективнее. В нашем же случае — давайте что-нибудь сваям на Unity3D — это просто еще одна реализация ПИД-контроллера, которая ни чем не лучше других и даже менее понятная, так что еще раз дружно порадуемся как хорошо программировать в уютненьком C#, а не в жутком и страшном VHDL, например.
Вместо заключения. Куда бы еще присобачить ПИД-регулятор
Теперь попробуем немного усложнить управление корабля используя двухконтурное управление: один ПИД-регулятор, уже знакомый нам _angleController, отвечает по прежнему за угловое позиционирование, а вот второй — новый, _angularVelocityController — контролирует скорость поворота:
public float ControlRotate(float targetAngle, float thrust)
{
float CO = 0f;
float MV = 0f;
float dt = Time.fixedDeltaTime;
_angle = _myTransform.eulerAngles.z;
//Контроллер угла поворота
float angleError = Mathf.DeltaAngle(_angle, targetAngle);
float torqueCorrectionForAngle =
_angleController.Update(angleError, _angle, dt);
//Контроллер стабилизации скорости
float angularVelocityError = -_rb2d.angularVelocity;
float torqueCorrectionForAngularVelocity =
_angularVelocityController.Update(angularVelocityError, -angularVelocityError, dt);
//Суммарный выход контроллера
CO = torqueCorrectionForAngle + torqueCorrectionForAngularVelocity;
//Дискретизируем с шагом 100
CO = Mathf.Round(100f * CO) / 100f;
//Сатурируем
MV = CO;
if (CO > thrust) MV = thrust;
if (CO < -thrust) MV = -thrust;
return MV;
}
Назначение второго регулятора — гашение избыточных угловых скоростей, за счет изменения крутящего момента — это сродни наличию углового трения, которое мы отключили еще при создании игрового объекта. Такая схема управления [возможно] позволит получить более стабильное поведение корабля, и даже обойтись только пропорциональными коэффициентами управления — второй регулятор будет гасить все колебания, выполняя функцию, аналогичную дифференциальной составляющей первого регулятора.
Помимо этого, добавим новый класс ввода игрока — PlayerInputCorvette, в котором повороты буду осуществляться уже за счет нажатия клавиш «вправо-влево», а целеуказание с помощью мыши мы оставим для чего-нибудь более полезного, например, для управления турелью. Заодно у нас теперь появился такой параметр как _turnRate — отвечающий за скорость/отзывчивость поворота (не понятно только куда его поместить лучше в InputCOntroller или все же Ship).
public class PlayerCorvetteInput : BaseInputController
{
public float _turnSpeed = 90f;
public override void ControlRotate()
{
// Находим указатель мыши
Vector3 worldPos = Input.mousePosition;
worldPos = Camera.main.ScreenToWorldPoint(worldPos);
// Сохраняем относительные координаты указателя мыши
float dx = -this.transform.position.x + worldPos.x;
float dy = -this.transform.position.y + worldPos.y;
//Передаем направление указателя мыши
Vector2 target = new Vector2(dx, dy);
_agentBody._target = target;
//Вычисляем поворот в соответствии с нажатием клавиш
_agentBody._rotation -= Input.GetAxis("Horizontal") * _turnSpeed * Time.deltaTime;
}
public override void ControlForce()
{
//Передаем movement
_agentBody._movement = Input.GetAxis("Vertical") * Vector2.up;
}
}
Также для наглядности накидаем на коленках скрипт для отображения отладочной информации
namespace Assets.Scripts.SpaceShooter.UI
{
[RequireComponent(typeof(Ship))]
[RequireComponent(typeof(BaseInputController))]
public class Debugger : MonoBehaviour
{
Ship _ship;
BaseInputController _controller;
List<SimplePID> _pids = new List<SimplePID>();
List<string> _names = new List<string>();
Vector2 _orientation = new Vector2();
// Use this for initialization
void Start()
{
_ship = GetComponent<Ship>();
_controller = GetComponent<BaseInputController>();
_pids.Add(_ship._angleController);
_names.Add("Angle controller");
_pids.Add(_ship._angularVelocityController);
_names.Add("Angular velocity controller");
}
// Update is called once per frame
void Update()
{
DrawDebug();
}
Vector3 GetDiretion(eSpriteRotation spriteRotation)
{
switch (_controller._spriteOrientation)
{
case eSpriteRotation.Rigth:
return transform.right;
case eSpriteRotation.Up:
return transform.up;
case eSpriteRotation.Left:
return -transform.right;
case eSpriteRotation.Down:
return -transform.up;
}
return Vector3.zero;
}
void DrawDebug()
{
//Направление поворота
Vector3 vectorToTarget = transform.position
+ 5f * new Vector3(-Mathf.Sin(_ship._targetAngle * Mathf.Deg2Rad),
Mathf.Cos(_ship._targetAngle * Mathf.Deg2Rad), 0f);
// Текущее направление
Vector3 heading = transform.position + 4f * GetDiretion(_controller._spriteOrientation);
//Угловое ускорение
Vector3 torque = heading - transform.right * _ship._Torque;
Debug.DrawLine(transform.position, vectorToTarget, Color.white);
Debug.DrawLine(transform.position, heading, Color.green);
Debug.DrawLine(heading, torque, Color.red);
}
void OnGUI()
{
float x0 = 10;
float y0 = 100;
float dx = 200;
float dy = 40;
float SliderKpMax = 1;
float SliderKpMin = 0;
float SliderKiMax = .5f;
float SliderKiMin = -.5f;
float SliderKdMax = .5f;
float SliderKdMin = 0;
int i = 0;
foreach (SimplePID pid in _pids)
{
y0 += 2 * dy;
GUI.Box(new Rect(25 + x0, 5 + y0, dx, dy), "");
pid.Kp = GUI.HorizontalSlider(new Rect(25 + x0, 5 + y0, 200, 10),
pid.Kp,
SliderKpMin,
SliderKpMax);
pid.Ki = GUI.HorizontalSlider(new Rect(25 + x0, 20 + y0, 200, 10),
pid.Ki,
SliderKiMin,
SliderKiMax);
pid.Kd = GUI.HorizontalSlider(new Rect(25 + x0, 35 + y0, 200, 10),
pid.Kd,
SliderKdMin,
SliderKdMax);
GUIStyle style1 = new GUIStyle();
style1.alignment = TextAnchor.MiddleRight;
style1.fontStyle = FontStyle.Bold;
style1.normal.textColor = Color.yellow;
style1.fontSize = 9;
GUI.Label(new Rect(0 + x0, 5 + y0, 20, 10), "Kp", style1);
GUI.Label(new Rect(0 + x0, 20 + y0, 20, 10), "Ki", style1);
GUI.Label(new Rect(0 + x0, 35 + y0, 20, 10), "Kd", style1);
GUIStyle style2 = new GUIStyle();
style2.alignment = TextAnchor.MiddleLeft;
style2.fontStyle = FontStyle.Bold;
style2.normal.textColor = Color.yellow;
style2.fontSize = 9;
GUI.TextField(new Rect(235 + x0, 5 + y0, 60, 10), pid.Kp.ToString(), style2);
GUI.TextField(new Rect(235 + x0, 20 + y0, 60, 10), pid.Ki.ToString(), style2);
GUI.TextField(new Rect(235 + x0, 35 + y0, 60, 10), pid.Kd.ToString(), style2);
GUI.Label(new Rect(0 + x0, -8 + y0, 200, 10), _names[i++], style2);
}
}
}
}
Класс Ship также претерпел необратимые мутации и теперь должен выглядеть вот так:
namespace Assets.Scripts.SpaceShooter.Bodies
{
public class Ship : BaseBody
{
public GameObject _flame;
public Vector2 _movement = new Vector2();
public Vector2 _target = new Vector2();
public float _targetAngle = 0f;
public float _angle = 0f;
public float _thrust = 1f;
[Header("PID")]
public SimplePID _angleController = new SimplePID(0.1f,0f,0.05f);
public SimplePID _angularVelocityController = new SimplePID(0f,0f,0f);
private float _torque = 0f;
public float _Torque
{
get
{
return _torque;
}
}
private Vector2 _force = new Vector2();
public Vector2 _Force
{
get
{
return _force;
}
}
public void FixedUpdate()
{
_torque = ControlRotate(_targetAngle, _thrust);
_force = ControlForce(_movement, _thrust);
_rb2d.AddTorque(_torque);
_rb2d.AddRelativeForce(_force);
}
public float ControlRotate(float targetAngle, float thrust)
{
float CO = 0f;
float MV = 0f;
float dt = Time.fixedDeltaTime;
_angle = _myTransform.eulerAngles.z;
//Контроллер угла поворота
float angleError = Mathf.DeltaAngle(_angle, targetAngle);
float torqueCorrectionForAngle =
_angleController.Update(angleError, _angle, dt);
//Контроллер стабилизации скорости
float angularVelocityError = -_rb2d.angularVelocity;
float torqueCorrectionForAngularVelocity =
_angularVelocityController.Update(angularVelocityError, -angularVelocityError, dt);
//Суммарный выход контроллера
CO = torqueCorrectionForAngle + torqueCorrectionForAngularVelocity;
//Дискретизируем с шагом 100
CO = Mathf.Round(100f * CO) / 100f;
//Сатурируем
MV = CO;
if (CO > thrust) MV = thrust;
if (CO < -thrust) MV = -thrust;
return MV;
}
public Vector2 ControlForce(Vector2 movement, float thrust)
{
Vector2 MV = new Vector2();
if (movement != Vector2.zero)
{
if (_flame != null)
{
_flame.SetActive(true);
}
}
else
{
if (_flame != null)
{
_flame.SetActive(false);
}
}
MV = movement * thrust;
return MV;
}
public void Update()
{
}
}
}
А вот, собственно заключительное видео того, что должно получиться:
К сожалению получилось охватить не все, что хотелось бы, в частности почти не затронут вопрос настройки ПИД-регулятора и практически не освящена интегральная составляющая — фактически приведен пример только для ПД-регулятора. Собственно изначально планировалось несколько больше примеров (круиз-контроль, вращение турели и компенсация вращательного момента), но статья итак уже разбухла, да и вообще:
Немного ссылок
- Годная статья на английской вики
- PID tutorial
- ПИД-регуляторы: вопросы реализации. Часть 1
- ПИД-регуляторы: вопросы реализации. Часть 2
- PID Without a PhD
- PID Without a PhD. Перевод
- Derivative Action and PID Control
- Control System Lab: PID
- ПИД-регулятор своими руками
- Корректная реализация разностной схемы ПИД регулятора
- Программируем квадрокоптер на Arduino (часть 1)
- Виртуальный квадрокоптер на Unity + OpenCV (Часть 1)
- Поляков К.Ю. Теория автоматического управления для чайников
- PID control system analysis, design, and technology
- Aidan O’Dwyer. Handbook of PI and PID Controller Tuning Rules (3rd ed.)
- PID process control, a “Cruise Control” example
- https://www.mathworks.com/discovery/pid-control.html
- http://scilab.ninja/study-modules/scilab-control-engineering-basics/module-4-pid-control/
- https://sourceforge.net/p/octave/control/ci/default/tree/inst/optiPID.m
Еще немного ссылок на другие примеры
http://luminaryapps.com/blog/use-a-pid-loop-to-control-unity-game-objects/
http://www.habrador.com/tutorials/pid-controller/3-stabilize-quadcopter/
https://www.gamedev.net/articles/programming/math-and-physics/pid-control-of-physics-bodies-r3885/
https://ksp-kos.github.io/KOS/tutorials/pidloops.html