Функции: универсальные функции
На этой странице приводится документация по функциям, универсальным для типов SimModel
, StateEstimator
и PredictiveController
.
Установка ограничения
#
ModelPredictiveControl.setconstraint!
— Function
setconstraint!(estim::MovingHorizonEstimator; <keyword arguments>) -> estim
Задает параметры ограничений MovingHorizonEstimator
estim
.
Поддерживает как мягкие, так и жесткие ограничения для оценочного состояния , шума процесса и шума датчика :
а также для . Все параметры ограничений представляют собой вектор. Используйте значения ±Inf
, если ограничения нет. Параметры мягкости ограничений , также называемые равным значением релаксации, — это неотрицательные значения, которые определяют мягкость соответствующей границы. Используйте значения 0.0
для жестких ограничений (по умолчанию для всех). Обратите внимание, что ограничение оценочного шума датчика равносильно ограничению порождающего члена, так как . В расширенной справке приводятся подробные сведения о расширении модели и динамических ограничениях.
Аргументы
Ограничения по умолчанию упоминаются здесь для наглядности, однако если опустить именованный аргумент, ему не будет снова присвоено значение по умолчанию (значения по умолчанию задаются только в момент создания). То же самое касается |
-
estim::MovingHorizonEstimator
: средство оценки подвижного горизонта для задания ограничений -
x̂min=fill(-Inf,nx̂)
/x̂max=fill(+Inf,nx̂)
: оценочная граница состояния -
ŵmin=fill(-Inf,nx̂)
/ŵmax=fill(+Inf,nx̂)
: оценочная граница шума процесса -
v̂min=fill(-Inf,nym)
/v̂max=fill(+Inf,nym)
: оценочная граница шума датчика -
c_x̂min=fill(0.0,nx̂)
/c_x̂max=fill(0.0,nx̂)
:x̂min
/x̂max
вес мягкости -
c_ŵmin=fill(0.0,nx̂)
/c_ŵmax=fill(0.0,nx̂)
:ŵmin
/ŵmax
вес мягкости -
c_v̂min=fill(0.0,nym)
/c_v̂max=fill(0.0,nym)
:v̂min
/v̂max
вес мягкости -
все перечисленные выше именованные аргументы, но с первой заглавной буквой, например
X̂max
илиC_ŵmax
: для динамических ограничений (см. расширенную справку)
Примеры
julia> estim = MovingHorizonEstimator(LinModel(ss(0.5,1,1,0,1)), He=3);
julia> estim = setconstraint!(estim, x̂min=[-50, -50], x̂max=[50, 50])
MovingHorizonEstimator estimator with a sample time Ts = 1.0 s, OSQP optimizer, LinModel and:
3 estimation steps He
1 manipulated inputs u (0 integrating states)
2 estimated states x̂
1 measured outputs ym (1 integrating states)
0 unmeasured outputs yu
0 measured disturbances d
Расширенная справка
Обратите внимание, что ограничения состояния и шума процесса применяются к расширенной модели, как описано в расширенной справке по SteadyKalmanFilter
. Для переменных ограничений границы можно изменить после вызова updatestate!
, то есть во время выполнения. Это не касается границ ±Inf
. Возможны также динамические ограничения по горизонту оценки . Математически они определяются следующим образом.
Для этого используйте те же именованные аргументы, что и выше, но с первой заглавной буквой:
-
X̂min
/X̂max
/C_x̂min
/C_x̂max
: ограничения(nx̂*(He+1),)
. -
Ŵmin
/Ŵmax
/C_ŵmin
/C_ŵmax
: ограничения(nx̂*He,)
. -
V̂min
/V̂max
/C_v̂min
/C_v̂max
: ограничения(nym*He,)
.
setconstraint!(mpc::PredictiveController; <keyword arguments>) -> mpc
Задает параметры ограничений PredictiveController
mpc
.
Прогнозирующие контроллеры поддерживают как мягкие, так и жесткие ограничения, определяемые следующим образом:
а также . Последняя строка — это терминальные ограничения, применяемые к состояниям в конце горизонта (см. расширенную справку). В описании ограничений MovingHorizonEstimator
можно найти подробные сведения о границах и параметрах мягкости . Все выходные и терминальные ограничения по умолчанию являются мягкими. Сведения о динамических ограничениях см. в расширенной справке.
Аргументы
-
mpc::PredictiveController
: прогнозирующий контроллер для задания ограничений -
umin=fill(-Inf,nu)
/umax=fill(+Inf,nu)
: граница обрабатываемого входа -
Δumin=fill(-Inf,nu)
/Δumax=fill(+Inf,nu)
: граница обрабатываемого входа с приращением -
ymin=fill(-Inf,ny)
/ymax=fill(+Inf,ny)
: граница прогнозируемого выхода -
x̂min=fill(-Inf,nx̂)
/x̂max=fill(+Inf,nx̂)
: граница терминального ограничения -
c_umin=fill(0.0,nu)
/c_umax=fill(0.0,nu)
:umin
/umax
вес мягкости -
c_Δumin=fill(0.0,nu)
/c_Δumax=fill(0.0,nu)
:Δumin
/Δumax
вес мягкости -
c_ymin=fill(1.0,ny)
/c_ymax=fill(1.0,ny)
:ymin
/ymax
вес мягкости -
c_x̂min=fill(1.0,nx̂)
/c_x̂max=fill(1.0,nx̂)
:x̂min
/x̂max
вес мягкости -
все перечисленные выше именованные аргументы, но с первой заглавной буквой, кроме терминальных ограничений, например
Ymax
илиC_Δumin
: для динамических ограничений (см. расширенную справку)
Примеры
julia> mpc = LinMPC(setop!(LinModel(tf(3, [30, 1]), 4), uop=[50], yop=[25]));
julia> mpc = setconstraint!(mpc, umin=[0], umax=[100], Δumin=[-10], Δumax=[+10])
LinMPC controller with a sample time Ts = 4.0 s, OSQP optimizer, SteadyKalmanFilter estimator and:
10 prediction steps Hp
2 control steps Hc
1 manipulated inputs u (0 integrating states)
2 estimated states x̂
1 measured outputs ym (1 integrating states)
0 unmeasured outputs yu
0 measured disturbances d
Расширенная справка
Терминальные ограничения обеспечивают устойчивость при замкнутом контуре для модели номинального объекта. Однако они могут создавать непреодолимую проблему. На практике для обеспечения устойчивости хватает достаточно большого горизонта прогнозирования без терминальных ограничений. Обратите внимание, что терминальные ограничения применяются к расширенному вектору состояний (дополнительные сведения о расширении см. в описании SteadyKalmanFilter
).
Для переменных ограничений границы можно изменить после вызова moveinput!
, то есть во время выполнения. Это не касается параметров мягкости . Изменять границы ±Inf
во время выполнения нельзя.
Чтобы не налагать на переменную ограничений, но оставить возможность добавить ограничение позднее во время выполнения, при создании контроллера присвойте границе достаточно большое абсолютное значение (но отличное от |
По горизонтам и также можно указать динамические ограничения. В этом случае они определяются так:
Для этого используйте те же именованные аргументы, что и выше, но с первой заглавной буквой:
-
Umin
/Umax
/C_umin
/C_umax
: ограничения(nu*Hp,)
. -
ΔUmin
/ΔUmax
/C_Δumin
/C_Δumax
: ограничения(nu*Hc,)
. -
Ymin
/Ymax
/C_ymin
/C_ymax
: ограничения(ny*Hp,)
.
Вычисление выхода y
#
ModelPredictiveControl.evaloutput
— Function
evaloutput(model::SimModel, d=[]) -> y
Вычисляет выходы y
модели SimModel
на основе состояний model.x
и измеряемых возмущений d
.
При вызове объекта SimModel
вызывается данный метод evaloutput
.
Примеры
julia> model = setop!(LinModel(tf(2, [10, 1]), 5.0), yop=[20]);
julia> y = evaloutput(model)
1-element Vector{Float64}:
20.0
evaloutput(estim::StateEstimator, d=[]) -> ŷ
Вычисляет выходы ŷ
модели StateEstimator
на основе состояний estim.x̂
и возмущений d
.
При вызове объекта StateEstimator
вызывается данный метод evaloutput
.
Примеры
julia> kf = SteadyKalmanFilter(setop!(LinModel(tf(2, [10, 1]), 5), yop=[20]));
julia> ŷ = evaloutput(kf)
1-element Vector{Float64}:
20.0
Обновление состояния x
#
ModelPredictiveControl.updatestate!
— Function
updatestate!(model::SimModel, u, d=[]) -> x
Обновляет состояния model.x
с использованием текущих входов u
и измеряемых возмущений d
.
Примеры
julia> model = LinModel(ss(1.0, 1.0, 1.0, 0, 1.0));
julia> x = updatestate!(model, [1])
1-element Vector{Float64}:
1.0
updatestate!(estim::StateEstimator, u, ym, d=[]) -> x̂
Обновляет оценку estim.x̂
с использованием текущих входов u
, измеренных выходов ym
и распределения d
.
Этот метод удаляет рабочие точки с помощью remove_op!
и вызывает update_estimate!
.
Примеры
julia> kf = SteadyKalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4.0)));
julia> x̂ = updatestate!(kf, [1], [0]) # x̂[2] — это состояние интегратора (аргумент nint_ym)
2-element Vector{Float64}:
0.5
0.0
updatestate!(mpc::PredictiveController, u, ym, d=[]) -> x̂
Вызывает updatestate!
для mpc.estim
StateEstimator
.
Инициализация состояния x
#
ModelPredictiveControl.initstate!
— Function
initstate!(model::SimModel, u, d=[]) -> x
Инициирует model.x
с использованием обрабатываемых входов u
и измеряемых возмущений d
в установившемся состоянии.
Вызывает steadystate!(model, u, d)
:
Примеры
julia> model = LinModel(tf(6, [10, 1]), 2.0);
julia> u = [1]; x = initstate!(model, u); y = round.(evaloutput(model), digits=3)
1-element Vector{Float64}:
6.0
julia> x ≈ updatestate!(model, u)
true
initstate!(estim::StateEstimator, u, ym, d=[]) -> x̂
Инициирует состояния estim.x̂
с использованием текущих входов u
, измеренных выходов ym
и возмущений d
.
Этот метод пытается найти подходящее установившееся состояние для начальной оценки . Он удаляет рабочие точки с помощью remove_op!
и вызывает init_estimate!
:
-
Если объект
estim.model
относится к типуLinModel
, метод находит установившееся состояние расширенной модели с использованием аргументовu
иd
и с помощью аргументаym
налагает условие . В управляющих системах это решение обеспечивает мягкую передачу управления с ручного на автоматическое. Подробные сведения см. в описанииinit_estimate!
. -
В противном случае
estim.x̂
остается без изменений. Для изменения вручную используйтеsetstate!
.
Если применимо, также меняет значение ковариации погрешности estim.P̂
на estim.P̂0
.
Примеры
julia> estim = SteadyKalmanFilter(LinModel(tf(3, [10, 1]), 0.5), nint_ym=[2]);
julia> u = [1]; y = [3 - 0.1]; x̂ = round.(initstate!(estim, u, y), digits=3)
3-element Vector{Float64}:
5.0
0.0
-0.1
julia> x̂ ≈ updatestate!(estim, u, y)
true
julia> evaloutput(estim) ≈ y
true
initstate!(mpc::PredictiveController, u, ym, d=[]) -> x̂
Инициирует состояния mpc.estim
StateEstimator
и выполняет мягкий запуск mpc.ΔŨ
в нулевой точке.
Установка состояния x
#
ModelPredictiveControl.setstate!
— Function
setstate!(model::SimModel, x)
Присваивает состояниям model.x
значения, заданные в x
.
setstate!(estim::StateEstimator, x̂)
Присваивает состояниям estim.x̂
значения, заданные в x̂
.
setstate!(mpc::PredictiveController, x̂)
Задает оценку в mpc.estim.x̂
.
Быстрое моделирование
Моделирование
#
ModelPredictiveControl.sim!
— Function
sim!(plant::SimModel, N::Int, u=plant.uop.+1, d=plant.dop; x0=zeros(plant.nx)) -> res
Моделирование с разомкнутым контуром объекта plant
в течение N
временных шагов; по умолчанию выполняется модульный импульсный тест на всех входах.
Обрабатываемые входы и измеряемые возмущения остаются постоянными со значениями u
и d
соответственно. Начальное состояние объекта задается именованными аргументами x0
. Функция возвращает экземпляры SimResult
, которые можно визуализировать путем вызова функции plot
из Plots.jl
(см. примеры ниже). Обратите внимание, что этот метод изменяет внутренние состояния plant
.
Примеры
julia> plant = NonLinModel((x,u,d)->0.1x+u+d, (x,_)->2x, 10.0, 1, 1, 1, 1);
julia> res = sim!(plant, 15, [0], [0], x0=[1])
Simulation results of NonLinModel with 15 time steps.
julia> using Plots; plot(res, plotu=false, plotd=false, plotx=true)
sim!(
estim::StateEstimator,
N::Int,
u = estim.model.uop .+ 1,
d = estim.model.dop;
<keyword arguments>
) -> res
Моделирование с замкнутым контуром оценки estim
в течение N
шагов; по умолчанию импульсы на входах.
Допустимые варианты см. в описании аргументов. Шумы предоставляются в виде векторов среднеквадратичных отклонений σ. Моделируемые шумы датчика и процесса объекта plant
задаются аргументами y_noise
и x_noise
соответственно.
Аргументы
-
estim::StateEstimator
: моделируемое средство оценки состояния -
N::Int
: длительность моделирования во временных шагах -
u = estim.model.uop .+ 1
: значение обрабатываемого входа -
d = estim.model.dop
: значение измеряемого возмущения объекта -
plant::SimModel = estim.model
: модель объекта -
u_step = zeros(plant.nu)
: ступенчатое возмущение по нагрузке на входах объекта -
u_noise = zeros(plant.nu)
: гауссово возмущение по нагрузке на входах объекта -
y_step = zeros(plant.ny)
: возмущение по нагрузке на выходах объекта -
y_noise = zeros(plant.ny)
: аддитивный гауссов шум на выходах объекта -
d_step = zeros(plant.nd)
: шаг измеряемых возмущений -
d_noise = zeros(plant.nd)
: аддитивный гауссов шум в измеряемом возмущении -
x_noise = zeros(plant.nx)
: аддитивный гауссов шум в состояниях объекта -
x0 = plant.x
: начальное состояние объекта -
x̂0 = nothing
: начальная оценка ; при значенииnothing
используетсяinitstate!
-
lastu = plant.uop
: последний вход объекта для инициализации
Примеры
julia> model = LinModel(tf(3, [30, 1]), 0.5);
julia> estim = KalmanFilter(model, σR=[0.5], σQ=[0.25], σQint_ym=[0.01], σP0int_ym=[0.1]);
julia> res = sim!(estim, 50, [0], y_noise=[0.5], x_noise=[0.25], x0=[-10], x̂0=[0, 0])
Simulation results of KalmanFilter with 50 time steps.
julia> using Plots; plot(res, plotŷ=true, plotu=false, plotxwithx̂=true)
sim!(
mpc::PredictiveController,
N::Int,
ry = mpc.estim.model.yop .+ 1,
d = mpc.estim.model.dop,
ru = mpc.estim.model.uop;
<keyword arguments>
) -> res
Моделирование с замкнутым контуром контроллера mpc
в течение N
шагов; по умолчанию импульсы уставок на выходах.
Уставки выходов и обрабатываемых входов остаются постоянными в ry
и ru
соответственно. Именованные аргументы такие же, как у sim!(::StateEstimator, ::Int)
.
Примеры
julia> model = LinModel([tf(3, [30, 1]); tf(2, [5, 1])], 4);
julia> mpc = setconstraint!(LinMPC(model, Mwt=[0, 1], Nwt=[0.01], Hp=30), ymin=[0, -Inf]);
julia> res = sim!(mpc, 25, [0, 0], y_noise=[0.1], y_step=[-10, 0])
Simulation results of LinMPC with 25 time steps.
julia> using Plots; plot(res, plotry=true, plotŷ=true, plotymin=true, plotu=true)
Результаты моделирования
#
ModelPredictiveControl.SimResult
— Type
SimResult(
obj::Union{SimModel, StateEstimator, PredictiveController},
U_data,
Y_data,
D_data = [];
X_data = nothing,
X̂_data = nothing,
Ry_data = nothing,
Ru_data = nothing
)
Вручную создайте SimResult
, чтобы быстро строить графики результатов моделирования obj
.
Все аргументы, кроме obj
, должны быть матрицами из N
столбцов, где N
— количество временных шагов. Объекты SimResult
позволяют быстро строить графики результатов моделирования. Просто вызывайте для них функцию plot
из Plots.jl
.
Примеры
julia> plant = LinModel(tf(1, [1, 1]), 1.0); N = 5; U_data = fill(1.0, 1, N);
julia> Y_data = reduce(hcat, (updatestate!(plant, U_data[:, i]); plant()) for i=1:N)
1×5 Matrix{Float64}:
0.632121 0.864665 0.950213 0.981684 0.993262
julia> res = SimResult(plant, U_data, Y_data)
Simulation results of LinModel with 5 time steps.
julia> using Plots; plot(res)
Получение дополнительной информации
#
ModelPredictiveControl.getinfo
— Function
getinfo(estim::MovingHorizonEstimator) -> info
Возвращает дополнительные сведения об оптимуме estim
MovingHorizonEstimator
для устранения неполадок.
Эта функция должна вызываться после вызова updatestate!
. Она возвращает словарь info
со следующими полями:
-
:Ŵ
: оптимальный оценочный шум процесса по , -
:x̂arr
: оптимальное оценочное состояние в конечный момент, -
:ϵ
: оптимальная ослабляющая переменная, -
:J
: оптимум целевого значения, -
:X̂
: оптимальные оценочные состояния по , -
:x̂
: оптимальное оценочное состояние для следующего временного шага, -
:V̂
: оптимальный оценочный шум датчика по , -
:P̄
: оценочная ковариация погрешности в конечный момент, -
:x̄
: оптимальная оценочная погрешность в конечный момент, -
:Ŷ
: оптимальные оценочные выходы по , -
:Ŷm
: оптимальные оценочные измеряемые выходы по , -
:Ym
: измеряемые выходы по , -
:U
: обрабатываемые входы по , -
:D
: измеряемые возмущения по , -
:sol
: сводка по решению оптимизатора для вывода
Примеры
julia> estim = MovingHorizonEstimator(LinModel(ss(1.0, 1.0, 1.0, 0, 1)), He=1, nint_ym=0);
julia> updatestate!(estim, [0], [1]);
julia> round.(getinfo(estim)[:Ŷ], digits=3)
1-element Vector{Float64}:
0.5
getinfo(mpc::PredictiveController) -> info
Возвращает дополнительные сведения об оптимуме mpc
PredictiveController
для устранения неполадок.
Эта функция должна вызываться после вызова moveinput!
. Она возвращает словарь info
со следующими полями:
-
:ΔU
: оптимальные приращения на обрабатываемых входах по , -
:ϵ
: оптимальная ослабляющая переменная, -
:J
: оптимум целевого значения, -
:U
: оптимальные обрабатываемые входы по , -
:u
: текущий оптимальный обрабатываемый вход, -
:d
: текущее измеряемое возмущение, -
:D̂
: прогнозируемые измеряемые возмущения по , -
:ŷ
: текущий оценочный выход, -
:Ŷ
: оптимальные прогнозируемые выходы по , -
:x̂end
: оптимальные конечные состояния, -
:Ŷs
: прогнозируемый стохастический выход по моделиInternalModel
, -
:R̂y
: уставка прогнозируемого выхода по , -
:R̂u
: уставка прогнозируемого обрабатываемого входа по ,
Для LinMPC
и NonLinMPC
поле :sol
также содержит сводку по решению оптимизатора, которую можно вывести на экран. Наконец, также доступны оптимальные затраты :JE
для NonLinMPC
.
Примеры
julia> mpc = LinMPC(LinModel(tf(5, [2, 1]), 3), Nwt=[0], Hp=1, Hc=1);
julia> u = moveinput!(mpc, [10]);
julia> round.(getinfo(mpc)[:Ŷ], digits=3)
1-element Vector{Float64}:
10.0