以 PID 控制器为例建立控制系统模型¶
在本示例中,我们将考虑在Engee环境下使用 PID 控制器控制一个稳定的二阶对象。此外,Engee 仿真的结果将与Simulink仿真的结果进行比较。
所研究的控制系统为pid_controls_tf_stable.engee模型:
准备和设置¶
连接必要的库并启动 Simulink:
In [ ]:
Pkg.add(["Statistics"])
In [ ]:
using Plots
using MATLAB
using Statistics
gr( fmt=:png )
mat"start_simulink"
在 Engee 中建模¶
要在恩吉中运行一个模型,我们需要执行以下一系列操作: 1.使用 Engee API 加载模型 2.使用相同的应用程序接口运行模拟
In [ ]:
modelName = "pid_controls_tf_stable";
PID_model = modelName in [m.name for m in engee.get_all_models()] ? engee.open( modelName ) : engee.load( "$(@__DIR__)/$(modelName).engee");
results = engee.run( modelName )
Out[0]:
让我们提取数据进行分析:
In [ ]:
PID_res_e_t = results["out"].time;
PID_res_e_d = results["out"].value;
为建模结果绘制图表:
In [ ]:
plot(PID_res_e_t , PID_res_e_d, legend = false)
plot!(title = "Результаты моделирования в Engee", ylabel = "Отклик", xlabel="Время, c")
Out[0]:
在 Simulink 中运行模拟¶
MATLAB.jl
库用于连接 Engee 和 MATLAB。mat
命令负责调用 MATLAB 脚本和命令。我们使用sim
命令运行仿真:
In [ ]:
mat"cd $(@__DIR__)"
mat"out = sim('pid_controls_tf_stable');";
为了将模拟结果加载到 Engee 中,我们首先需要反汇编Simulink.SimulationData
类的out
对象(别忘了删除不必要的数据!):
In [ ]:
mat""" res = out.yout;
sig = res.getElement(1);
assignin('base',sig.Name,sig.Values)
clear res sig
"""
让我们来看看Simulink中的仿真结果:
In [ ]:
pid_values = mat"traj.Data";
pid_times = mat"traj.Time";
plot(pid_times, pid_values, legend = false)
plot!(title = "Результаты моделирования в Simulink", ylabel = "Отклик", xlabel="Время, c")
Out[0]:
模拟结果比较¶
让我们比较一下Engee和Simulink的仿真结果。首先,让我们将结果图相互叠加:
In [ ]:
plot(PID_res_e_t,PID_res_e_d, label = "Engee")
plot!(title = "Сравнение результатов моделирования")
plot!(pid_times, pid_values, label = "Simulink")
plot!(legend = :outertopright,ylabel = "Отклик", xlabel="Время, c")
Out[0]:
然后,我们将计算模拟结果之间的差异。为此,我们将使用绝对和相对平均计算误差以及相关性:
In [ ]:
println("Корреляция: ", cor(pid_values, PID_res_e_d))
相关性接近统一,即 Simulink 和 Engee 中表征结果的两个向量具有非常强的统计关系,换句话说,它们的值非常接近。
另外,为了清楚起见,让我们绘制绝对误差图,以直观显示整个仿真时间内的误差。
In [ ]:
difference = pid_values - PID_res_e_d;
In [ ]:
plot(difference)
Out[0]:
In [ ]:
println("Средняя абсолютная погрешность вычислений: ", abs(mean(difference)));
In [ ]:
println("Средняя относительная погрешность вычислений: ", abs(mean(filter(!isnan,(difference)./pid_values)))*100, "%:");
我们可以看到,计算误差非常小。
结论¶
在本例中,我们探讨了在Engee环境中使用 PID 控制器控制稳定的二阶对象的可能性。我们还看到,Engee 的精度与Matlab相当。