Ошибка регулирования тау это

Действительные
значения регулируемой величины в
реальных САР отличаются от предписанных.
Разность между предписанным и
действительным значениями регулируемой
величины называется ошибкой
регулирования
.

∆xз(t)
= xз
– x(t)
– ошибка регулирования

хз
– предписанное (заданное) значение
управляемой величины;

x(t)
– ее текущее значение

В
процессе функционирования САР может
переходить от одного состояния,
принимаемого за исходное, в другое.
Разность между текущими значениями
регулируемой величины и значением,
соответствующим исходному состоянию,
принято называть отклонением регулируемой
величины

∆x0(t)
= x(t)
– x0(t) (1.3)

где
xo
– значение регулируемой величины в
исходном состоянии.

x0(t)
– исходное значение регулируемой
величины.

Рис.
1.3. Изменение значения регулируемой
величины в процессе регулирования

1.4. Статическое и астатическое регулирование

В
зависимости от того, является или нет
ошибка регулирования функцией возмущающего
воздействия в установившемся режиме,
различают статическое
и астатическое
регулирование.

При
статическом регулировании ошибка
регулирования возрастает с увеличением
значения возмущающего воздействия.
Пример статического регулирования
приведен на рис. 1.4, а).

а)

б)

в)

Рис.
1.4. Пример статического регулятора и
его характеристика (1 – генератор; 2 –
электронный усилитель, 3 – регулировочный
реостат, Uг
– напряжение генератора (регулируемый
параметр);Uзад
– задающее воздействие, которое равно
заданному (предписанному) значению
напряжения генератора; Pг
– активная мощность генератора
(возмущающее воздействие); UИП
– напряжение источника питания; UОВ
– напряжения обмотки возбуждения; ΔU
– входное напряжения электронного
усилителя)

Принцип
действия этого регулятора достаточно
ясно виден из рассмотрения схемы и
особых пояснений не требует. Заметим
лишь, что требуемого возбуждение
генератора 1 осуществляется путем
изменения входного сигнала (ΔU)
электронного усилителя 2. В свою очередь
этот сигнал пропорционален отклонению
регулируемого параметра Uг
от заданного значения Uзад
(ΔU=Uг–Uзад).
Поэтому такое отклонение, т.е. наличие
ΔU,
является неизбежным и должно быть тем
больше, чем больше изменяется величина
внешнего возмущения Pг.
Очевидно, что это отклонение регулируемого
параметра от заданного значения
сохраняется также и в установившемся
режиме.

Рабочая
характеристика (зависимость напряжения
генератора от нагрузки – активной
мощности Pг)
статического регулятора приведена на
рис. 1.4, б).

На
рис. 1.4, в)
показан переходный процесс в системе
при уменьшении нагрузки генератора.

Регулированием
с астатической
характеристикой

называется такое регулирование, при
котором в установившемся состоянии
системы отклонение регулируемого
параметра от заданного значения равно
нулю при любой величине внешнего
возмущения. Равновесие системы имеет
место всегда при заданном значении
регулируемого параметра.

Пример
астатического регулирования приведен
на рис. 1.5, а).

а)

б)

в)

Рис.
1.5. Пример астатического регулятора
и его характеристика (1 – генератор;
2 – электронный усилитель; 3 – якорь
двигателя постоянного тока; 4, 5 –
регулировочные реостаты, Uг
– напряжение генератора (регулируемый
параметр); Uзад
– задающее воздействие, которое равно
заданному (предписанному) значению
напряжения генератора; Pг
– активная мощность генератора
(возмущающее воздействие); UИП1,
UИП2
– напряжения источников питания №1
и №2; UОВ1
и UОВ3
– напряжения обмоток возбуждений
генератора и двигателя; ΔU
– входное напряжения электронного
усилителя; Uвых
–напряжение на выходе электронного
усилителя)

Характеристика
астатического регулятора приведена на
рис. 1.5, б),
а кривая переходного процесса – на рис.
1.5, в).

При
увеличении нагрузки на генераторе, т.е.
увеличении активной мощности генератора
Pг,
уменьшается напряжение на его выводах
Uг,
что приводит к появлению отклонения
регулируемого параметра Uг
от заданного значения Uзад
(ΔU=Uг–Uзад).
Параметр Uзад
задается
регулировочным реостатом 5. При этом
появляется напряжение на якоре двигателя
постоянного тока Uвых,
и двигатель начинает перемещать контакт
регулировочного реостата 4 по часовой
стрелке, что приводит к увеличению тока
возбуждения генератора IОВ1,
а значит, и напряжения на его выводах
Uг.
Параметр Uг
будет увеличиваться до тех пор, пока
ошибка регулирования ΔU
не станет равной 0.

Астатические
САР обеспечивают высокую точность
регулирования. Однако по сравнению со
статическими они являются более сложными
и инерционными, т.е. процессы регулирования
в них являются замедленными.

1.5.
Линейные и нелинейные системы. Линеаризация
уравнений

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

Рис.
1.6. Принцип суперпозиции

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

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

Пусть
имеем некоторую непрерывную функцию
F(x)
(рис. 1.7).

Если
аргумент X
получил приращение ΔX
от исходного значения Xo,
то функция получит приращение ΔF(X).
Новое значение функции F(X)
можно разложить в ряд Тейлора:

Рис.
1.7. Пример линеаризации нелинейной
функции

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

,

где
.

Теоретически
это означает, что на интервале ±Δx
(рис. 1.6) кривая F(x)
заменяется прямой линией, являющейся
касательной при x=xo.

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

Пример
линеаризации нелинейного элемента
системы.

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

а)

б)

Рис.
1.8. Линеаризация нелинейного элемента
системы

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

Тогда
дифференциальное уравнение элемента
в случае, если потокосцепление
катушки
элементазависит от тока линейно, т.е.
если индуктивность L=/i
не зависит от тока и является величиной
постоянной, имеет вид:

Обозначив

и
,
учитывая, что
,
и пользуясь операторной (символической)
формой записи, в которой принято
,
получим:

(1.3)

Предположим
теперь, что в рассматриваемом примере
индуктивность зависит от тока и,
следовательно, элемент является
нелинейным. Тогда уравнение (1.3) для
такого элемента неправомерно, ибо
потокосцепление
зависит от тока нелинейно и, следовательно,
L=/i
есть величина переменная. Для
усатновившегося режима элемента при
входном постоянном напряжении uвх
потокосцепление 0
тоже постоянно во времени и, следовательно,
.
Тогда можно написать:

