Документация Engee

Функции: универсальные функции

Установка ограничения

# ModelPredictiveControl.setconstraint!Function

setconstraint!(estim::MovingHorizonEstimator; <keyword arguments>) -> estim

Задает параметры ограничений MovingHorizonEstimator estim.

Поддерживает как мягкие, так и жесткие ограничения для оценочного состояния , шума процесса и шума датчика :

а также для . Все параметры ограничений представляют собой вектор. Используйте значения ±Inf, если ограничения нет. Параметры мягкости ограничений , также называемые равным значением релаксации, — это неотрицательные значения, которые определяют мягкость соответствующей границы. Используйте значения 0.0 для жестких ограничений (по умолчанию для всех). Обратите внимание, что ограничение оценочного шума датчика равносильно ограничению порождающего члена, так как . В расширенной справке приводятся подробные сведения о расширении модели и динамических ограничениях.

Аргументы

Ограничения по умолчанию упоминаются здесь для наглядности, однако если опустить именованный аргумент, ему не будет снова присвоено значение по умолчанию (значения по умолчанию задаются только в момент создания). То же самое касается PredictiveController.

  • 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 во время выполнения нельзя.

Чтобы не налагать на переменную ограничений, но оставить возможность добавить ограничение позднее во время выполнения, при создании контроллера присвойте границе достаточно большое абсолютное значение (но отличное от ±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.evaloutputFunction

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):

  • Если объект model относится к типу LinModel, этот метод вычисляет установившееся состояние текущих входов u и измеряемых возмущений d.

  • В противном случае model.x остается без изменений. Для изменения вручную используйте setstate!.

Примеры

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̂ значения, заданные в .

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.SimResultType

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.getinfoFunction

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