Автоматическая настройка регулятора
Автоматизированная настройка регулятора
Введение
Настройка регулятора для системы управления это классическая задача, которую изучают в рамках курса по ТАУ. Однако все методы, которые изучаются в рамках этого курса занимают много времени. В этой публикации мы рассмотрим применение алгоритмов оптимизации для ускорения и автоматизации настройки регуляторов.
Для демонстрации будем использовать модель stepfun:
Подготовительные работы
Нам понадобятся две библиотеки: ControlSystemBase и Optim. Установим их:
import Pkg
Pkg.add(["ControlSystemsBase","Optim"])
Теперь, создадим функцию для симуляции модели. Результаты симуляции будем передавать в функцию stepinfo() из ControlSystemBase. Эта функция рассчитывает характеристики переходного процесса и порождает объект типа StepInfo, который можно визуализировать. Будем возвращать такой объект:
gr()
engee.load(joinpath(@__DIR__,"stepfun.engee"))
using ControlSystemsBase
function sim_parameterized()
simres = engee.run("stepfun")
y = collect(simres["y"]);
u = collect(simres["u"]);
yv = reshape(y.value,(1,length(y.value)))
rt = ControlSystemsBase.SimResult(yv,y.time,yv,u.value,ss(tf([1.0],[1.0, 0.0])))
si = stepinfo(rt)
return si
end
Начало работы
Посмотрим на то, как система работает с настройками регулятора по умолчанию:
engee.set_param!("stepfun/reg","P"=>1.0)
engee.set_param!("stepfun/reg","I"=>1.0)
si = sim_parameterized()
ref = plot(si)
display(ref)
Исследуем систему с помощью перебора параметров
Перебор параметров - достаточно распространенный метод для исследования влияния параметра на поведение системы. Минусом данного метода является то, что перебирать параметры - долго. Даже если мы распараллелим перебор, то на больших выборках мы будем ждать результата непозволительно долго. А если параметр будет варьироваться большими скачками, то качество анализа упадет. Но даже это может помочь в нашей задаче. Давайте посмотрим какой эффект даст изменение коэффициента усиления в интегрирующем звене регулятора:
par_variation_l = 10;
param = collect(range(0.5,4.5,par_variation_l));
using ControlSystemsBase
#mySystem = feedback(tf([1.0],[1.0,1.0])*tf([1.0],[1.0, 0.0]))
K = 1.0
overshoot = zeros(par_variation_l);
setting_time = zeros(par_variation_l);
rise_time = zeros(par_variation_l);
for i in 1:par_variation_l
engee.set_param!("stepfun/reg","I"=>"$(param[i])")
si = sim_parameterized()
overshoot[i] = si.overshoot;
setting_time[i] = si.settlingtime;
rise_time[i] = si.risetime;
end
Исследуем результаты перебора параметров
Самый простой способ исследовать какие-либо данные - посмотреть их глазами. Давайте посмотрим на графики перерегулирования (overshoot), времени нарастания (rise_time) и времени уставки (setting_time)
p1 = plot(param, overshoot,label="overshoot")
p2 = plot(param,rise_time,color=:red,label="rise_time")
p3 = plot(param,setting_time,color=:green,label="setting_time")
plot(p1,p2,p3,layout=(3,1))
Здесь нам важны не количественные результаты, а то как ведет себя система. Мы видим, что по мере увеличения коэффициента усиления в интегрирующем звене, нарастает перерегулирование и время уставки. Таким образом мы можем сказать, что искомый оптимальный коэффициента должен быть меньше 1,5. Если мы проведем такой анализ для усилиющего звена, то мы тоже сможем выдвинуть требование к его коэфициенту усиления.
Автоматическая настройка параметров регулятора
Для автоматической настройки регулятора будем использовать методы оптимизации.
Для применения оптимизации нужно создать целевую функцию, у которой будем искать минимум. Воспользуемся объектом StepInfo, чтобы достать из результатов характеристики переходного процесса, а функция будет возвращать сумму этих характеристик, помноженную на веса. Веса назначаются исходя из требований к переходному процессу. Допустим, нам хочется сократить время уставки, при этом минимизировать перерегулирование, а время нарастания нам не важно. Тогда, наша целевая функция примет вид:
function cost_fun(p::Vector{Float64})
engee.set_param!("stepfun/reg","P"=>p[1])
engee.set_param!("stepfun/reg","I"=>p[2])
si = sim_parameterized()
return 2*si.overshoot + 0.5*si.risetime + 10*si.settlingtime
end
Прежде чем запускать оптимизацию и настраивать регулятор, требуется настроить саму оптимизацию. Мы хотим ограничить поиск параметров, так как выяснили что параметры иметь значения меньше 1.5. А нижняя граница у них будет 0.5. Далее, требуется ограничить сам алгоритм.
Задача оптимизации будет использовать сразу два алгоритма - Fminbox как "внешний", и градиентный спуск как "внутренний". На каждом шаге внешнего алгоритма будет запускаться несколько шагов внутреннего алгоритма, и если мы не ограничим количество шагов обоих алгоритмов, то оптимизация займет много времени или вообще зависнет. Для более подробного описания настроек обратитесь к документации.
После выполнения всех настроек, запустим оптимизацию:
using Optim
lowbound = [0.5, 0.5];
highbound = [1.5, 1.5];
opt = Optim.Options(
iterations = 5,
outer_iterations = 25,
f_abstol = 1e-5,
f_reltol = 1e-2,
show_trace = true);
res = optimize(cost_fun, lowbound, highbound, [1.0, 1.0], Fminbox(GradientDescent()),opt)
Были найдены следующие значения.
optimal_params = Optim.minimizer(res)
Построим графики переходных процессов для исходного и настроенного регуляторов:
engee.set_param!("stepfun/reg","P"=>optimal_params[1])
engee.set_param!("stepfun/reg","I"=>optimal_params[2])
si = sim_parameterized()
fin = plot(si)
plot(ref,fin,layout=(2,1))
Выводы
Мы посмотрели на процесс автоматизации настройки регулятора. При помощи перебора параметров были получены границы, внутри которых лежат параметры регулятора, а затем были найдены их точные значения.


