Документация Engee

Итеративное обучающее управление

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

Алгоритм

Итерационная схема ИОУ обычно выглядит следующим образом (существует множество вариантов) при итерации ИОУ :

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

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

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

Модель системы и регулятор

using ControlSystemsBase, Plots

function double_mass_model(;
                Jm = 1,   # инерция двигателя
                Jl = 1,   # инерция груза
                k  = 100, # жесткость
                c0 = 1,   # демпфирование двигателя
                c1 = 1,   # демпфирование передачи
                c2 = 1,   # демпфирование груза
)

    A = [
        0.0 1 0 0
        -k/Jm -(c1 + c0)/Jm k/Jm c1/Jm
        0 0 0 1
        k/Jl c1/Jl -k/Jl -(c1 + c2)/Jl
    ]
    B = [0, 1/Jm, 0, 0]
    C = [1 0 0 0]
    ss(A, B, C, 0)
end

G    = double_mass_model(Jl = 1)
Gact = double_mass_model(Jl = 1.5) # груз на 50 % больше, чем в модели

bodeplot([G, Gact], lab=["G model" "G actual"], plotphase=false)

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

C  = pid(10, 1, 1, form = :series) * tf(1, [0.02, 1])
Ts = 0.02 # Интервал выборки
Gc = c2d(feedback(G*C), Ts)       |> tf
Gcact = c2d(feedback(Gact*C), Ts) |> tf
plot(step(Gc, 10), title="Closed-loop step response", lab="model")
plot!(step(Gcact, 10), lab="actual")

Заданная траектория

Далее мы проектируем заданную траекторию и моделируем реальную динамику замкнутого контура.

T = 3pi    # Длительность
t = 0:Ts:T # Вектор времени
function funnysin(x)
    x = sin(x)
    s,a = sign(x), abs(x)
    s*((a + 0.01)^0.2 - 0.01^0.2)
end
r = funnysin.(t)' |> Array # Эталонный сигнал

res = lsim(Gcact, r, t)
plot(res, plotu=true, layout=1, sp=1, title="Closed-loop simulation with actual dynamics", lab=["y" "r"])

Производительность низкая…​ Используйте ИОУ!

Акаузальная фильтрация

Для корректной работы ИОУ определим две вспомогательные функции. Одну, которая применяет нуль-фазовый фильтр для фильтрации как вперед, так и назад (filtfilt). Это возможно, поскольку ИОУ работает с сигналами в автономном режиме между итерациями в схеме ИОУ. Мы также определим специальную функцию lsim, которая работает с некаузальными системами, позволяя «заглядывать» в будущее. Это, как правило, значительно повышает производительность ИОУ, что опять же возможно, поскольку ИОУ работает с заранее записанными сигналами.

function lsim_zerophase(G, u, args...; kwargs...)
    res = lsim(G, u[:, end:-1:1], args...; kwargs...)
    lsim(G, res.y[:, end:-1:1], args...; kwargs...).y
end

function lsim_noncausal(L::LTISystem{<:Discrete}, u, args...; kwargs...)
    np = length(denpoly(L)[])
    nz = length(numpoly(L)[])
    zeroexcess = nz-np
    if zeroexcess <= 0
        return lsim(L, u, args...; kwargs...)
    end
    integrators = tf(1, [1, 0], L.Ts)^zeroexcess
    res = lsim(L*integrators, u, args...; kwargs...)
    res.y[1:end-zeroexcess] .= res.y[1+zeroexcess:end]
    res.y
end
nothing # скрыть

Выбор фильтров

Следующим шагом является определение фильтров ИОУ и .

Фильтр выступает в роли частотно-зависимого шага. Для того чтобы процедура выполнялась с меньшим шагом, достаточно масштабировать по константе < 1. При уменьшении масштаба процесс обучения замедляется, но становится более устойчивым. Эвристическим выбором является некоторая форма масштабированного упреждения, например , где  — число выборок упреждения. В подходе на основе модели может использоваться некоторая форма инверсии модели системы, которую мы и будем использовать в данном случае. [^нелинейные]

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

z = tf("z", Ts)
Q = c2d(tf(1, [0.05, 1]), Ts)
# L = 0,9z^1 # Более консервативный и эвристический вариант
L = 0.5inv(Gc) # Уменьшение коэффициента масштабирования, чтобы делать меньшие шаги

Теорема Норрлофа гласит, что для сходимости итераций ИОУ необходимо, чтобы выполнялось условие , в чем мы можем убедиться, посмотрев на кривые Боде двух сторон неравенства

bodeplot([inv(Q), (1 - L*Gc)], plotphase=false, lab=["Stability boundary \$Q^{-1}\$" "\$1 - LG\$"])
bodeplot!((1 - L*Gcact), plotphase=false, lab="\$1 - LG\$ actual")

Выше мы построили эту кривую и для реальной динамики. Конечно, это невозможно в реальном сценарии, где эта величина неизвестна, но можно построить график для нескольких правдоподобных моделей и убедиться, что все они находятся ниже границы. Руководство по этому вопросу см. на странице Моделирование неопределенности с помощью RobustAndOptimalControl.jl. Если посмотреть на условие устойчивости, то становится очевидным, как малая величина в условиях неопределенности модели благоприятно сказывается на надежности схемы ИОУ.

Итерация ИОУ

Следующим шагом является реализация схемы ИОУ и ее выполнение:

function ilc(Gc, Q, L)
    a = zero(r) # Сигнал регулировки ИОУ начинается с 0
    fig = plot(t, vec(r), sp=1, layout=(3,1), l=(:black, 3), lab="Ref")
    for iter = 1:5
        ra = r .+ a
        res = lsim(Gc, ra, t) # Моделирование системы, заменяемое реальным экспериментом при работе в реальном процессе
        y = res.y             # Отклик системы
        e = r .- y            # Погрешность
        Le = lsim_noncausal(L, e, t)
        a  = lsim_zerophase(Q, a + Le, t) # Обновление корректировки ИОУ

        plot!(res, plotu=true, sp=[1 2], title=["Output \$y(t)\$" "Adjusted reference \$r + a\$"], lab="Iter $iter", c=iter)
        plot!(e[:], sp=3, title="Tracking error \$e(t)\$", lab="err: $(round(sum(abs2, e), digits=2))", c=iter)
    end
    fig
end
ilc(Gc, Q, L)

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

Как это работает в «реальной» динамике?

ilc(Gcact, Q, L)

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

Сводка

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

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