Engee 文档
Notebook

以 PID 控制器为例建立控制系统模型

在本示例中,我们将考虑在Engee环境下使用 PID 控制器控制一个稳定的二阶对象。此外,Engee 仿真的结果将与Simulink仿真的结果进行比较。

所研究的控制系统为pid_controls_tf_stable.engee模型:

engee_pid.png

准备和设置

连接必要的库并启动 Simulink:

In [ ]:
Pkg.add(["Statistics"])
In [ ]:
using Plots
using MATLAB
using Statistics
gr( fmt=:png )

mat"start_simulink"
>> [Warning: MATLAB has disabled some advanced graphics rendering features by
switching to software OpenGL. For more information, click <a
href="matlab:opengl('problems')">here</a>.] 

在 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]:
Dict{String, DataFrames.DataFrame} with 2 entries:
  "out" => 200001×2 DataFrame…
  "ref" => 200001×2 DataFrame

让我们提取数据进行分析:

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]:
No description has been provided for this image

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]:
No description has been provided for this image

模拟结果比较

让我们比较一下EngeeSimulink的仿真结果。首先,让我们将结果图相互叠加:

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]:
No description has been provided for this image

然后,我们将计算模拟结果之间的差异。为此,我们将使用绝对和相对平均计算误差以及相关性:

In [ ]:
println("Корреляция: ", cor(pid_values, PID_res_e_d))
Корреляция: 1.0

相关性接近统一,即 Simulink 和 Engee 中表征结果的两个向量具有非常强的统计关系,换句话说,它们的值非常接近。

另外,为了清楚起见,让我们绘制绝对误差图,以直观显示整个仿真时间内的误差。

In [ ]:
difference = pid_values - PID_res_e_d;
In [ ]:
plot(difference)
Out[0]:
No description has been provided for this image
In [ ]:
println("Средняя абсолютная погрешность вычислений: ", abs(mean(difference)));
Средняя абсолютная погрешность вычислений: 1.9695099104476718e-17
In [ ]:
println("Средняя относительная погрешность вычислений: ", abs(mean(filter(!isnan,(difference)./pid_values)))*100, "%:"); 
Средняя относительная погрешность вычислений: 1.81497090313774e-15%:

我们可以看到,计算误差非常小。

结论

在本例中,我们探讨了在Engee环境中使用 PID 控制器控制稳定的二阶对象的可能性。我们还看到,Engee 的精度与Matlab相当。

示例中使用的块