.

Изменение
входного напряжения повлечет за собой
изменение тока и выходного напряжения.

Текущие
значения uвх
и uвых
и i
можно представить так:

;

;

,

где
Δuвх,
Δuвых
и Δi
– отклонения
соответствующих величин от их
установившихся значений.

Пусть
потокосцепление является нелинейной
функцией тока, как это показано на рис.
1.8, б).
Эту функцию можно разложить в ряд:

(1.4)

При
достаточно малых отклонения тока можно
ограничиться первыми двумя членами
ряда. Величина

определяется тангенсом угла наклона
касательной к кривой, приведенной на
рис. 1.8,б), в
точке с абсциссой i0.

Обозначив
динамическую индуктивность элемента
для тока i0
через Lд,
т. е.
,
можем написать:

.

Так
как
,
то будем иметь:

.

Исходное
уравнение запишется теперь так:

,

или,
подставляя ранее найденное выражение
для uвых0,
получим:

.

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

(1.5)

где

и k=1.

Оно
справедливо только для малых отклонений
входной и выходной величины относительно
начального значения uвх0.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Вместо введения

Системы автоматического управления (САУ) предназначены для автоматического изменения одного или нескольких параметров объекта управления с целью установления требуемого режима его работы. САУ обеспечивает поддержание постоянства заданных значений регулируемых параметров или их изменение по заданному закону либо оптимизирует определенные критерии качества управления. Например, к таким системам относятся:

  • системы стабилизации,
  • системы программного управления,
  • следящие системы

Это достаточно широкий класс систем, которые можно найти где угодно. Но какое это отношение имеет к Unity3D и вероятно к играм в частности? В принципе прямое: в любой игре так или иначе использующей симуляцию как элемент геймплея реализуются САУ, к таким играм относятся, например, Kerbal Space Programm, Digital Combat Simulator (бывший Lock On), Strike Suit Zero и т.д. (кто знает еще примеры — пишите в комментариях). В принципе любая игра, моделирующая реальные физические процессы, в том числе и просто кинематику с динамикой движения, может реализовывать те или иные САУ — этот подход проще, естественнее, а у разработчика уже есть есть набор готовых инструментов, предоставленных всякими Вышнеградскими, Ляпуновыми, Калманами, Чебышевами и прочими Коломогоровами, поэтому можно обойтись без изобретения велосипеда, т.к. его уже изобрели, да так, что получилась отдельная наука: Теория автоматического управления. Главное тут не переусердствовать. Одна тут только проблема: рассказывают про ТАУ не везде, не всем, зачастую мало и не очень понятно.

Немножко теории

Классическая система автоматического управления представленная на следующем рисунке:

image

Ключевым элементом любой САУ является регулятор представляющий из себя устройство, которое следит за состоянием объекта управления и обеспечивает требуемый закон управления. Процесс управления включает в себя: вычисление ошибки управления или сигнала рассогласования e(t) как разницы между желаемой уставкой (set point или SP) и текущей величиной процесса (process value или PV), после чего регулятор вырабатывает управляющие сигналы (manipulated value или MV).

Одной из разновидностью регуляторов является пропорционально-интегрально-дифференцирующий (ПИД) регулятор, который формирует управляющий сигнал, являющийся суммой трёх слагаемых: пропорционального, интегрального и дифференциального.

image

Где, $e(t)$ ошибка рассогласования, а также, $ P = K_p cdot e(t)$ — пропорциональная, $ I = K_i cdot int_0^t e(tau)dtau$ — интегральная, $D = K_d cdot frac{de(t)}{dt}$ — дифференциальная составляющие (термы) закона управления, который в итоговом виде описывается следующими формулами

$ e(t) = SP(t) - PV(t), $

$ MV(t) = underbrace{K_p cdot e(t)}_{P} + underbrace{K_i cdot int_0^t e(tau)dtau}_{I} + underbrace{K_d cdot frac{de(t)}{dt}}_{D}, $

Пропорциональная составляющая P — отвечает за т.н. пропорциональное управление, смысл которого в том, что выходной сигнал регулятора, противодействует отклонению регулируемой величины (ошибки рассогласования или еще это называют невязкой) от заданного значения. Чем больше ошибка рассогласования, тем больше командное отклонение регулятора. Это самый простой и очевидный закон управления. Недостаток пропорционального закона управления заключается в том, что регулятор никогда не стабилизируется в заданном значении, а увеличение коэффициента пропорциональности всегда приводит к автоколебаниям. Именно поэтому в довесок к пропорциональному закону управления приходиться использовать интегральный и дифференциальный.

Интегральная составляющая I накапливает (интегрирует) ошибку регулирования, что позволяет ПИД-регулятору устранять статическую ошибку (установившуюся ошибку, остаточное рассогласование). Или другими словами: интегральное звено всегда вносит некоторое смещение и если система подвержена некоторыми постоянным ошибкам, то оно их компенсирует (за счет своего смещения). А вот если же этих ошибок нет или они пренебрежительно малы, то эффект будет обратным — интегральная составляющая сама будет вносить ошибку смещения. Именно по этой причине её не используют, например, в задачах сверхточного позиционирования. Ключевым недостатком интегрального закона управления является эффект насыщения интегратора (Integrator windup).

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

Таким образом, в зависимости от ситуации могут применятся П-, ПД-, ПИ- и ПИД-регуляторы, но основным законом управления в основном является пропорциональный (хотя в некоторых специфических задачах и могут использоваться исключительно только звенья дифференциаторов и интеграторов).

Казалось бы, вопрос реализации ПИД-регуляторов уже давно избит и здесь на Хабре есть парочка неплохих статей на эту тему в том числе и на Unity3D, также есть неплохая статья PID Without a PhD (перевод) и цикл статей в журнале «Современные технологии автоматизации» в двух частях: первая и вторая. Также к вашим услугам статья на Википедии (наиболее полную читайте в английском варианте). А на форумах коммьюнити Unity3D нет-нет, да и всплывет PID controller как и на gamedev.stackexchange

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

Попытка номер раз

В качестве примера попытаемся реализовать схему регулирования на примере управления поворотом в простенькой космической 2D-аркаде, по шагам, начиная с самого начала (не забыли, что это туториал?).

Почему не 3D? Потому что реализация не измениться, за исключением того, что придется воротить ПИД-регулятор для контроля тангажа, рысканья и крена. Хотя вопрос корректного применения ПИД-регулирования вместе с кватернионами действительно интересный, возможно в будущем его и освящу, но даже в NASA предпочитают углы Эйлера вместо кватернионов, так что обойдемся простенькой моделью на двухмерной плоскости.

