AnyMath 文档
Notebook

调节器的自动调节

导言

为控制系统设置调节器是一项经典任务,作为TAU课程的一部分进行研究。 但是,本课程中研究的所有方法都需要花费大量时间。 在本出版物中,我们将介绍优化算法的应用,以加快和自动化控制设置。

我们将使用stepfun模型进行演示。:

image.png

筹备工作

我们将需要两个库:ControlSystemBase和Optim。 让我们安装它们:

In [ ]:
import Pkg
Pkg.add(["ControlSystemsBase","Optim"])
   Resolving package versions...
   Installed ControlSystems ─ v1.15.4
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
     Project No packages added to or removed from `~/.project/Project.toml`
    Manifest No packages added to or removed from `~/.project/Manifest.toml`

现在,让我们创建一个函数来模拟模型。 仿真结果将从ControlSystemBase传递给stepinfo()函数。 该函数计算过渡过程的特征,并生成一个可以可视化的StepInfo类型对象。 我们将返回这样的对象:

In [ ]:
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
Out[0]:
sim_parameterized (generic function with 1 method)

开始行动

让我们来看看系统如何使用控制器的默认设置。:

In [ ]:
    engee.set_param!("stepfun/reg","P"=>1.0)
    engee.set_param!("stepfun/reg","I"=>1.0)
    si = sim_parameterized()
    ref = plot(si)
    display(ref)
No description has been provided for this image

让我们通过遍历参数来探索系统

迭代参数是研究参数对系统行为的影响的一种相当常见的方法。 这种方法的缺点是遍历参数需要很长时间。 即使我们并行搜索,我们也会等待大样本上的结果令人无法接受的长时间。 如果参数变化很大,分析的质量就会下降。 但即使这可以帮助我们的任务。 让我们看看调节器积分环节中增益因子的变化会产生什么影响。:

In [ ]:
par_variation_l = 10;
param = collect(range(0.5,4.5,par_variation_l));
In [ ]:
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
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.

让我们检查遍历参数的结果

探索任何数据的最简单方法是通过他们的眼睛来看待它。 让我们来看看过冲(overshoot)、上升时间(rise_time)和设定点时间(setting_time)图。

In [ ]:
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))
Out[0]:
No description has been provided for this image

这里重要的不是定量结果,而是系统的行为方式。 我们看到,随着积分环节的增益增加,过冲和设定点时间也会增加。 因此,我们可以说期望的最佳系数应该小于1.5。 如果我们对起始环节进行这样的分析,那么我们也将能够对其加固系数提出要求。

自动调整调节器参数

我们将使用优化方法自动调整调节器。

要应用优化,您需要创建一个目标函数,我们将寻找最小值。 让我们使用StepInfo对象从结果中获取过渡过程的特征,函数将返回这些特征乘以权重的总和。 权重是根据过渡过程的要求分配的. 假设我们希望减少设定点时间,同时最大限度地减少过冲,但上升时间对我们来说并不重要。 然后,我们的目标函数将采取以下形式:

In [ ]:
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
Out[0]:
cost_fun (generic function with 1 method)

在您可以开始优化和调整控制器之前,您需要调整优化本身。 我们想限制对参数的搜索,因为我们发现参数的值小于1.5。 它们的下界将是0.5。 接下来,我们需要限制算法本身。

优化任务将同时使用两种算法-Fminbox作为"外部"算法,梯度下降作为"内部"算法。 在外部算法的每个步骤中,都会运行内部算法的几个步骤,如果我们不限制两种算法的步数,那么优化将花费很长时间甚至冻结。 有关设置的更详细说明,请参阅[文档](https://engee.com/helpcenter/stable/ru-en/julia/Optim/user/config.html )。

完成所有设置后,我们将开始优化。:

In [ ]:
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)
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
Fminbox
-------
Initial mu = 0.0

Fminbox iteration 1
-------------------
Calling inner optimizer with mu = 0.0

(numbers below include barrier contribution)
Iter     Function value   Gradient norm 
     0     2.248455e+02     8.399782e+01
 * time: 0.037448883056640625
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
     1     5.645585e+01     3.724740e+01
 * time: 139.6843729019165
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
     2     5.495090e+01     8.098034e+01
 * time: 207.34265685081482
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
     3     5.494912e+01     4.866916e+02
 * time: 362.8312578201294
     4     5.494560e+01     7.379368e+01
 * time: 379.5791518688202
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
Exiting inner optimizer with x = [1.340378007208218, 0.5002145746699308]
Current distance to box: 0.000214575
Decreasing barrier term μ.
Out[0]:
 * Status: success

 * Candidate solution
    Final objective value:     5.478000e+01

 * Found with
    Algorithm:     Fminbox with Gradient Descent

 * Convergence measures
    |x - x'|               = 5.00e-01 ≰ 0.0e+00
    |x - x'|/|x'|          = 3.73e-01 ≰ 0.0e+00
    |f(x) - f(x')|         = 1.70e+02 ≰ 1.0e-05
    |f(x) - f(x')|/|f(x')| = 3.10e+00 ≰ 1.0e-02
    |g(x)|                 = 0.00e+00 ≤ 1.0e-08

 * Work counters
    Seconds run:   401  (vs limit Inf)
    Iterations:    1
    f(x) calls:    23
    ∇f(x) calls:   23
    ∇f(x)ᵀv calls: 0

发现了以下值。

In [ ]:
optimal_params = Optim.minimizer(res)
Out[0]:
2-element Vector{Float64}:
 1.340378007208218
 0.5002145746699308

让我们为初始稳压器和配置稳压器构建瞬态图。:

In [ ]:
    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))
Out[0]:
No description has been provided for this image

结论

我们研究了自动调整调节器的过程。 通过迭代参数,获得调节器的参数所在的边界,然后找到它们的确切值。