/rfilt

Нелинейный фильтр ограничения скорости, ускорения и рывка

Primary LanguageC

Нелинейный фильтр ограничения скорости, ускорения и рывка

Фильтр может быть использован при решении различных задач управления приводами, кранами, станками с ЧПУ, 3d принтерами, в железнодорожном и другом транспорте, в радиолокации, в авиации, при управлении БЛА, в ракето- и торпедо-строении, при проектировании лифтов, при построении различными претензионных систем плавного пуска и торможения.

При "медленно меняющихся" входных значениях выходная последовательность повторяет входную (должна!).

Выходные значения "стараются максимально быстро повторять" входные, но на первую, вторую и третью производную выходного значения накладываются ограничения.

Для инициализации и сброса фильтра служит функция rfilt_init(). Для обновления параметров фильтра "на лету" служит функция rfilt_tune(). Основная рабочая функция фильтра - rfilt_step().

ИДЕЯ ФИЛЬТРА

Считается, что выходное значение на каждом интервале меняется по закону:

dt = t[i+1] - t[i]
x[i+1] = x[i] + V[i] * dt + A[i] * dt^2 / 2 + R[i] * dt^3 / 6  (1)
где:
  dt     - шаг разбиения по времени;
  x[i]   - выходное значение на текущем шаге
  x[i+1] - выходное значение на следующем шаге
  V[i]   - текущая (начальная на интервале) скорость
  A[i]   - текущее (начальника на интервале) ускорение
  R[i]   - выбранный для данного интервала рывок

Скорость и ускорение расчитывается следующим образом:

  V[i+1] = V[i] + A[i] * dt + R[i] * dt^2 / 2                  (2)
  aAi+1] = A[i] + R[i] * dt                                    (3)

Для того, чтобы при вычислениях не использовать dt, dt^2 и dt^3 используются приведенные величины скорости, ускорения и рывка (фактически это конечные разности первого, второго и третьего порядка):

  v[i] = dx[i]  = V[i] * dt
  a[i] = d2x[i] = A[i] * dt^2
  r[i] = d3x[i] = R[i] * dt^3