Для начала создадим сам объект игровой объект космического корабля, который будет состоять из собственно самого объекта корабля на верхнем уровне иерархии, прикрепим к нему дочерний объект Engine (чисто спецэффектов ради). Вот как это выглядит у меня:

image

А на сам объект космического корабля накидаем в инспекторе всяческих компонент. Забегая вперед, приведу скрин того, как он будет выглядеть в конце:

image
Но это потом, а пока в нем еще нет никаких скриптов, только стандартный джентльменский набор: 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, происходит резкий (ступенчатый) скачок рассогласования ошибки, которая, как мы помним, вычисляется вот так: $e(t) = SP(t) - PV(t), $ соответственно происходит резкий скачок производной ошибки $frac{de(t)}{dt}$, которую мы вычисляем в этой строчке кода:

D = (error - lastError) / dt;

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

Думаю что настал момент построить графики переходного процесса: ступенчатое воздействие от S(t) = 0 в SP(t) = 90 градусов для тела массой в 1 кг, длинной плеча силы в 1 метр и шагом сетки дифференцирования 0.02 с — прям как в нашем примере на Unity3D (на самом деле не совсем, при построении этих графиков не учитывалось, что момент инерции зависит от геометрии твердого тела, поэтому переходный процесс будет немножко другой, но все же достаточно похожий для демонстрации). Все величены на грифике приведены в абсолютных значениях:
image
Хм, что здесь происходит? Куда улетел отклик ПИД-регулятора?

Поздравляю, мы только что столкнулись с таким явлением как «удар» (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()
        {

        }        
    }
}

Итоговая схема нашего САУ тогда станет уже вот такой
image

При этом уже становится понятно, что выход контроллера CO(t) немного не одно и тоже, что управляемая величина процесса MV(t).

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

Запустив игру, мы обнаружим, что космический корабль стал наконец управляемым:

Если построить графики, то можно увидеть, что реакция контроллера стала уже вот такой:
image
Здесь уже используются нормированные величены, углы поделены на значение SP, а выход контроллера отнормирован относительно максимального значения на котором уже происходит сатурация.

Теперь на графике видно наличие ошибки перерегулирования (overshooting) и затухающие колебания. Уменьшая Kp и увеличивая Kd можно добиться уменьшения колебаний, но зато увеличится время реакции контроллера (скорость поворота корабля). И наоборот, увеличивая Kp и уменьшая Kd — можно добиться увеличения скорости реакции контроллера, но появятся паразитные колебания, которые при определенных (критических) значениях, перестанут быть затухающими.

Ниже приведена известна таблица влияния увеличения параметров ПИД-регулятора (как уменьшить шрифт, а то таблица безе переносов не лезет?):

А общий алгоритм ручной настройки ПИД-регулятора следующий:

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

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

В общем не будем о грустном, дальше нас ждет самое интересное…

Попытка номер три. Еще раз производные

Приделав костыль в виде ограничения значений выхода контроллера мы так и не решили самую главную проблему нашего регулятора — дифференциальная составляющая плохо себя чувствует при ступенчатом изменении ошибки на входе регуляторе. На самом деле есть множество других костылей, например, в момент скачкообразного изменения SP «отключать» дифференциальную составляющую или же поставить фильтры нижних частот между SP(t) и операцией $SP(t)-PV(t)$ за счет которого будет происходить плавное нарастание ошибки, а можно совсем развернуться и впендюрить самый настоящий фильтр Калмана для сглаживания входных данных. В общем костылей много, и добавить наблюдателя конечно хотелось бы, но не в этот раз.

Поэтому снова вернемся к производной ошибки рассогласования и внимательно на неё посмотрим:

$ frac{de(t)}{dt} = frac{d(SP(t)-PV(t))}{dt} = frac{dSP(t)}{dt} - frac{dPV(t)}{dt}, $

Ничего не заметили? Если хорошенько присмотреться, то можно обнаружить, что вообще-то SP(t), не меняется во времени (за исключением моментов ступенчатого изменения, когда регулятор получает новую команду), т.е. её производная равна нулю:

$ frac{dSP(t)}{dt} = 0, $

тогда

$ frac{de(t)}{dt} = - frac{dPV(t)}{dt}, $

Иными словами, вместо производной ошибки, которая дифференцируема не везде мы можем использовать производную от процесса, который в мире классической механики как правило непрерывен и дифференцируем везде, а схема нашей САУ уже приобретет следующий вид:
image

$ e(t) = SP(t) - PV(t), $

$ CO(t) = underbrace{K_p cdot e(t)}_{P} + underbrace{K_i cdot int_0^t e(tau)dtau}_{I} - underbrace{K_d cdot frac{dPV(t)}{dt}}_{D}, $

Модифицируем код регулятора:

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;
}

И-и-и-и… если запустить игру, то обнаружиться, что на самом деле ничего ничего не изменилось с последней попытки, что и требовалось доказать. Однако, если убрать сатурацию, то график реакции регулятора будет выглядеть вот так:
image
Скачок CO(t) по прежнему присутствует, однако он уже не такой большой как был в самом начале, а самое главное — он стал предсказуемым, т.к. обеспечивается исключительно пропорциональной составляющей, и ограничен максимально возможной ошибкой рассогласования и пропорциональным коэффициентом ПИД-регулятора (а это уже намекает на то, что Kp имеет смысл выбрать все же меньше единицы, например, 1/90f), но не зависит от шага сетки дифференцирования (т.е. dt). В общем, я настоятельно рекомендую использовать именно производную процесса, а не ошибки.

Думаю теперь никого не удивит, но таким же макаром можно заменить $K_p cdot e(t)$ на $-K_p cdot PV(t)$, однако останавливаться на этом мы не будем, можете сами поэкспериментировать и рассказать в комментариях, что из этого получилось (самому интересно)

Попытка номер четыре. Альтернативные реализации ПИД-регулятор

Помимо описанного выше идеального представления ПИД-регулятора, на практике часто применяется стандартная форма, без коэффициентов Ki и Kd, вместо которых используются временные постоянные.

Такой подход связан с тем, что ряд методик настройки ПИД-регулятора основан на частотных характеристиках ПИД-регулятора и процесса. Собственно вся ТАУ и крутится вокруг частотных характеристик процессов, поэтому для желающих углубиться, и, внезапно, столкнувшихся с альтернативной номенклатурой, приведу пример т.н. стандартной формы ПИД-регулятора:

