From 93e119da0705177f1a2b71480ddff35cc306bc1b Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 9 Sep 2026 10:16:02 -0400 Subject: [PATCH 1/4] doc: shorter examples to fit in max char length --- ext/LinearMPCext.jl | 6 +++--- src/controller/linmpc.jl | 2 +- src/controller/nonlinmpc.jl | 8 ++++---- src/estimator/internal_model.jl | 2 +- src/estimator/kalman.jl | 8 ++++---- src/estimator/manual.jl | 14 +++++++------- src/estimator/mhe/construct.jl | 4 ++-- src/model/linearization.jl | 4 ++-- src/plot_sim.jl | 16 +++++++++------- src/predictive_control.jl | 4 ++-- src/sim_model.jl | 6 +++--- src/state_estim.jl | 6 +++--- 12 files changed, 41 insertions(+), 39 deletions(-) diff --git a/ext/LinearMPCext.jl b/ext/LinearMPCext.jl index bbe4fa511..b639b3c21 100644 --- a/ext/LinearMPCext.jl +++ b/ext/LinearMPCext.jl @@ -252,13 +252,13 @@ documentation for more details on the supported features and how to generate cod ```jldoctest julia> import LinearMPC, JuMP, DAQP; -julia> mpc1 = LinMPC(LinModel(tf(2, [10, 1]), 1.0); optim=JuMP.Model(DAQP.Optimizer)); +julia> mpc1 = LinMPC(LinModel(tf(2, [9, 1]), 1.0); optim=JuMP.Model(DAQP.Optimizer)); julia> preparestate!(mpc1, [1.0]); julia> u = moveinput!(mpc1, [10.0]); round.(u, digits=6) 1-element Vector{Float64}: - 17.577311 + 17.527485 julia> mpc2 = LinearMPC.MPC(mpc1); @@ -266,7 +266,7 @@ julia> x̂ = LinearMPC.correct_state!(mpc2, [1.0]); julia> u = LinearMPC.compute_control(mpc2, x̂, r=[10.0]); round.(u, digits=6) 1-element Vector{Float64}: - 17.577311 + 17.527485 ``` """ LinearMPC.MPC(mpc::ModelPredictiveControl.LinMPC) = convert(LinearMPC.MPC, mpc) diff --git a/src/controller/linmpc.jl b/src/controller/linmpc.jl index 6910eaf08..ebb3c8102 100644 --- a/src/controller/linmpc.jl +++ b/src/controller/linmpc.jl @@ -263,7 +263,7 @@ Use custom state estimator `estim` to construct `LinMPC`. # Examples ```jldoctest -julia> estim = KalmanFilter(LinModel([tf(3, [30, 1]); tf(-2, [5, 1])], 4), i_ym=[2]); +julia> estim = KalmanFilter(LinModel([tf(6, [9, 1]); tf(2, [5, 1])], 4), i_ym=[2]); julia> mpc = LinMPC(estim, Mwt=[0, 1], Nwt=[0.5], Hp=30, Hc=1) LinMPC controller with a sample time Ts = 4.0 s: diff --git a/src/controller/nonlinmpc.jl b/src/controller/nonlinmpc.jl index 3b3ae1594..e38caf7cf 100644 --- a/src/controller/nonlinmpc.jl +++ b/src/controller/nonlinmpc.jl @@ -239,10 +239,10 @@ This controller allocates memory at each time step for the optimization. # Examples ```jldoctest -julia> model = NonLinModel((x,u,_,_)->0.5x+u, (x,_,_)->2x, 10.0, 1, 1, 1, solver=nothing); +julia> model = NonLinModel((x,u,_,_)->0.5x+u, (x,_,_)->x, 5, 1, 1, 1, solver=nothing); julia> mpc = NonLinMPC(model, Hp=20, Hc=10, transcription=MultipleShooting()) -NonLinMPC controller with a sample time Ts = 10.0 s: +NonLinMPC controller with a sample time Ts = 5.0 s: ├ estimator: UnscentedKalmanFilter ├ model: NonLinModel ├ optimizer: Ipopt @@ -385,12 +385,12 @@ Use custom state estimator `estim` to construct `NonLinMPC`. # Examples ```jldoctest -julia> model = NonLinModel((x,u,_,_)->0.5x+u, (x,_,_)->2x, 10.0, 1, 1, 1, solver=nothing); +julia> model = NonLinModel((x,u,_,_)->0.5x+u, (x,_,_)->x, 5, 1, 1, 1, solver=nothing); julia> estim = UnscentedKalmanFilter(model, σQint_ym=[0.05]); julia> mpc = NonLinMPC(estim, Hp=20, Cwt=1e4) -NonLinMPC controller with a sample time Ts = 10.0 s: +NonLinMPC controller with a sample time Ts = 5.0 s: ├ estimator: UnscentedKalmanFilter ├ model: NonLinModel ├ optimizer: Ipopt diff --git a/src/estimator/internal_model.jl b/src/estimator/internal_model.jl index ac65017de..a357801b8 100644 --- a/src/estimator/internal_model.jl +++ b/src/estimator/internal_model.jl @@ -79,7 +79,7 @@ estimator is allocation-free if `model` simulations do not allocate. # Examples ```jldoctest -julia> estim = InternalModel(LinModel([tf(3, [30, 1]); tf(-2, [5, 1])], 0.5), i_ym=[2]) +julia> estim = InternalModel(LinModel([tf(3, [9, 1]); tf(2, [4, 1])], 0.5), i_ym=[2]) InternalModel estimator with a sample time Ts = 0.5 s: ├ model: LinModel ├ direct: true diff --git a/src/estimator/kalman.jl b/src/estimator/kalman.jl index 52d573d77..3e2989f03 100644 --- a/src/estimator/kalman.jl +++ b/src/estimator/kalman.jl @@ -661,10 +661,10 @@ This estimator is allocation-free if `model` simulations do not allocate. # Examples ```jldoctest -julia> model = NonLinModel((x,u,_,_)->0.1x+u, (x,_,_)->2x, 10.0, 1, 1, 1, solver=nothing); +julia> model = NonLinModel((x,u,_,_)->0.1x+u, (x,_,_)->x, 5, 1, 1, 1, solver=nothing); julia> estim = UnscentedKalmanFilter(model, σR=[1], nint_ym=[2], σPint_ym_0=[1, 1]) -UnscentedKalmanFilter estimator with a sample time Ts = 10.0 s: +UnscentedKalmanFilter estimator with a sample time Ts = 5.0 s: ├ model: NonLinModel ├ direct: true └ dimensions: @@ -1032,9 +1032,9 @@ differentiation. This estimator is allocation-free if `model` simulations do not # Examples ```jldoctest -julia> model = NonLinModel((x,u,_,_)->0.2x+u, (x,_,_)->-3x, 5.0, 1, 1, 1, solver=nothing); +julia> model = NonLinModel((x,u,_,_)->0.2x+u, (x,_,_)->x, 5, 1, 1, 1, solver=nothing); -julia> estim = ExtendedKalmanFilter(model, σQ=[2], σQint_ym=[2], σP_0=[0.1], σPint_ym_0=[0.1]) +julia> estim = ExtendedKalmanFilter(model, σQ=[2], σQint_ym=[2], σP_0=[0.1]) ExtendedKalmanFilter estimator with a sample time Ts = 5.0 s: ├ model: NonLinModel ├ jacobian: AutoForwardDiff diff --git a/src/estimator/manual.jl b/src/estimator/manual.jl index f60f4d043..bf41dd80b 100644 --- a/src/estimator/manual.jl +++ b/src/estimator/manual.jl @@ -76,7 +76,7 @@ examples. ```jldoctest julia> model = LinModel([tf(3, [30, 1]); tf(-2, [5, 1])], 0.5); -julia> estim = ManualEstimator(model, nint_ym=0) # disable augmentation with integrators +julia> estim = ManualEstimator(model, nint_ym=0) # no augmentation with integrators ManualEstimator estimator with a sample time Ts = 0.5 s: ├ model: LinModel └ dimensions: @@ -109,14 +109,14 @@ ManualEstimator estimator with a sample time Ts = 0.5 s: initstate!(estim, [0], [0]) y_data, ŷ_data = zeros(5), zeros(5) for i=1:5 - y = model() # simulated measurement - x̂ = preparestate!(estim, y) # correct nonlinear MHE state estimate - ŷ = estim() # nonlinear MHE estimated output - setstate!(mpc, x̂) # update MPC with the MHE corrected state + y = model() # simulated measurement + x̂ = preparestate!(estim, y) # correct nonlinear MHE state estimate + ŷ = estim() # nonlinear MHE estimated output + setstate!(mpc, x̂) # update MPC with the MHE corrected state u = moveinput!(mpc, [0]) y_data[i], ŷ_data[i] = y[1], ŷ[1] - updatestate!(estim, u, y) # update nonlinear MHE estimation - updatestate!(model, u .+ 0.5) # update simulator with load disturbance + updatestate!(estim, u, y) # update nonlinear MHE estimation + updatestate!(model, u.+0.5) # update simulator with load disturbance end return collect([y_data ŷ_data]') end; diff --git a/src/estimator/mhe/construct.jl b/src/estimator/mhe/construct.jl index 2e22e49eb..36c84b15c 100644 --- a/src/estimator/mhe/construct.jl +++ b/src/estimator/mhe/construct.jl @@ -354,10 +354,10 @@ at each time step for the optimization. # Examples ```jldoctest -julia> model = NonLinModel((x,u,_,_)->0.1x+u, (x,_,_)->2x, 10.0, 1, 1, 1, solver=nothing); +julia> model = NonLinModel((x,u,_,_)->0.1x+u, (x,_,_)->x, 5, 1, 1, 1, solver=nothing); julia> estim = MovingHorizonEstimator(model, He=5, σR=[1], σP_0=[0.01]) -MovingHorizonEstimator estimator with a sample time Ts = 10.0 s: +MovingHorizonEstimator estimator with a sample time Ts = 5.0 s: ├ model: NonLinModel ├ optimizer: Ipopt ├ transcription: SingleShooting diff --git a/src/model/linearization.jl b/src/model/linearization.jl index eb916dca3..620b9614b 100644 --- a/src/model/linearization.jl +++ b/src/model/linearization.jl @@ -69,7 +69,7 @@ the `jacobian` keyword argument at the construction of `model` to swap the backe # Examples ```jldoctest -julia> model = NonLinModel((x,u,_,_)->x.^3 + u, (x,_,_)->x, 0.1, 1, 1, 1, solver=nothing); +julia> model = NonLinModel((x,u,_,_)->x.^3+u, (x,_,_)->x, 5, 1, 1, 1, solver=nothing); julia> linmodel = linearize(model, x=[10.0], u=[0.0]); @@ -145,7 +145,7 @@ The keyword arguments are identical to [`linearize`](@ref). The code is allocati # Examples ```jldoctest -julia> model = NonLinModel((x,u,_,_)->x.^3 + u, (x,_,_)->x, 0.1, 1, 1, 1, solver=nothing); +julia> model = NonLinModel((x,u,_,_)->x.^3+u, (x,_,_)->x, 5, 1, 1, 1, solver=nothing); julia> linmodel = linearize(model, x=[10.0], u=[0.0]); linmodel.A 1×1 Matrix{Float64}: diff --git a/src/plot_sim.jl b/src/plot_sim.jl index 737153dd2..71025bd56 100644 --- a/src/plot_sim.jl +++ b/src/plot_sim.jl @@ -45,7 +45,9 @@ julia> model = LinModel(tf(1, [1, 1]), 1.0); julia> N = 5; U_data = fill(1.0, 1, N); Y_data = zeros(1, N); -julia> foreach(i->(updatestate!(model, U_data[:, i]); Y_data[:, i] = model()), 1:N); Y_data +julia> foreach(i->(updatestate!(model, U_data[:, i]); Y_data[:, i] = model()), 1:N); + +julia> Y_data 1×5 Matrix{Float64}: 0.632121 0.864665 0.950213 0.981684 0.993262 @@ -121,9 +123,9 @@ internal states. # Examples ```jldoctest -julia> plant = NonLinModel((x,u,d,_)->0.1x+u+d, (x,_,_)->2x, 5, 1, 1, 1, 1, solver=nothing); +julia> plant = NonLinModel((x,u,_,_)->0.1x+u, (x,_,_)->x, 5, 1, 1, 1, solver=nothing); -julia> res = sim!(plant, 15, [0], [0], x_0=[1]) +julia> res = sim!(plant, 15, [0], x_0=[1]) Simulation results of NonLinModel with 15 time steps. ``` """ @@ -197,9 +199,9 @@ vectors. The simulated sensor and process noises of `plant` are specified by `y_ ```jldoctest julia> model = LinModel(tf(3, [30, 1]), 0.5); -julia> estim = KalmanFilter(model, σR=[0.5], σQ=[0.25], σQint_ym=[0.01], σPint_ym_0=[0.1]); +julia> estim = KalmanFilter(model, σR=[0.5], σQ=[0.2], σQint_ym=[0.01]); -julia> res = sim!(estim, 50, [0], y_noise=[0.5], x_noise=[0.25], x_0=[-10], x̂_0=[0, 0]) +julia> res = sim!(estim, 50, [0], y_noise=[0.5], x_noise=[0.2], x_0=[-10], x̂_0=[0, 0]) Simulation results of KalmanFilter with 50 time steps. ``` """ @@ -232,7 +234,7 @@ The keyword arguments are identical to [`sim!(::StateEstimator, ::Int)`](@ref). ```jldoctest 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> mpc = setconstraint!(LinMPC(model, Mwt=[0, 1], Nwt=[.01]), 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. @@ -473,7 +475,7 @@ Plot the simulation results of a [`StateEstimator`](@ref). # Examples ```julia-repl -julia> res = sim!(KalmanFilter(LinModel(tf(3, [2.0, 1]), 1.0)), 25, [0], y_step=[1]); +julia> res = sim!(KalmanFilter(LinModel(tf(3, [2, 1]), 1.0)), 25, [0], y_step=[1]); julia> using Plots; plot(res, plotu=false, plotŷ=true, plotxwithx̂=true) ``` diff --git a/src/predictive_control.jl b/src/predictive_control.jl index 3772d4ade..86fbed615 100644 --- a/src/predictive_control.jl +++ b/src/predictive_control.jl @@ -7,11 +7,11 @@ Abstract supertype of all predictive controllers. (mpc::PredictiveController)(ry, d=[]; kwargs...) -> u -Functor allowing callable `PredictiveController` object as an alias for [`moveinput!`](@ref). +Call [`moveinput!`](@ref) by calling a `PredictiveController` object. # Examples ```jldoctest -julia> mpc = LinMPC(LinModel(tf(5, [2, 1]), 3), Nwt=[0], Hp=1000, Hc=1, direct=false); +julia> mpc = LinMPC(LinModel(tf(5, [2, 1]), 3), Hp=1000, Hc=1, direct=false); julia> u = mpc([5]); round.(u, digits=3) 1-element Vector{Float64}: diff --git a/src/sim_model.jl b/src/sim_model.jl index 4c819bc50..91d0c7480 100644 --- a/src/sim_model.jl +++ b/src/sim_model.jl @@ -7,15 +7,15 @@ Abstract supertype of [`LinModel`](@ref) and [`NonLinModel`](@ref) types. (model::SimModel)(d=[]) -> y -Functor allowing callable `SimModel` object as an alias for [`evaloutput`](@ref). +Call [`evaloutput`](@ref) by calling a `SimModel` object. # Examples ```jldoctest -julia> model = NonLinModel((x,u,_,_)->-x + u, (x,_,_)->x .+ 20, 4, 1, 1, 1, solver=nothing); +julia> model = NonLinModel((x,u,_,_)->-x+u, (x,_,_)->x.+5, 4, 1, 1, 1, solver=nothing); julia> y = model() 1-element Vector{Float64}: - 20.0 + 5.0 ``` """ abstract type SimModel{NT<:Real} end diff --git a/src/state_estim.jl b/src/state_estim.jl index 1c5943147..67c8b19a3 100644 --- a/src/state_estim.jl +++ b/src/state_estim.jl @@ -7,15 +7,15 @@ Abstract supertype of all state estimators. (estim::StateEstimator)(d=[]) -> ŷ -Functor allowing callable `StateEstimator` object as an alias for [`evaloutput`](@ref). +Call [`evaloutput`](@ref) by calling a `StateEstimator` object. # Examples ```jldoctest -julia> kf = KalmanFilter(setop!(LinModel(tf(3, [10, 1]), 2), yop=[20]), direct=false); +julia> kf = KalmanFilter(setop!(LinModel(tf(3, [9, 1]), 2), yop=[6]), direct=false); julia> ŷ = kf() 1-element Vector{Float64}: - 20.0 + 6.0 ``` """ abstract type StateEstimator{NT<:Real} end From 557f8f844105b2d0323a343f0663d079c94bc842 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 9 Sep 2026 10:59:57 -0400 Subject: [PATCH 2/4] doc: idem --- src/controller/execute.jl | 14 ++++++++++---- src/estimator/execute.jl | 14 ++++++++------ src/sim_model.jl | 4 +++- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/controller/execute.jl b/src/controller/execute.jl index 490081b62..4859a614c 100644 --- a/src/controller/execute.jl +++ b/src/controller/execute.jl @@ -607,14 +607,20 @@ prediction horizon ``H_p``. # Examples ```jldoctest -julia> mpc = LinMPC(KalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4.0)), σR=[√25]), Hp=1, Hc=1); +julia> model1 = LinModel(ss(0.1, 0.5, 1, 0, 4.0)); -julia> mpc.estim.model.A[1], mpc.estim.cov.R̂[1], mpc.weights.M_Hp[1], mpc.weights.Ñ_Hc[1] +julia> mpc = LinMPC(KalmanFilter(model1, σR=[√25]), Hp=1, Hc=1); + +julia> estim = mpc.estim; + +julia> estim.model.A[1], estim.cov.R̂[1], mpc.weights.M_Hp[1], mpc.weights.Ñ_Hc[1] (0.1, 25.0, 1.0, 0.1) -julia> setmodel!(mpc, LinModel(ss(0.42, 0.5, 1, 0, 4.0)); R̂=[9], M_Hp=[10], Nwt=[0.666]); +julia> model2 = LinModel(ss(0.42, 0.5, 1, 0, 4.0)); + +julia> setmodel!(mpc, model2; R̂=[9], M_Hp=[10], Nwt=[0.666]); -julia> mpc.estim.model.A[1], mpc.estim.cov.R̂[1], mpc.weights.M_Hp[1], mpc.weights.Ñ_Hc[1] +julia> estim.model.A[1], estim.cov.R̂[1], mpc.weights.M_Hp[1], mpc.weights.Ñ_Hc[1] (0.42, 9.0, 10.0, 0.666) ``` """ diff --git a/src/estimator/execute.jl b/src/estimator/execute.jl index 62d6456af..a46ce3c2e 100644 --- a/src/estimator/execute.jl +++ b/src/estimator/execute.jl @@ -190,7 +190,7 @@ If applicable, it also sets the error covariance `estim.cov.P̂` to `estim.cov.P # Examples ```jldoctest -julia> estim = SteadyKalmanFilter(LinModel(tf(3, [10, 1]), 0.5), nint_ym=[2], direct=false); +julia> estim = Luenberger(LinModel(tf(3, [10, 1]), 0.5), nint_ym=[2], direct=false); julia> u = [1]; y = [3 - 0.1]; x̂ = round.(initstate!(estim, u, y), digits=3) 3-element Vector{Float64}: @@ -277,11 +277,11 @@ Calling a [`StateEstimator`](@ref) object calls this `evaloutput` method. # Examples ```jldoctest -julia> kf = SteadyKalmanFilter(setop!(LinModel(tf(2, [10, 1]), 5), yop=[20]), direct=false); +julia> kf = KalmanFilter(setop!(LinModel(tf(2, [10, 1]), 5), yop=[6]), direct=false); julia> ŷ = evaloutput(kf) 1-element Vector{Float64}: - 20.0 + 6.0 ``` """ function evaloutput(estim::StateEstimator{NT}, d=estim.buffer.empty) where NT <: Real @@ -318,13 +318,13 @@ delayed/predictor (2.) formulation: # Examples ```jldoctest -julia> estim2 = SteadyKalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4)), nint_ym=0, direct=true); +julia> estim2 = KalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4)), nint_ym=0, direct=true); julia> x̂ = round.(preparestate!(estim2, [1]), digits=2) 1-element Vector{Float64}: 0.5 -julia> estim1 = SteadyKalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4)), nint_ym=0, direct=false); +julia> estim1 = KalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4)), nint_ym=0, direct=false); julia> x̂ = preparestate!(estim1, [1]) 1-element Vector{Float64}: @@ -462,7 +462,9 @@ augmented model is not verified (see Extended Help for more info). # Examples ```jldoctest -julia> kf = KalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4.0)), σQ=[√4.0], σQint_ym=[√0.25]); +julia> model = LinModel(ss(0.1, 0.5, 1, 0, 4.0)); + +julia> kf = KalmanFilter(model, σQ=[√4.0], σQint_ym=[√0.25]); julia> kf.model.A[], kf.cov.Q̂[1, 1], kf.cov.Q̂[2, 2] (0.1, 4.0, 0.25) diff --git a/src/sim_model.jl b/src/sim_model.jl index 91d0c7480..f4ef77f6f 100644 --- a/src/sim_model.jl +++ b/src/sim_model.jl @@ -136,7 +136,9 @@ used in the plotting functions. # Examples ```jldoctest -julia> model = setname!(LinModel(tf(3, [10, 1]), 2.0), u=["\$A\$ (%)"], y=["\$T\$ (∘C)"]) +julia> model = LinModel(tf(3, [10, 1]), 2.0) + +julia> model = setname!(model, u=["\$A\$ (%)"], y=["\$T\$ (∘C)"]) LinModel with a sample time Ts = 2.0 s: └ dimensions: ├ 1 manipulated inputs u From a25ac28d618d38d3001c39609888d268b0ba1a52 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 9 Sep 2026 11:29:01 -0400 Subject: [PATCH 3/4] doc: idem but in "Manual" section --- docs/src/manual/linmpc.md | 3 ++- docs/src/manual/mtk.md | 14 +++++++------- docs/src/manual/nonlinmpc.md | 31 ++++++++++++++++++------------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/docs/src/manual/linmpc.md b/docs/src/manual/linmpc.md index df2fe2a9b..5cd58ccbb 100644 --- a/docs/src/manual/linmpc.md +++ b/docs/src/manual/linmpc.md @@ -245,7 +245,8 @@ We need to construct a new [`LinModel`](@ref) that includes the measured disturb ``\mathbf{d} = u_l`` and the operating point ``\mathbf{d_{op}} = 20``: ```@example 1 -model_d = setop!(LinModel([G G[1:2, 2]], Ts, i_d=[3]), uop=[20, 20], yop=[50, 30], dop=[20]) +model_d = LinModel([G G[1:2, 2]], Ts, i_d=[3]) +model_d = setop!(model_d, uop=[20, 20], yop=[50, 30], dop=[20]) ``` A [`LinMPC`](@ref) controller is constructed on this model: diff --git a/docs/src/manual/mtk.md b/docs/src/manual/mtk.md index 5c3c43897..6c3b7d1fc 100644 --- a/docs/src/manual/mtk.md +++ b/docs/src/manual/mtk.md @@ -57,8 +57,8 @@ function generate_f_h(model, inputs, outputs) f_ip(ẋ, x, u, p, nothing) catch err if err isa MethodError - error("NonLinModel does not support a time argument t in the f function, "* - "see the constructor docstring for a workaround.") + error("NonLinModel does not support a time argument t in the f "* + "function, see the constructor docstring for a workaround.") else rethrow() end @@ -71,14 +71,14 @@ function generate_f_h(model, inputs, outputs) u_nothing = fill(nothing, nu) function h!(y, x, _ , p) try - # MTK.jl supports a `u` argument in `h_ip` function but not this package. We set - # `u` as a vector of nothing and `h_ip` function will presumably throw an - # MethodError if this argument is used inside the function + # MTK.jl supports a `u` argument in `h_ip` function but not this package. We + # set `u` as a vector of nothing and `h_ip` function will presumably throw + # an MethodError if this argument is used inside the function h_ip(y, x, u_nothing, p, nothing) catch err if err isa MethodError - error("NonLinModel only support strictly proper systems (no manipulated "* - "input argument u in the output function h)") + error("NonLinModel only support strictly proper systems (no "* + "manipulated input argument u in the output function h)") else rethrow() end diff --git a/docs/src/manual/nonlinmpc.md b/docs/src/manual/nonlinmpc.md index 671f0d25a..5ed7e2026 100644 --- a/docs/src/manual/nonlinmpc.md +++ b/docs/src/manual/nonlinmpc.md @@ -130,7 +130,8 @@ The option `Cwt=Inf` disables the slack variable `ϵ` for constraint softening. ```@example man_nonlin using JuMP; unset_time_limit_sec(nmpc.optim) # hide -res_ry = sim!(nmpc, N, [180.0], plant=plant, x_0=[0, 0], x̂_0=[0, 0, 0]) +ry = [180.0] +res_ry = sim!(nmpc, N, ry, plant=plant, x_0=[0, 0], x̂_0=[0, 0, 0]) plot(res_ry) savefig("plot3_NonLinMPC.svg"); nothing # hide ``` @@ -142,7 +143,7 @@ inverted position, the closed-loop response to a step disturbances of 10° is al satisfactory: ```@example man_nonlin -res_yd = sim!(nmpc, N, [180.0], plant=plant, x_0=[π, 0], x̂_0=[π, 0, 0], y_step=[10]) +res_yd = sim!(nmpc, N, ry, plant=plant, x_0=[π, 0], x̂_0=[π, 0, 0], y_step=[10]) plot(res_yd) savefig("plot4_NonLinMPC.svg"); nothing # hide ``` @@ -185,8 +186,10 @@ Kalman Filter similar to the previous one (``\mathbf{y^m} = θ`` and ``\mathbf{y ```@example man_nonlin h2(x, _ , _ ) = [180/π*x[1], x[2]] nu, nx, ny = 1, 2, 2 -model2 = setname!(NonLinModel(f, h2, Ts, nu, nx, ny; p=p_model), u=vu, x=vx, y=[vy; vx[2]]) -plant2 = setname!(NonLinModel(f, h2, Ts, nu, nx, ny; p=p_plant), u=vu, x=vx, y=[vy; vx[2]]) +model2 = NonLinModel(f, h2, Ts, nu, nx, ny; p=p_model) +model2 = setname!(model2, u=vu, x=vx, y=[vy; vx[2]]) +plant2 = NonLinModel(f, h2, Ts, nu, nx, ny; p=p_plant) +plant2 = setname!(plant2, u=vu, x=vx, y=[vy; vx[2]]) estim2 = UnscentedKalmanFilter(model2; σQ, σR, nint_u, σQint_u, i_ym=[1]) ``` @@ -212,7 +215,8 @@ setpoint is similar: ```@example man_nonlin unset_time_limit_sec(empc.optim) # hide -res2_ry = sim!(empc, N, [180, 0], plant=plant2, x_0=[0, 0], x̂_0=[0, 0, 0]) +ry = [180.0, 0] +res2_ry = sim!(empc, N, ry, plant=plant2, x_0=[0, 0], x̂_0=[0, 0, 0]) plot(res2_ry, ploty=[1]) savefig("plot5_NonLinMPC.svg"); nothing # hide ``` @@ -232,7 +236,7 @@ Dict(:W_nmpc => calcW(res_ry), :W_empc => calcW(res2_ry)) Also, for a 10° step disturbance: ```@example man_nonlin -res2_yd = sim!(empc, N, [180; 0]; plant=plant2, x_0=[π, 0], x̂_0=[π, 0, 0], y_step=[10, 0]) +res2_yd = sim!(empc, N, ry; plant=plant2, x_0=[π, 0], x̂_0=[π, 0, 0], y_step=[10, 0]) plot(res2_yd, ploty=[1]) savefig("plot6_NonLinMPC.svg"); nothing # hide ``` @@ -304,7 +308,7 @@ In addition to the 180° setpoint response: ```@example man_nonlin using Logging # hide res3_ry = with_logger(ConsoleLogger(stderr, Error)) do # hide -res3_ry = sim!(nmpc2, N, [180; 0]; plant=plant2, x_0=[0, 0], x̂_0=[0, 0, 0]); +res3_ry = sim!(nmpc2, N, ry; plant=plant2, x_0=[0, 0], x̂_0=[0, 0, 0]); end # hide nothing # hide ``` @@ -316,7 +320,7 @@ function plotWithPower(res, Pmax) t, τ, ω = res.T_data, res.U_data[1, :], res.X_data[2, :] P, Pmax = τ.*ω, fill(Pmax, size(t)) plt1 = plot(res, ploty=[1]) - plt2 = plot(t, P, label=raw"$P$", ylabel=raw"$P$ (W)", xlabel="Time (s)", legend=:right) + plt2 = plot(t, P, label="\$P\$", ylabel="\$P\$ (W)", xlabel="Time (s)", legend=:right) plot!(plt2, t, Pmax, label=raw"$P_\mathrm{max}$", linestyle=:dot, linewidth=1.5) return plot(plt1, plt2, layout=(2,1)) end @@ -353,7 +357,8 @@ mpc = setconstraint!(mpc, umin=[-1.5], umax=[+1.5]) The linear controller satisfactorily rejects the 10° step disturbance: ```@example man_nonlin -res_lin = sim!(mpc, N, [180.0]; plant, x_0=[π, 0], y_step=[10]) +ry = [180.0] +res_lin = sim!(mpc, N, ry; plant, x_0=[π, 0], y_step=[10]) plot(res_lin) savefig("plot9_NonLinMPC.svg"); nothing # hide ``` @@ -392,7 +397,7 @@ mpc2 = setconstraint!(mpc2; umin, umax) does slightly improve the rejection of the step disturbance: ```@example man_nonlin -res_lin2 = sim!(mpc2, N, [180.0]; plant, x_0=[π, 0], y_step=[10]) +res_lin2 = sim!(mpc2, N, ry; plant, x_0=[π, 0], y_step=[10]) plot(res_lin2) savefig("plot10_NonLinMPC.svg"); nothing # hide ``` @@ -412,7 +417,7 @@ Superimposing the previous disturbance rejection to the newer one gives almost i results: ```@example man_nonlin -res_ms = sim!(mpc_ms, N, [180.0]; plant, x_0=[π, 0], y_step=[10]) +res_ms = sim!(mpc_ms, N, ry; plant, x_0=[π, 0], y_step=[10]) plot!(res_ms) savefig("plot10b_NonLinMPC.svg"); nothing # hide ``` @@ -426,7 +431,7 @@ For example, the 180° setpoint response from 0° is unsatisfactory since the pr poor in the first quadrant: ```@example man_nonlin -res_lin3 = sim!(mpc2, N, [180.0]; plant, x_0=[0, 0]) +res_lin3 = sim!(mpc2, N, ry; plant, x_0=[0, 0]) plot(res_lin3) savefig("plot11_NonLinMPC.svg"); nothing # hide ``` @@ -483,7 +488,7 @@ operating point. The [`SimResult`](@ref) object is for plotting purposes only. T [`LinMPC`](@ref) performances are similar to the nonlinear MPC, both for the 180° setpoint: ```@example man_nonlin -x_0 = [0, 0]; x̂_0 = [0, 0, 0]; ry = [180] +x_0 = [0, 0]; x̂_0 = [0, 0, 0]; res_slin = sim_adapt!(mpc3, model, N, ry, plant, x_0, x̂_0) plot(res_slin) savefig("plot12_NonLinMPC.svg"); nothing # hide From 536b8d06dd5e5c49c7a181ecf0b8bff992524b00 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 9 Sep 2026 12:13:56 -0400 Subject: [PATCH 4/4] doc: debug `jldoctest` --- src/sim_model.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sim_model.jl b/src/sim_model.jl index f4ef77f6f..d867c4c92 100644 --- a/src/sim_model.jl +++ b/src/sim_model.jl @@ -136,7 +136,7 @@ used in the plotting functions. # Examples ```jldoctest -julia> model = LinModel(tf(3, [10, 1]), 2.0) +julia> model = LinModel(tf(3, [10, 1]), 2.0); julia> model = setname!(model, u=["\$A\$ (%)"], y=["\$T\$ (∘C)"]) LinModel with a sample time Ts = 2.0 s: