Привет! PID-регулятор — частая проблема для начинающих в робототехнике: математика отпугивает. Но саму идею понять можно без формул. В этой статье я объясню P, I и D простыми словами.
Симулятор
Чтобы было проще понять работу регулятора, я написал простой симулятор. Он доступен по ссылке — там можно поэкспериментировать самому. Всё на Python — так он доступен как можно большему кругу людей. Буду рад звёздочке :)
Что такое PID-регулятор?
PID-регулятор — это программа, которая читает показания датчика и управляет мощностью так, чтобы значение датчика стало тем, что вы задали. Он применяется для очень многих задач, где нужно что-то удерживать в заданном положении:
Температура в комнате, печи, паяльнике, бойлере
Скорость автомобиля, конвейера, вентилятора
Расстояние до машины впереди
Высота и наклон квадрокоптера
И многое другое
Как работает
Регулятор постоянно смотрит на два значения:
Что датчик показывает сейчас
Что хотят, чтобы он показывал
Он вычисляет разницу (отклонение/ошибку) и решает, как сильно надо двигать рычаг, чтобы уменьшить эту ошибку. Решение складывается из трёх частей (составляющих):
P — пропорциональная (proportional)
I — интегральная (integral)
D — дифференциальная (derivative)
Не надо пугаться страшных слов, на деле всё проще, чем кажется.
Каждую часть можно усилить или ослабить специальным числом — коэффициентом. В итоге он складывает P+I+D (три числа) и получает или мощность нагревателя, или степень открытия окна, или напряжение двигателя и т. д.
Далее мы поэтапно разберём, зачем нужна каждая из составляющих. Для примера, мы будем стараться остановить робота в нужной позиции.
Релейный регулятор – самое простое, но грубое решение
Сначала вспомним самый простой способ управления:
Если робот слева от цели — включим двигатель на фиксированную мощность вправо
Если справа — включим двигатель на фиксированную мощность влево

Как видно, робот медленно добрался до нужной точки и остаётся в ней. Но что, если робот станет тяжелее или у него появится больше силы?

А вот теперь он уже не может остановиться в нужной точке. Со временем колебания стихают из-за трения, но так не пойдёт. Это происходит, так как даже когда роботу надо подвинуться совсем немного, он всё равно включает двигатель так, как будто он ещё далеко и слишком сильно разгоняется. Частые резкие включения/выключения быстро изнашивают детали.
P-составляющая, P-регулятор
Давайте же будем по мере приближения уменьшать мощность. Чем меньше ошибка, тем меньше мощность. Пример: если робот в 10 см от цели — подать 50% мощности; если в 1 см — 5%.

Теперь робот легко достигает цели и плавно выключает моторы. Отлично! Но что, если робот станет ещё тяжелее и сильнее?

Он снова болтается! Это происходит, так как с увеличением силы робот стал ездить быстрее и ему теперь сложнее затормозить, а большая масса ещё больше ему в этом мешает. В итоге силы трения не хватает, чтобы погасить набранную скорость.
D-составляющая, PD-регулятор
Чтобы с этим справиться, ему придётся начать тормозить самостоятельно ещё до достижения цели. Тут мы уже будем смотреть не на то, как далеко от цели находимся, а на то, как быстро к ней приближаемся. В нашем случае — это скорость робота. Чем быстрее едет робот, тем больше D-составляющая будет его тормозить.
Добавим к нашему P-регулятору D-составляющую и получим PD-регулятор. Посмотрим, что у нас получилось.

Отлично! Мы справились и с этим. Видно, что, когда робот далеко, P-составляющая зашкаливает и робот отлично разгоняется, но по мере сближения она ослабевает и в дело вступает D-составляющая, которая видит, что робот едет слишком быстро и тормозит его. Она это делала и раньше, но так как P-составляющая была очень большой, робот всё равно разгонялся, просто не так быстро. Теперь каким бы мощным и тяжёлым не становился робот, мы просто можем увеличить коэффициент D-составляющей и всё снова придёт в норму.
Вот работа регулятора на легком и мощном роботе.