$ e(t) = SP(t) - PV(t), $

$ CO(t) =CO_{bias} + K_p cdot Bigl(e(t) + frac{1}{T_i} cdot int_0^t e(tau)dtau - T_d cdot frac{dPV(t)}{dt} Bigl), $

где, $T_d= frac{K_d}{K_p}$ — постоянная дифференцирования, влияющая на прогнозирование состояния системы регулятором,
$T_i = frac{K_p}{K_i}$ — постоянная интегрирования, влияющая на интервал усреднения ошибки интегральным звеном.

Основные принципы настройки ПИД-регулятора в стандартной форме аналогичны идеализированному ПИД-регулятору:

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

Исходный код стандартной формы, вы можете найти под спойлером

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 — при таких значениях корабль поворачивается достаточно быстро и обладает некоторым запасом устойчивости.

Помимо такой формы ПИД-регулятора, часто используется т.н. реккурентная форма:

$ CO(t_k)=CO(t_{k-1})+K_pleft[left(1+dfrac{Delta t}{T_i}+dfrac{T_d}{Delta t}right)e(t_k)+left(-1-dfrac{2T_d}{Delta t}right)e(t_{k-1})+dfrac{T_d}{Delta t}e(t_{k-2})right] $

Не будем на ней останавливаться, т.к. она актуальна прежде всего для хардверных программистов, работающих с 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()
        {

        }        
    }
}

А вот, собственно заключительное видео того, что должно получиться:

К сожалению получилось охватить не все, что хотелось бы, в частности почти не затронут вопрос настройки ПИД-регулятора и практически не освящена интегральная составляющая — фактически приведен пример только для ПД-регулятора. Собственно изначально планировалось несколько больше примеров (круиз-контроль, вращение турели и компенсация вращательного момента), но статья итак уже разбухла, да и вообще:
image

Немного ссылок

  1. Годная статья на английской вики
  2. PID tutorial
  3. ПИД-регуляторы: вопросы реализации. Часть 1
  4. ПИД-регуляторы: вопросы реализации. Часть 2
  5. PID Without a PhD
  6. PID Without a PhD. Перевод
  7. Derivative Action and PID Control
  8. Control System Lab: PID
  9. ПИД-регулятор своими руками
  10. Корректная реализация разностной схемы ПИД регулятора
  11. Программируем квадрокоптер на Arduino (часть 1)
  12. Виртуальный квадрокоптер на Unity + OpenCV (Часть 1)
  13. Поляков К.Ю. Теория автоматического управления для чайников
  14. PID control system analysis, design, and technology
  15. Aidan O’Dwyer. Handbook of PI and PID Controller Tuning Rules (3rd ed.)
  16. PID process control, a “Cruise Control” example
  17. https://www.mathworks.com/discovery/pid-control.html
  18. http://scilab.ninja/study-modules/scilab-control-engineering-basics/module-4-pid-control/
  19. 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

К системам автоматического регулирования (САР) предъявляются требования не только
устойчивости процессов регулирования. Для работоспособности системы не менее необходимо, чтобы процесс автоматического регулирования осуществлялся при обеспечении определенных показателей качества процесса управления.

Если исследуемая САР является устойчивой, возникает вопрос о том, насколько качественно происходит регулирование в этой системе и удовлетворяет ли оно технологическим требованиям обьекта управления.На практике качество регулирования определяется визуально по графику переходной характеристики. Однако, имеются точные но более сложные математические методы, дающие конкретные числовые значения (которые не рассматриваются в данной методике).

Классификация показателей качества состоит из нескольких групп:

  • прямые — определяемые непосредственно по переходной характеристике процесса,
  • корневые — определяемые по корням характеристического полинома,
  • частотные — по частотным характеристикам,
  • интегральные — получаемые путем интегрирования функций.

Прямыми показателями качества процесса управления, определяемые непосредственно по
переходной характеристике являются:

  1. Установившееся значение выходной величины Yуст,
  2. Степень затухания ?,
  3. Время достижения первого максимума tmax,
  4. Время регулирования tp,
  5. Ошибка регулирования Ест (статистическая или среднеквадратическая составляющие),
  6. Перерегулирование у,
  7. Динамический коэффициент регулирования Rd,
  8. Показатель колебательности М.

Например, переходная характеристика, снятая на объекте управления при отработке ступенчатого воздействия, имеет колебательный вид и представлена на рис.1.

Рисунок 1 — Определение показателей качества по переходной характеристике

Установившееся значение выходной величины Yуст

Установившееся значение выходной величины Yуст определяется по переходной характеристике,представленной на рис.1.

Степень затухания ?

Степень затухания ? определяется по формуле:

где А1 и А3 — соответственно 1-я и 3-я амплитуды переходной характеристики рис.1.

Время достижения первого максимума tmax

Время достижения первого максимума tmax определяется по переходной характеристике,представленной на рис.1.

Время регулирования tp

Время регулирования tp определяется согласно рис.1 следующим образом:Находится допустимое отклонение Д, например, задано Д = 5%Yуст и строится «зона» толщиной 2 Д(см. рис.1). Время tp соответствует последней точке пересечения Y(t) с данной границей. То есть время,когда колебания регулируемой величины перестают превышать 5 % от установившегося значения.
Настройки регулятора необходимо выбирать так, чтобы обеспечить минимально возможное значение общего времени регулирования, либо минимальное значение первой полуволны переходного процесса.

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

Ошибка регулирования Ест

Статическая ошибка регулирования Ест = Ув — Ууст, где Ув — входная величина (см. рис.1).В некоторых САР наблюдается ошибка, которая не исчезает даже по истечении длительногоинтервала времени — это статическая ошибка регулирования Ест. Данная ошибка не должна превышатьнекоторой наперед заданной величины. У регуляторов с интегральной составляющей ошибки в установившемся состоянии теоретическиравны нулю, но практически незначительные ошибки могут существовать из-за наличия зоннечувствительности в элементах системы.

Перерегулирование у

Величина перерегулирования у зависит от вида отрабатываемого сигнала.При отработке ступенчатого воздействия (по сигналу задания) – см. рис.1 величина перерегулирования у определяется по формуле:

где значения величин Ymax и Yуст определяются согласно рис.1.

При отработке возмущающего воздействия, величина перерегулирования у определяется изсоотношения:

где значения величин Xm и X1 определяются согласно рис. 2.

Рисунок 2 — График переходного процесса при отработке возмущения

Динамический коэффициент регулирования Rd

Динамический коэффициент регулирования Rd определяется из формулы:

где значения величин Y1 и Y0 определяются согласно рис. 3.

Рисунок 3 — К понятию динамического коэффициента регулирования

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

Показатель колебательности М

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

Рисунок 4 — График модуля частотной передаточной функции замкнутой системы

Условно считается, что значение М=1,5-1,6 является оптимальным для промышленных САР, т.к. вэтом случае у обеспечивается в районе от 20% до 40%. При увеличении значения M колебательность всистеме возрастает.

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

К системам автоматического регулирования (САР) предъявляются требования не только
устойчивости процессов регулирования. Для работоспособности системы не менее необходимо, чтобы процесс автоматического регулирования осуществлялся при обеспечении определенных показателей качества процесса управления.

Если исследуемая САР является устойчивой, возникает вопрос о том, насколько качественно происходит регулирование в этой системе и удовлетворяет ли оно технологическим требованиям обьекта управления.На практике качество регулирования определяется визуально по графику переходной характеристики. Однако, имеются точные но более сложные математические методы, дающие конкретные числовые значения (которые не рассматриваются в данной методике).

Классификация показателей качества состоит из нескольких групп:

  • прямые — определяемые непосредственно по переходной характеристике процесса,
  • корневые — определяемые по корням характеристического полинома,
  • частотные — по частотным характеристикам,
  • интегральные — получаемые путем интегрирования функций.

Прямыми показателями качества процесса управления, определяемые непосредственно по
переходной характеристике являются:

  1. Установившееся значение выходной величины Yуст,
  2. Степень затухания ?,
  3. Время достижения первого максимума tmax,
  4. Время регулирования tp,
  5. Ошибка регулирования Ест (статистическая или среднеквадратическая составляющие),
  6. Перерегулирование у,
  7. Динамический коэффициент регулирования Rd,
  8. Показатель колебательности М.

Например, переходная характеристика, снятая на объекте управления при отработке ступенчатого воздействия, имеет колебательный вид и представлена на рис.1.

Рисунок 1 — Определение показателей качества по переходной характеристике

Установившееся значение выходной величины Yуст

Установившееся значение выходной величины Yуст определяется по переходной характеристике,представленной на рис.1.

Степень затухания ?

Степень затухания ? определяется по формуле:

где А1 и А3 — соответственно 1-я и 3-я амплитуды переходной характеристики рис.1.

Время достижения первого максимума tmax

Время достижения первого максимума tmax определяется по переходной характеристике,представленной на рис.1.

Время регулирования tp

Время регулирования tp определяется согласно рис.1 следующим образом:Находится допустимое отклонение Д, например, задано Д = 5%Yуст и строится «зона» толщиной 2 Д(см. рис.1). Время tp соответствует последней точке пересечения Y(t) с данной границей. То есть время,когда колебания регулируемой величины перестают превышать 5 % от установившегося значения.
Настройки регулятора необходимо выбирать так, чтобы обеспечить минимально возможное значение общего времени регулирования, либо минимальное значение первой полуволны переходного процесса.

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

Ошибка регулирования Ест

Статическая ошибка регулирования Ест = Ув — Ууст, где Ув — входная величина (см. рис.1).В некоторых САР наблюдается ошибка, которая не исчезает даже по истечении длительногоинтервала времени — это статическая ошибка регулирования Ест. Данная ошибка не должна превышатьнекоторой наперед заданной величины. У регуляторов с интегральной составляющей ошибки в установившемся состоянии теоретическиравны нулю, но практически незначительные ошибки могут существовать из-за наличия зоннечувствительности в элементах системы.

Перерегулирование у

Величина перерегулирования у зависит от вида отрабатываемого сигнала.При отработке ступенчатого воздействия (по сигналу задания) – см. рис.1 величина перерегулирования у определяется по формуле:

где значения величин Ymax и Yуст определяются согласно рис.1.

При отработке возмущающего воздействия, величина перерегулирования у определяется изсоотношения:

где значения величин Xm и X1 определяются согласно рис. 2.

Рисунок 2 — График переходного процесса при отработке возмущения

Динамический коэффициент регулирования Rd

Динамический коэффициент регулирования Rd определяется из формулы:

где значения величин Y1 и Y0 определяются согласно рис. 3.

Рисунок 3 — К понятию динамического коэффициента регулирования

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

Показатель колебательности М

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

Рисунок 4 — График модуля частотной передаточной функции замкнутой системы

Условно считается, что значение М=1,5-1,6 является оптимальным для промышленных САР, т.к. вэтом случае у обеспечивается в районе от 20% до 40%. При увеличении значения M колебательность всистеме возрастает.

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

Лекция 17.
Расчет
установившейся ошибки в системах
управления. Структурные признаки
астатизма. Коэффициенты ошибок

Установившейся
(статической) ошибкой называют постоянное
значение сигнала ошибки x(t)=g(t)-y(t),
которое она приобретает по окончании
переходного процесса:
,
рисунок 116.

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

,

,


и так далее.

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

,

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

Рассмотрим порядок
расчета установившейся ошибки на
следующем достаточно общем примере
(рисунок 117).

В соответствии с
принципом суперпозиции установившаяся
ошибка будет определяться здесь в виде
суммы трех составляющих
.

Изображение по
Лапласу ошибки от задающего воздействия
получают через передаточную функцию
замкнутой системы по ошибке

при известном изображении задающего
воздействия G(s):

,

где (s)
– основная передаточная функция
замкнутой системы. Для структурной
схемы на рисунке 117

,

где

— передаточная функция разомкнутой
системы, или прямой цепи системы, для
рассматриваемого примера.

Непосредственно
для расчета установившегося значения
ошибки от задающего воздействия
используют теорему о конечном значении
для преобразования Лапласа:

В результате:

.

Изображение по
Лапласу ошибки от возмущающего воздействия
получают через передаточную функцию
замкнутой системы по ошибке от возмущения

при известном изображении возмущающего
воздействия F(s):

,

где f(s)
–передаточная функция замкнутой системы
по возмущающему воздействию,

;

Wf(s)
– передаточная функция разомкнутой
системы по возмущению (передаточная
функция участка прямой цепи системы от
точки приложения возмущающего воздействия
до выхода системы).

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

Для f1:

,

,

.

Для f2:

,

,

.

Расчет упрощается
для системы с единичной отрицательной
обратной связью (рисунок 118):

,

,

где k=k1k2k3
– коэффициент передачи разомкнутой
системы.

Найдем установившуюся
ошибку для некоторых типовых вариантов
задающего воздействия.

При

получим:

.

При

получим:

.

При

получим:

.

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

Количество типовых
вариантов входного сигнала – членов
степенного ряда, при которых установившаяся
ошибка тождественно равна нулю, определяет
порядок астатизма.

Рассматриваемая
система обладает свойством астатизма
второго порядка по задающему воздействию.

Рассмотрим
установившуюся ошибку от возмущения
f1:

,

,

где

– коэффициент передачи разомкнутой
системы по возмущению f1.

При

получим:

.

При

получим:

.

При

получим тот же результат.

Отметим, что по
возмущению f1
рассматриваемая система не является
астатической. Кроме того, она не в
состоянии отработать два последних
варианта входного сигнала.

Рассмотрим
установившуюся ошибку от возмущения
f2:

,

,

где

– коэффициент передачи разомкнутой
системы по возмущению f2.

При

получим:

.

При

получим:

.

При

получим:

.

По возмущению f2
рассматриваемая система имеет астатизм
первого порядка. Она не в состоянии
отработать возмущающее воздействие,
изменяющееся во времени с постоянным
ускорением.

Подведем некоторые
итоги:

1. Наличие и глубина
свойства астатизма зависят от точки
приложения входного сигнала.

2. Постоянные
времени звеньев системы не влияют на
ее точность.

3. Увеличение
значения коэффициента передачи
разомкнутой системы приводит к снижению
величины установившейся ошибки.

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

Рассмотрим
структуру, показанную на рисунке 119.

В общем случае
передаточная функция разомкнутой
системы может быть представлена в
следующей форме:

,

где l0.

Тогда получим:

и для общего вида
задающего воздействия
,
которому соответствует изображение
,

.

Результат нахождения
этого предела зависит от соотношения
показателей степени:

— при l>v
установившаяся ошибка равна нулю
независимо от остальных параметров, то
есть имеет место астатизм;

— при l=v
получаем константу;

— при l<v
установившаяся ошибка стремится к
бесконечности, то есть система не в
состоянии отработать входной сигнал.

Учитывая, что
минимальное значение v
нулевое, получаем условие астатизма по
задающему воздействию: l>0.

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

Нетрудно также
убедиться, что положительное значение
l
совпадает с порядком астатизма.

Для получения
признака астатизма по возмущающему
воздействию представим передаточные
функции на рисунке 10 в форме:

,

,

где l1+l2=l,
k1k2=k,
m1+m2=m,
n1+n2=n,
причем

и
.

Тогда получим:

и для общего вида
возмущающего воздействия
,
которому соответствует изображение
,

.

Все вышеприведенные
выводы можно повторить для показателя
степени l1.

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

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

Если рассматривать
произвольный закон изменения задающего
воздействия g(t),
то эта функция времени может быть
разложена в степенной ряд относительно
аргумента t.
Члены степенного ряда, как известно,
находятся через производные

,
,
…,
,

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

,
n>m.

Для задачи оценки
установившейся ошибки при

с формулированное допущение вполне
корректно, так как в противном случае
эта задача не имеет смысла.

Коэффициенты
ошибки получают разложением передаточной
функции замкнутой системы по ошибке в
степенной ряд (ряд Тейлора) относительно
аргумента s:

,

где коэффициенты
разложения в общем случае находят как
значения производных в точке s=0:

.

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

С учетом разложения
передаточной функции в ряд можно записать
изображение по Лапласу сигнала ошибки
в следующей форме:

.

Отметим, что с
учетом сформулированного выше допущения
такое представление сигнала ошибки
соответствует

или
.

Перейдя к оригиналу
с учетом теоремы дифференцирования
получим:

.

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

Найдем коэффициенты
разложения передаточной функции по
ошибке

в степенной ряд.

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

Далее получим:

В результате
получаем
,
,
,

и так далее.

Найдем производные
задающего воздействия:

,
,
.

Ясно, что для
определения установившейся ошибки
достаточно первых трех коэффициентов:

.

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

Соседние файлы в папке Конспект ТАУ

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Макеты страниц

где коэффициенты принято называть коэффициентами ошибок. Формула (4.3) получена следующим образом.

Передаточная функция замкнутой системы относительно ошибки (рис. 4.1)

Из (4.4) можно найти выражение для изображения ошибки:

Разложим передаточную функцию по ошибке в ряд по возрастающим степеням s в окрестности точки что соответствует большим значениям времени т. е. значению установившейся ошибки при заданном управляющем воздействии.

В соответствии с (4.5) можно записать

Если передаточная функция является дробно-рациональной функцией

то разложение в ряд можно осуществить делением числителя на знаменатель, располагая члены полинома в порядке возрастания степеней. Переходя в (4.6) от изображений к оригиналам, можно получить для выражение (4.3).

Коэффициенты ошибок определяют по формулам разложения функции в ряд Тейлора:

Если то все производные тогда

В данном случае — значение установившейся ошибки в замкнутой системе.

Если ; коэффициенты и т. д.

Коэффициент называют коэффициентом статической или позиционной ошибки; коэффициент С — коэффициентом скоростной ошибки, — коэффициентом ошибки от ускорения.

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

Пусть воздействия на САУ являются постоянными величинами и равны Рассмотрим несколько случаев.

1. В системе отсутствуют интегрирующие звенья. Элементы 1 и 2 системы (рис. 4.2) являются инерционными звеньями и соответственно равны

Рис. 4.2

Тогда на основании метода суперпозиции установившаяся ошибка САУ

где — ошибка отработки системой задающего воздействия:

а — ошибка, вызванная действием помехи:

В данном случае САУ является статической относительно обоих воздействий, так как .

2. Допустим, что в элемент 2 рассматриваемой системы (рис. 4.2) включено интегрирующее звено, а элемент является инерционным звеном, как и в случае 1. При этом передаточная функция элемента 2

Тогда составляющие ошибки системы (4.9)

Следовательно, САУ является астатической относительно задающего воздействия и статической относительно возмущения

3. Пусть интегрирующее звено включено в элемент передаточная функция его при этом равна

Второе звено является инерционным звеном, а передаточная функция его та же, что и в случае 1.

Рассчитаем составляющие ошибки

Поскольку и система является астатической и относительно воздействия и относительно возмущения

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

