Идентификация модели следящего гидропривода
Линеаризация модели следящего гидропривода
В примере демонстрируется линеаризация динамической модели следящего гидропривода с обратной связью по положению. При этом, для обеспечения точности линеаризации, она осуществляется в два этапа: при помощи функций subspaceid и newpem.
Описание модели
Объект линеаризации – система управления гидроцилиндром с обратной связью по положению. Она состоит из контроллера, функции задержки сигнала, и физической подсистемы объекта управления – гидравлического актуатора.
В качестве задающего сигнала на вход системы управления подается произвольный закон перемещения гидроцилиндра, повторение которого на выходном звене гидроцилиндра должна обеспечить гидравлическая подсистема актуатора, управление перемещением которого осуществляется при помощи переключения однопоточного распределителя из нормально открытого в закрытое положение по сигналу от управляющей системы.

Построим графики входного и выходного сигналов следящего гидропривода.
Pkg.add(["ControlSystemIdentification", "ControlSystems"])
gr()
modelName = "ServoHydraulicLinearization"
if !(modelName in [m.name for m in engee.get_all_models()]) engee.load( "$(@__DIR__)/$(modelName).engee"); end;
data = engee.run( modelName )
u=WorkspaceArray{Float64}("ServoHydraulicLinearization/u")
input=WorkspaceArray{Float64}("ServoHydraulicLinearization/input")
displacement=WorkspaceArray{Float64}("ServoHydraulicLinearization/displacement")
PressureSideA=WorkspaceArray{Float64}("ServoHydraulicLinearization/Actuator/PressureSideA")
PressureSideB=WorkspaceArray{Float64}("ServoHydraulicLinearization/Actuator/PressureSideB")
ValveOpening=WorkspaceArray{Float64}("ServoHydraulicLinearization/Actuator/1WayDCV/ValveOpening")
using ControlSystems, ControlSystemIdentification
using ControlSystemIdentification: Sec
Ts=0.001
# Преобразуем WorkspaceArray в структуры данных
df_u = collect(u)
df_input = collect(input)
df_displacement = collect(displacement)
# Извлекаем чистые векторы времени и значений сигналов
time_vector = df_input.time # Время (оно общее для графиков)
input_values = df_input.value # Значения входного сигнала
disp_values = df_displacement.value # Значения смещения
plot(time_vector, [input_values disp_values], label=["input" "displacement"])
Линеаризация физической модели гидропривода
Создадим передаточную функцию модели гидропривода при помощи функций subspaceid (преобразование модель пространства состояний) и newpem (PEM, метод ошибок прогнозирования) для повышения точности результатов линеаризации. При этом результат subspaceid будет использоваться как начальное приближение для метода PEM.
Для линеаризации выберем время t>2.5 с, так как в этот момент распределитель гарантированно активирован. Для этого найдем первый временной шаг модели по истечении времени симуляции 2.5 с, который и будет являться целевой точкой линеаризации.
# Создадим объект Identification Data
# iddata требует строго одномерные векторы типа Float64
u_raw = vec(Float64.(df_u.value))
y_raw = vec(Float64.(df_displacement.value))
# Восстановление временной сетки по шагу расчета
t_raw = range(0, step=Ts, length=length(u_raw))
# Нахождение первой точки стационарного режима после t > 2.5 с
idx_target = findfirst(t -> t > 2.5, t_raw)
if idx_target === nothing
error("Время симуляции в WorkspaceArray не достигло 2.5 секунд!")
end
u_base = u_raw[idx_target]
y_base = y_raw[idx_target]
# Центрирование динамических процессов (линеаризация в отклонениях)
u_delta = u_raw .- u_base
y_delta = y_raw .- y_base
d=iddata(y_delta, u_delta, Ts)
d_filtered = detrend(d) # Фильтруем сверхнизкие частоты
# Идентифицируем систему при помощи subspaceid, предполагаемый порядок системы 4
nx = 4
sys_sub = subspaceid(d_filtered, nx; focus = :prediction)
# Уточним полученную модель системы при помощи функции newpem
sys_pem, _ = ControlSystemIdentification.newpem(d_filtered, nx; sys0 = sys_sub.sys, focus = :simulation)
Сборка разомкнутой системы
Соберем модель системы управления согласно схеме, указанной в описании
Controller=tf([-0.5],[0.001,1.0]) # Передаточная функция контроллера
G_actuator_continuous = d2c(tf(sys_pem.sys)) # Преобразованная в continuous передаточная функция гидравлической подсистемы
Delay_Scheme = ControlSystems.pade(0.0015, 2) # Задержка сигнала
# Соберем передаточную функцию разомкнутой системы
G_raw_loop = G_actuator_continuous * Delay_Scheme * Controller # Передаточная функция разомкнутой системы
# Распределитель управляет сливом (подается сигнал на распределитель - распределитель закрывается - цилиндр перемещается вперед, поэтому проверяем dcgain на знак)
if dcgain(G_raw_loop)[1] < 0
G_open_loop = -1.0 * G_raw_loop
else
G_open_loop = G_raw_loop
end
Построение ЛАЧХ/ЛФЧХ (Диаграммы Боде)
# Ограничиваем частотный диапазон от 10^-3 до 10^5 Гц
f_Hz = 10 .^ range(-3, 5, length=1000)
w_rad = 2 * π * f_Hz
# Построение графика
fig = bodeplot(
G_open_loop,
w_rad;
hz = true, # Шкала частот в Гц
plotphase = true, # Отображать фазочастотную характеристику
title = ["Частотная характеристика гидропривода (Engee)" ""],
label = "Идентифицированная модель PEM (с задержкой 1.5*Ts)",
linecolor = :blue,
linewidth = 1.5,
layout = (2, 1),
size = (850, 550)
)

