Моделирование систем управления на примере ПИД-регулятора
В этом примере мы рассмотрим управление устойчивым объектом второго порядка c помощью ПИД-регулятора в среде Engee. Дополнительно будет проведено сравнение результатов моделирования в среде Engee с результатами моделирования в Simulink.
Исследуемая система управления находится в модели pid_controls_tf_stable.engee:
Подготовка и настройка
Подключим необходимые библиотеки и запустим Simulink:
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
Для запуска модели в Engee нам потребуется выполнить следующую последовательность действий:
-
Загрузить модель с помощью API Engee
-
Запустить симуляцию с помощью того же API
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 )
Dict{String, DataFrames.DataFrame} with 2 entries:
"out" => 200001×2 DataFrame…
"ref" => 200001×2 DataFrame…
Извлечем данные для их анализа:
PID_res_e_t = results["out"].time;
PID_res_e_d = results["out"].value;
Построим график для результатов моделирования:
plot(PID_res_e_t , PID_res_e_d, legend = false)
plot!(title = "Результаты моделирования в Engee", ylabel = "Отклик", xlabel="Время, c")
Запуск моделирования в Simulink
Для связи Engee и MATLAB используется библиотека MATLAB.jl
. За вызов скриптов и команд MATLAB отвечает команда mat
. Для запуска симуляции используем команду sim
:
mat"cd $(@__DIR__)"
mat"out = sim('pid_controls_tf_stable');";
Для того что бы загрузить результаты симуляции в Engee, сначала требуется разобрать объект out
класса Simulink.SimulationData
(и не забыть удалить ненужные данные!):
mat""" res = out.yout;
sig = res.getElement(1);
assignin('base',sig.Name,sig.Values)
clear res sig
"""
Посмотрим на результаты симуляции в Simulink:
pid_values = mat"traj.Data";
pid_times = mat"traj.Time";
plot(pid_times, pid_values, legend = false)
plot!(title = "Результаты моделирования в Simulink", ylabel = "Отклик", xlabel="Время, c")
Сравнение результатов моделирования
Сравним результаты симуляции в Engee и Simulink. Сначала наложим графики результатов друг на друга:
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")
Затем, вычислим расхождение между результатами моделирования. Для этого мы будем использовать как абсолютную, так и относительные средние погрешности вычислений, а также корреляцию:
println("Корреляция: ", cor(pid_values, PID_res_e_d))
Корреляция: 1.0
Корреляция близка к единице, тоесть два вектора, характеризующие результаты в Simulink и Engee имеют очень сильную статистическую связь, иначе говоря они очень близки по значениям, теперь рассчитаем погрешности.
Также для наглядности построим график абсолютной погрешности для визуализации погрешнасти за всё время моделирования.
difference = pid_values - PID_res_e_d;
plot(difference)
println("Средняя абсолютная погрешность вычислений: ", abs(mean(difference)));
Средняя абсолютная погрешность вычислений: 1.9695099104476718e-17
println("Средняя относительная погрешность вычислений: ", abs(mean(filter(!isnan,(difference)./pid_values)))*100, "%:");
Средняя относительная погрешность вычислений: 1.81497090313774e-15%:
Как мы видем погрешность вычислений крайне мала.