А теперь ещё и на тяжелом.

И вот, кажется, всё работает как надо: робот быстро достигает цели и не болтается. А давайте наклоним наше поле!

Теперь робот вообще не может достигнуть своей цели: в таких условиях чтобы остановиться там, где мы хотим, ему всегда надо прилагать усилия, иначе он будет скатываться, а PD-регулятор это делает только при отдалении от цели.
Важно, что это может быть не только наклон. Например:
Если робот с отдельными моторами для левого и правого колеса захочет ехать прямо, у него это скорее всего не получится, так как двух одинаковых моторов не существует и один будет перегонять другого. Робота будет уводить влево или вправо.
У нагревателя не получится держать заданную температуру, так как холодный воздух будет его охлаждать.
Вентилятор не сможет поддерживать заданную скорость вращения, так как его тормозят трение в подшипниках и сопротивление воздуха.
I-составляющая, PID-регулятор
Теперь будем следить ещё за тем, чтобы мы не висели далеко от цели. I-составляющая накапливает ошибку со временем. Чем дальше робот от цели, тем быстрее она растет (или падает, когда робот перелетел). Чем дольше мы там находимся, тем дольше она будет расти.
Добавим к нашему PD-регулятору I-составляющую и получим PID-регулятор. Посмотрим, что у нас получилось.

Теперь робот почти, как и раньше, добрался до какой-то точки. На этот раз — другой: пока робот приближался, I-составляющая успела накопиться. Но теперь он медленно приближается к цели, а не просто стоит. Это как раз I-составляющая накапливает нужную силу. У вас, возможно, возник вопрос: почему бы не увеличить коэффициент I-составляющей чтобы сила накопилась быстрее. Вот что тогда будет.

Робот будет болтаться. А дело всё в том, что I-составляющая накапливается всё время, и пока мы приближаемся к цели она становится такой большой, что мы эту цель перелетаем. Так I-составляющая раскачивает робота.
Ограничения
Однако алгоритм подходит не для всего. Вот случаи, когда он работает плохо:
С высокой задержкой: если в большом ангаре датчик стоит далеко от нагревателя, то, пока до него дойдёт горячий воздух, нагреватель раскалится до максимума, не видя реакции. А когда тепло дойдёт, датчик очень сильно нагреется и нагреватель полностью выключится. Это приводит к сильным колебаниям, которые никогда не стихают.
С высокой нелинейностью: регулятор ожидает, что если он немного подвинет рычаг, то сила тоже изменится немного, а если сильно подвинет, то сильно и изменится. Но если это не так, регулятору будет очень сложно справиться с этим. Представьте себе кран с водой, где вы вертите-вертите, а вода всё горячая, а потом повернули ещё немного, и она уже холодная. Иногда это можно компенсировать программно.
С большой асимметрией: регулятор ожидает, что в обе стороны значения будут меняться одинаково, но это не всегда так. Например, мощный массивный нагреватель может очень быстро поднимать температуру, а охлаждаться он будет гораздо медленнее.
Если объект сильно меняется: регулятору будет сложно управлять беспилотным самолётом, так как его поведение сильно отличается на разной высоте, в разную погоду и с разным уровнем топлива (значительная часть массы). Где-то он будет болтаться, а где-то реагировать очень медленно. Иногда это можно компенсировать программно.
Итог
Мы рассмотрели базовую идею PID-регулятора: P — отвечает за мгновенную реакцию, I — накапливает ошибку и убирает постоянное отклонение, D — тормозит и убирает раскачивание. Такой подход хорошо работает для множества задач — от поддержания температуры до позиционирования робота.
Кстати, если мы захотим контролировать не позицию, а скорость робота, регулятор будет вести себя немного иначе. Но это уже тема для новой статьи. Также можно разобрать кодовую реализацию алгоритма, хотя без математики там уже не обойтись. Проголосуйте за статью и поставьте звёздочку симулятору, если было полезно :)