При такой подмене формулы (1), (2) и (3) принимают упрощенный вид:

  x[i+1] = x[i] + v[i] + a[i] / 2 + r[i] / 6   (1')
  v[i+1] = v[i] + a[i] + r[i] / 2              (2')
  a[i+1] = a[i] + r[i]                         (3')

Не простой задачей является вычисление оптимального значения величины r[i] для каждого интервала разбиения. Оптимизация проводится по минимальному времени достижения заданного значения на выходе фильтра при движении с заданными ограничениями величин скорости, ускорения и рывка.

Пользователь задает следующие ограничения для работы фильтра:

  v_max        - максимальная скорость изменения выходного значения
  a_up_max     - максимальное ускорение разгона
  a_down_max   - максимальное ускорение торможения
  r_max        - максимальный рывок
  beta         - коэффициент запаса фильтра по рывку от 0.001 до 0.1
  x_min, x_mаx - минимальное и максимальное выходное значение

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

  V  = v_max * dt,        V  > 0
  Au = a_up_max   * dt^2, Au > 0
  Ad = a_down_max * dt^2, Ad > 0
  R  = r_max * dt^3,      R  > 0

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

Если "пора/нужно тормозить", то выбирается рывок для данной фазы оптимального торможения.

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

  • тормозной путь после такта с максимальным положительным рывком;
  • тормозной путь после такта с максимальным отрицательным рывком. Если заданная точка находится "в трубке", то рывок вычисляется пропорционально промахам. Если трубка "не дотягивает" или "перепрыгивает" заданное значение, то берется максимальный/минимальный рывок.

Понятие разгона и торможения

Если модуль скорости растет то это разгон (v[i] * a[i] > 0), если модуль скорости снижается, то это торможение (v[i] * a[i] < 0).

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

  trend = v[i] * a[i];
  if (trend < 0.)
  { // торможение (скорость и ускорение не равны нулю и имеют разный знак
    A = Ad; // максимальное приведенное ускорение торможения
  }
  else if (trend > 0. || a[i] != 0.)
  { // разгон (знаки скорости и ускорения совпадают
    // или есть ускорение при нулевой скорости)
    A = Au; // максимальное приведенное ускорение разгона
  }

Характерные стратегии управления

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

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

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

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

  2. Реверс Направление движения (знак скорости) не соответствует разнице заданного и текущего положения. Требуется изменить направление движения.

На реверсе - требуется достичь максимального ускорения торможения Ad до тех пор пока "неверная" скорость не достигнет нуля.

  1. Разгон Производится набор скорости (с максимально допустимым рывком и ускорением).

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

  Критическая скорость разгона:
  Vcrit = V - a[i]^2 / (2. * R),
  где
    V - максимально допустимая приведенная скорость (V > 0),
    R - максимально допустимый приведенный рывок (R > 0).

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

  if ((a[i] > 0. && v[i] >=  Vcrit) ||
      (a[i] < 0. && v[i] <= -Vcrit))
  { // текущая скорость достигла критической
    // с максимальным по модулю рывком снизить ускорение до нуля
  }
  1. Удержание Vmax При достижение максимальной скорости v[i] >= V или v[i] <= -V ускорение должно быть обнулено.

Таблица знаков

Nреж ds = y[i]-x[i] v a Режим
1 0 0 0 Покой
2 ~0 ~0 ~0 Малый ход
3 + + - Торможение
3 - - + Торможение
4 + - - Провал в реверс
4 - + + Провал в реверс
4 + - + Выход из реверса
4 - + - Выход из реверса
5 + + + Разгон
5 - - - Разгон
5 + + 0 Удержание +Vmax
5 - - 0 Удержание -Vmax

Примечание: На начальной фазе программного торможения из-за ограничения рывка знаки могут соответствовать режму "Разгон", пока ускорение не помянет знак на соответствующий снижению скорости.

Расчёт траекторий тормозного пути

При расчете тормозного пути УДОБНО запомнить знак скорости (фактически направление движения) и если скорость отрицательна поменять знак скорости и ускорения на противоположный, вычислить тормозной путь (время торможения) для положительного значения начальной скорости (что удобнее, меньше шансов совершить ошибку). Знак тормозного пути поменять на выходе, если знак скорости и ускорения менялся.

Скорость набираемая/сбрасываемая за время снижения ускорения разгона/торможения до нуля:

dV = a^2 / (2 * R),                                            (4)
где
  a - ускорение на начале интервала (начальное ускорение)
  R - рывок с которым ведется линейное снижение до нуля ускорения

Еще раз в рамочку, соотношение скорости и ускорения, которые могут обеспечить торможение с постоянным рывком R до полной остановки (v = a = 0):

2 * V * R = A^2
T = A / R

Время и тормозной путь после равномерного движения с постоянной скоростью

Если осуществляется движение с постоянной скоростью (ускорение равно нулю), то торможение может состоять из 2-х или 3-х фаз.

Если начальная скорость (по модулю) |v| <= Ad^2 / R, где Ad - максимальное ускорение торможения, R - максимальный рывок, то торможение состоит из 2-х "симметричных" фаз:

  • фаза линейного набора ускорения торможения до amax = sqrt(|v| * R), где v - скорость на начале интервала, R - максимальный рывок (скорость нарастания ускорения торможения)
  • фаза линейного снижения ускорения торможения с amax до нуля. Время обоих фаз одинаковое. Из-за сравнительно небольшой начальной скорости за время тормозного пути ускорение торможения не успевает достигнуть максимально допустимого значения Ad. Время каждой фазы t1 = t2 = |amax| / R = sqrt(|v| / R)
Время полного торможения T2 = t1 + t2 = 2 * sqrt(|v| / R).       (5)

Тормозной путь второй фазы можно легко посчитать, если представить движение в обратном времени с постоянным рывком R от нулевой скорости и ускорения до скорости |v|/2 и ускорения |amax| в течении t2:

s2 = 1/6 * R * t2^3 = 1/6 * |v| * sqrt(|v| / R) = 1/6 * amax^3 / R^2

Тормозной путь первой фазы можно представить как площадь под графиком скорости, а это площадь прямоугольника |v| * t1 за вычетом s2, т.е s1 = |v| * sqrt(|v| / R) - s2,

Общий тормозной путь:
S2 = s1 + s2 = |v| * sqrt(|v| / R)                               (6)

Если начальная скорость (по модулю) |v| > Ad^2 / R, то торможение состоит из 3-х фаз:

  • фаза линейного набора ускорения торможения до максимального Ad
  • фаза равноускоренного торможение с максимальным ускорением Ad
  • фаза линейного снижения ускорения торможения с Ad до нуля и сброс скорости

Время первой и третей фазы t1 = t3 = Ad / R. Время второй фазы можно посчитать как время сброса скорости с постоянным ускорением ad на величину |v| - 2 * V12 с ускорением Ad, где V12 = Ad^2 / (2 * R) - величины сброса скорости на 1-й и 3-й фазе, то есть: t2 = |v| / Ad - Ad / R.

Время полного торможения T3 = t1 + t2 + t3 = |v| / Ad + Ad / R    (7)

Тормозной путь первой фазы - как площадь под графиком функции скорости: s1 = |v| * t1 - s3 = |v| * Ad / R - s3

Тормозной путь второй фазы - площадь трапеции с основаниями v1 = |v| - Ad^2 / (2 * R), v2 = Ad^2 / (2 * R) и высотой t2 s2 = t2 * (v1 + v2) / 2 = (|v| / Ad - Ad / R) * |v| / 2

Суммарный тормозной путь всех 3-х фаз
S3 = s1 + s2 + s3 = |v| * (Ad / R + |v| / A) / 2                   (8)

Время и часть тормозного пути сброса ускорения разгона до нуля

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

Ts = |a| / R,                                                      (9)
где |a| - модуль текущего ускорения разгона, а часть тормозного пути составляет
Ss = |a| / R * (|v| + a^2 / (3 * R))                               (10)

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

Время и тормозной путь после начала торможения

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

Возможно торможение в 2 фазы:

  • увеличение ускорения торможения вплоть до максимального Ad,
  • сброс ускорения торможения до нуля и полный останов. Данные фазы аналогичны 2-м фазам торможения после равномерного движения с постоянной скоростью с особенностью в том, что первая фаза "усечена" по времени т.к. мы уже тормозим и набрали какое-то отрицательное по отношение к скорости ускорение.

Возможно торможение в 3 фазы:

  • увеличение ускорения торможения до максимального Ad,
  • торможение с максимальным ускорением Ad,
  • сброс ускорения торможения до нуля и полный останов. Данные фазы аналогичны 3-м фазам торможения после равномерного движения с постоянной скоростью с особенностью в том, что первая фаза "усечена" по времени т.к. мы уже тормозим и набрали какое-то отрицательное по отношение к скорости ускорение.

Возможна щекотливая ситуация (почему?) с "выбегом" по скорости, когда за время сбрасывания ускорения с максимальным рывком скорость успевает поменять знак, что приводит к торможению в 3-5 фаз с реверсом (изменением знака скорости):

  • сброс скорости до нуля, при этом ускорение до нуля не доходит
  • сброс ускорения до нуля
  • 2 или 3 фазы торможения после движения с постоянной скоростью (см. выше). За счет "выбега" (изменения знака скорости) торможение происходит "долго".

Ответ на вопрос "почему?": Во время движения с большой скоростью произошло крутое изменение заданного значения. Во время действия большого ускорения (ускорения разворота) скорость упала. Если скорость |V| < A^2/(2 * R), то не возможно с ограниченным рывком обнулить одновременно скорость и ускорение.

Если модуль скорости меньше, чем v1 = a^2 / (2 * R), то торможение будет с "выбегом" с большим числом фаз.

Если модуль скорости больше, чем v2 = (Ad^2 - a[i]^2 / 2) / R, то торможение в три фазы, в противном случае в две. Примечание:

v2 = dV1 + dV3 - пороговая скорость для 3-х фазного торможения
dV1 = (Ad^2 - a[i]^2) / (2 * R) - падение скорости по модулю за первую фазу
dV3 = Ad^2 / (2 * R) - скорость на входе в третью фазу

Первая фаза из трех (увеличиваем тормозное ускорение с а[i] до Ad):

t1 = (Ad - |a[i]|) / R                     - время ф.1     (12)
s1 = v * t1 + a * t1^2 / 2 - R * t1^3 / 6  - путь ф.1      (13)

Вторая фаза из трех (тормозим с постоянным ускорением Ad):

t2 = (|v| - v2) / Ad;                - время ф.2       (14)
s2 = (|v| + a^2 / (2 * R)) * t2 / 2  - путь ф.2        (15)

Примечаение: s2 - это площадь трапеции с основаниями: Va = |v| - dV1, Vb = dV3 и высотой h=t2. (16) s2 = (Va + Vb) * h / 2 (17)

Третья фаза из трех (обнуляем скорость и ускорение с максимальным рывком):

t3 = Ad / R        - время фазы 3                  (18)
s3 = R * t3^3 / 6  - путь фазы 3                   (19)

Если торможение в две фазы (v <= v2), то вычисляем:

Amax = sqrt(R * |v| + a^2 / 2) - максимальное по модулю ускорения (20)

Первая фаза из двух (увеличиваем тормозное ускорения с а[i] до Amax):

t1 = (Amax - |a|) / R                       - время первой фазы  (21)
s1 = v * t1 + a * t1^2 / 2 - R * t1^3 / 6   - путь первой фазы   (22)

Вторая фаза из двух (обнуляем скорость и ускорение с максимальным рывком):

t2 = Amax / R         - время второй фазы                     (23)
s2 = R * t2^3 / 6.    - путь второй фазы                      (24)

Если торможение с реверсом (v <= v1 = a^2 / (2 * R)), то вычисляем:

  // фаза 1 (сбрасываем ускорение до нуля)
  t1 = |a| / R
  s1 = v * t1 + a * t1^2 / 2. + R * t1^3 / 6.;

  // теперь задача сводится к торможению после равномерного движения
  // в две или три фазы
  v = v1 - |v|; // считаем, что остаточная скорость положительна для удобства

  if (v <= Ad * Ad / R)
  { // торможение состоит из 3-х фаз
    t2 = 2 * sqrt(v / R); // время фазы 2 и 3
    s2 = -dt * v / 2.;  // тормозной путь ф2 и ф3
  }
  else
  { // торможение состоит из 4-х фаз
    t2  = v / Ad + Ad / R; // время фаз 2, 3 и 4
    s23  = -v * t2 / 2.; // тормозной путь ф2..ф4
  }

  s = s1 + s2;
  t = t1 + t2;
}

Обзор основных функций

  • rfilt_init() - функция первичной инициализации компонента rfilt_t
  • rfilt_tune() - обновление параметров фильтра «на лету»
  • rfilt_step() - основная рабочая функция

Обзор вспомогательных (внутренних) функций

  • rfilt_limit_r() - функция ограничения рывка с учётом текущей скорости, ускорения и заданных при инициализации параметров
  • rfilt_s() - основная идейная функций вычисления тормозного пути и времени
  • rfilt_test() - функция оценки возможности «малого хода»
  • rfilt_r() - функция итеративного вычисления рывка для следующего такта