Пример 4.1. Для системы (рис. 4.1) определить значение устано вившейся ошибки системы. Передаточная функция системы в разомкнутом состоянии

где

Выходной сигнал меняется по закону Найдем передаточную функцию замкнутой системы относительно ошибки:

Коэффициенты ошибок так как система астатическая) определяют по (4.7) или разложением в ряд по возрастающим степеням s функции делением числителя на знаменатель:

Коэффициенты вычислять не имеет смысла, так как функция имеет только две производные, не равные нулю.

Определим первую и вторую производные входного воздействия

Тогда


The deviation of the output of control system from desired response during steady state is known as steady state error. It is represented as $e_{ss}$. We can find steady state error using the final value theorem as follows.

$$e_{ss}=lim_{t to infty}e(t)=lim_{s to 0}sE(s)$$

Where,

E(s) is the Laplace transform of the error signal, $e(t)$

Let us discuss how to find steady state errors for unity feedback and non-unity feedback control systems one by one.

Steady State Errors for Unity Feedback Systems

Consider the following block diagram of closed loop control system, which is having unity negative feedback.

Steady State Negative Error

Where,

  • R(s) is the Laplace transform of the reference Input signal $r(t)$
  • C(s) is the Laplace transform of the output signal $c(t)$

We know the transfer function of the unity negative feedback closed loop control system as

$$frac{C(s)}{R(s)}=frac{G(s)}{1+G(s)}$$

$$Rightarrow C(s)=frac{R(s)G(s)}{1+G(s)}$$

The output of the summing point is —

$$E(s)=R(s)-C(s)$$

Substitute $C(s)$ value in the above equation.

$$E(s)=R(s)-frac{R(s)G(s)}{1+G(s)}$$

$$Rightarrow E(s)=frac{R(s)+R(s)G(s)-R(s)G(s)}{1+G(s)}$$

$$Rightarrow E(s)=frac{R(s)}{1+G(s)}$$

Substitute $E(s)$ value in the steady state error formula

$$e_{ss}=lim_{s to 0} frac{sR(s)}{1+G(s)}$$

The following table shows the steady state errors and the error constants for standard input signals like unit step, unit ramp & unit parabolic signals.

Input signal Steady state error $e_{ss}$ Error constant

unit step signal

$frac{1}{1+k_p}$

$K_p=lim_{s to 0}G(s)$

unit ramp signal

$frac{1}{K_v}$

$K_v=lim_{s to 0}sG(s)$

unit parabolic signal

$frac{1}{K_a}$

$K_a=lim_{s to 0}s^2G(s)$

Where, $K_p$, $K_v$ and $K_a$ are position error constant, velocity error constant and acceleration error constant respectively.

Note − If any of the above input signals has the amplitude other than unity, then multiply corresponding steady state error with that amplitude.

Note − We can’t define the steady state error for the unit impulse signal because, it exists only at origin. So, we can’t compare the impulse response with the unit impulse input as t denotes infinity.

Example

Let us find the steady state error for an input signal $r(t)=left( 5+2t+frac{t^2}{2} right )u(t)$ of unity negative
feedback control system with $G(s)=frac{5(s+4)}{s^2(s+1)(s+20)}$

The given input signal is a combination of three signals step, ramp and parabolic. The following table shows the error constants and steady state error values for these three signals.

Input signal Error constant Steady state error

$r_1(t)=5u(t)$

$K_p=lim_{s to 0}G(s)=infty$

$e_{ss1}=frac{5}{1+k_p}=0$

$r_2(t)=2tu(t)$

$K_v=lim_{s to 0}sG(s)=infty$

$e_{ss2}=frac{2}{K_v}=0$

$r_3(t)=frac{t^2}{2}u(t)$

$K_a=lim_{s to 0}s^2G(s)=1$

$e_{ss3}=frac{1}{k_a}=1$

We will get the overall steady state error, by adding the above three steady state errors.

$$e_{ss}=e_{ss1}+e_{ss2}+e_{ss3}$$

$$Rightarrow e_{ss}=0+0+1=1$$

Therefore, we got the steady state error $e_{ss}$ as 1 for this example.

Steady State Errors for Non-Unity Feedback Systems

Consider the following block diagram of closed loop control system, which is having nonunity negative feedback.

Non Unity

We can find the steady state errors only for the unity feedback systems. So, we have to convert the non-unity feedback system into unity feedback system. For this, include one unity positive feedback path and one unity negative feedback path in the above block diagram. The new block diagram looks like as shown below.

Unity Negative State

Simplify the above block diagram by keeping the unity negative feedback as it is. The following is the simplified block diagram.

Simplified Negative Diagram

This block diagram resembles the block diagram of the unity negative feedback closed loop control system. Here, the single block is having the transfer function $frac{G(s)}{1+G(s)H(s)-G(s)}$ instead of $G(s)$. You can now calculate the steady state errors by using steady state error formula given for the unity negative feedback systems.

Note − It is meaningless to find the steady state errors for unstable closed loop systems. So, we have to calculate the steady state errors only for closed loop stable systems. This means we need to check whether the control system is stable or not before finding the steady state errors. In the next chapter, we will discuss the concepts-related stability.


The deviation of the output of control system from desired response during steady state is known as steady state error. It is represented as $e_{ss}$. We can find steady state error using the final value theorem as follows.

$$e_{ss}=lim_{t to infty}e(t)=lim_{s to 0}sE(s)$$

Where,

E(s) is the Laplace transform of the error signal, $e(t)$

Let us discuss how to find steady state errors for unity feedback and non-unity feedback control systems one by one.

Steady State Errors for Unity Feedback Systems

Consider the following block diagram of closed loop control system, which is having unity negative feedback.

Steady State Negative Error

Where,

  • R(s) is the Laplace transform of the reference Input signal $r(t)$
  • C(s) is the Laplace transform of the output signal $c(t)$

We know the transfer function of the unity negative feedback closed loop control system as

$$frac{C(s)}{R(s)}=frac{G(s)}{1+G(s)}$$

$$Rightarrow C(s)=frac{R(s)G(s)}{1+G(s)}$$

The output of the summing point is —

$$E(s)=R(s)-C(s)$$

Substitute $C(s)$ value in the above equation.

$$E(s)=R(s)-frac{R(s)G(s)}{1+G(s)}$$

$$Rightarrow E(s)=frac{R(s)+R(s)G(s)-R(s)G(s)}{1+G(s)}$$

$$Rightarrow E(s)=frac{R(s)}{1+G(s)}$$

Substitute $E(s)$ value in the steady state error formula

$$e_{ss}=lim_{s to 0} frac{sR(s)}{1+G(s)}$$

The following table shows the steady state errors and the error constants for standard input signals like unit step, unit ramp & unit parabolic signals.

Input signal Steady state error $e_{ss}$ Error constant

unit step signal

$frac{1}{1+k_p}$

$K_p=lim_{s to 0}G(s)$

unit ramp signal

$frac{1}{K_v}$

$K_v=lim_{s to 0}sG(s)$

unit parabolic signal

$frac{1}{K_a}$

$K_a=lim_{s to 0}s^2G(s)$

Where, $K_p$, $K_v$ and $K_a$ are position error constant, velocity error constant and acceleration error constant respectively.

Note − If any of the above input signals has the amplitude other than unity, then multiply corresponding steady state error with that amplitude.

Note − We can’t define the steady state error for the unit impulse signal because, it exists only at origin. So, we can’t compare the impulse response with the unit impulse input as t denotes infinity.

Example

Let us find the steady state error for an input signal $r(t)=left( 5+2t+frac{t^2}{2} right )u(t)$ of unity negative
feedback control system with $G(s)=frac{5(s+4)}{s^2(s+1)(s+20)}$

The given input signal is a combination of three signals step, ramp and parabolic. The following table shows the error constants and steady state error values for these three signals.

Input signal Error constant Steady state error

$r_1(t)=5u(t)$

$K_p=lim_{s to 0}G(s)=infty$

$e_{ss1}=frac{5}{1+k_p}=0$

$r_2(t)=2tu(t)$

$K_v=lim_{s to 0}sG(s)=infty$

$e_{ss2}=frac{2}{K_v}=0$

$r_3(t)=frac{t^2}{2}u(t)$

$K_a=lim_{s to 0}s^2G(s)=1$

$e_{ss3}=frac{1}{k_a}=1$

We will get the overall steady state error, by adding the above three steady state errors.

$$e_{ss}=e_{ss1}+e_{ss2}+e_{ss3}$$

$$Rightarrow e_{ss}=0+0+1=1$$

Therefore, we got the steady state error $e_{ss}$ as 1 for this example.

Steady State Errors for Non-Unity Feedback Systems

Consider the following block diagram of closed loop control system, which is having nonunity negative feedback.

Non Unity

We can find the steady state errors only for the unity feedback systems. So, we have to convert the non-unity feedback system into unity feedback system. For this, include one unity positive feedback path and one unity negative feedback path in the above block diagram. The new block diagram looks like as shown below.

Unity Negative State

Simplify the above block diagram by keeping the unity negative feedback as it is. The following is the simplified block diagram.

Simplified Negative Diagram

This block diagram resembles the block diagram of the unity negative feedback closed loop control system. Here, the single block is having the transfer function $frac{G(s)}{1+G(s)H(s)-G(s)}$ instead of $G(s)$. You can now calculate the steady state errors by using steady state error formula given for the unity negative feedback systems.

Note − It is meaningless to find the steady state errors for unstable closed loop systems. So, we have to calculate the steady state errors only for closed loop stable systems. This means we need to check whether the control system is stable or not before finding the steady state errors. In the next chapter, we will discuss the concepts-related stability.

Ошибка регулирования

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

Теоретические аспекты и основы экологической проблемы: толкователь слов и идеоматических выражений. — Чувашский государственный университет им. И.Н.Ульянова. УНПП «Лаборатория проблем цивилизации».
.
1998.

Смотреть что такое «Ошибка регулирования» в других словарях:

  • ошибка регулирования — — [Я.Н.Лугинский, М.С.Фези Жилинская, Ю.С.Кабиров. Англо русский словарь по электротехнике и электроэнергетике, Москва, 1999 г.] Тематики электротехника, основные понятия EN error …   Справочник технического переводчика

  • ошибка регулирования в процентах — — [Я.Н.Лугинский, М.С.Фези Жилинская, Ю.С.Кабиров. Англо русский словарь по электротехнике и электроэнергетике, Москва, 1999] Тематики электротехника, основные понятия EN percent deviation …   Справочник технического переводчика

  • ошибка регулирования района — — [Я.Н.Лугинский, М.С.Фези Жилинская, Ю.С.Кабиров. Англо русский словарь по электротехнике и электроэнергетике, Москва, 1999] Тематики электротехника, основные понятия EN area control errorACE …   Справочник технического переводчика

  • Астатическая система регулирования —         система автоматического регулирования режимов работы промышленных установок, систем автоматического управления и др., в которой ошибка регулирования стремится к нулю независимо от размера воздействия, если последнее принимает… …   Большая советская энциклопедия

  • Динамическая ошибка —         динамическая погрешность, динамическое отклонение, разность между требуемым и действительным значениями регулируемой величины, возникающая и измеряющаяся в процессе регулирования; см. Регулирование автоматическое …   Большая советская энциклопедия

  • Теория автоматического управления — Содержание 1 История 2 Основные понятия 3 Функциональн …   Википедия

  • Статическая система — Статическая система  это такая система автоматического регулирования, в которой ошибка регулирования стремится к постоянному значению при входном воздействии, стремящемся к некоторому постоянному значению. Иными словами статическая система… …   Википедия

  • полный размах колебаний регулируемой величины от заданного значения — полный размах отклонений регулируемой величины от заданного значения ошибка регулирования — [Я.Н.Лугинский, М.С.Фези Жилинская, Ю.С.Кабиров. Англо русский словарь по электротехнике и электроэнергетике, Москва, 1999 г.] Тематики… …   Справочник технического переводчика

  • Регулирование автоматическое — (от нем. regulieren регулировать, от лат. regula норма, правило)         поддержание постоянства (стабилизация) некоторой регулируемой величины, характеризующей технический процесс, либо её изменение по заданному закону (программное… …   Большая советская энциклопедия

  • Трунов, Игорь Леонидович — В Википедии есть статьи о других людях с такой фамилией, см. Трунов. Игорь Леонидович Трунов Портрет Род деятельности: Адвокат Дата рождения: 1961 год(1 …   Википедия

Понравилась статья? Поделить с друзьями:
  • Ошибка рено дастер ро 303
  • Ошибка резидента фильм трилогия
  • Ошибка регулировка устойчивости bmw f30
  • Ошибка резидента фильм возвращение бекаса
  • Ошибка рено дастер молния