From b5912f7a5e27723fd7f25ee6da0fef1e0929597d Mon Sep 17 00:00:00 2001 From: franckgaga Date: Fri, 20 Mar 2026 13:31:00 -0400 Subject: [PATCH 1/6] wip: trying to update to MTK v11 --- docs/src/manual/mtk.md | 44 +++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/docs/src/manual/mtk.md b/docs/src/manual/mtk.md index 854e31bc0..3821d5fa8 100644 --- a/docs/src/manual/mtk.md +++ b/docs/src/manual/mtk.md @@ -23,35 +23,22 @@ the last section. will work for all corner cases. !!! compat - The example works on `ModelingToolkit.jl` v10 (corresponding to the following `[compat]` - entry: `ModelingToolkit = "10"`). + The example works on `ModelingToolkit.jl` v11 (corresponding to the following `[compat]` + entry: `ModelingToolkit = "11"`). We first construct and instantiate the pendulum model: ```@example 1 using ModelPredictiveControl, ModelingToolkit using ModelingToolkit: D_nounits as D, t_nounits as t, varmap_to_vars -@mtkmodel Pendulum begin - @parameters begin - g = 9.8 - L = 0.4 - K = 1.2 - m = 0.3 - end - @variables begin - θ(t) # state - ω(t) # state - τ(t) # input - y(t) # output - end - @equations begin - D(θ) ~ ω - D(ω) ~ -g/L*sin(θ) - K/m*ω + τ/m/L^2 - y ~ θ * 180 / π - end -end -@named mtk_model = Pendulum() -mtk_model = complete(mtk_model) +@parameters g=9.8 L=0.4 K=1.2 m=0.3 +@variables θ(t)=0 ω(t)=0 τ(t)=0 y(t) +eqs = [ + D(θ) ~ ω + D(ω) ~ -g/L*sin(θ) - K/m*ω + τ/m/L^2 + y ~ θ * 180 / π +] +@named mtk_model = System(eqs, t) ``` We than convert the MTK model to an [input-output system](https://docs.sciml.ai/ModelingToolkit/stable/basics/InputOutput/): @@ -59,7 +46,7 @@ We than convert the MTK model to an [input-output system](https://docs.sciml.ai/ ```@example 1 function generate_f_h(model, inputs, outputs) (_, f_ip), x_sym, p_sym, io_sys = ModelingToolkit.generate_control_function( - model, inputs, split=false; outputs + model, inputs, split=false, simplify=true ) if any(ModelingToolkit.is_alg_equation, equations(io_sys)) error("Systems with algebraic equations are not supported") @@ -98,10 +85,11 @@ function generate_f_h(model, inputs, outputs) end return nothing end - p = varmap_to_vars(defaults(io_sys), p_sym) + println(bindings(io_sys)) + p = varmap_to_vars(bindings(io_sys), p_sym) return f!, h!, p, x_sym, nu, nx, ny end -inputs, outputs = [mtk_model.τ], [mtk_model.y] +inputs, outputs = [τ], [y] f!, h!, p, x_sym, nu, nx, ny = generate_f_h(mtk_model, inputs, outputs) x_sym ``` @@ -121,8 +109,8 @@ model = setname!(NonLinModel(f!, h!, Ts, nu, nx, ny; p); u=vu, x=vx, y=vy) We also instantiate a plant model with a 25 % larger friction coefficient ``K``: ```@example 1 -@named mtk_plant = Pendulum(K=1.25*defaults(mtk_model)[mtk_model.K]) -mtk_plant = complete(mtk_plant) +plant_bindings = merge(bindings(mtk_model), Dict(K => 1.25 * bindings(mtk_model)[K])) +@named mtk_plant = System(eqs, t, [θ, ω, τ, y], [g, L, K, m]; bindings=plant_bindings) inputs, outputs = [mtk_plant.τ], [mtk_plant.y] f2!, h2!, p2 = generate_f_h(mtk_plant, inputs, outputs) plant = setname!(NonLinModel(f2!, h2!, Ts, nu, nx, ny; p=p2), u=vu, x=vx, y=vy) From b253406c08188b7cfc0f21a9d5c5c65a1a2e2264 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 25 Mar 2026 17:20:37 -0400 Subject: [PATCH 2/6] doc: updating MTK example to v11 --- docs/src/manual/mtk.md | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/docs/src/manual/mtk.md b/docs/src/manual/mtk.md index 3821d5fa8..6bb685ef7 100644 --- a/docs/src/manual/mtk.md +++ b/docs/src/manual/mtk.md @@ -30,7 +30,7 @@ We first construct and instantiate the pendulum model: ```@example 1 using ModelPredictiveControl, ModelingToolkit -using ModelingToolkit: D_nounits as D, t_nounits as t, varmap_to_vars +using ModelingToolkit: D_nounits as D, t_nounits as t @parameters g=9.8 L=0.4 K=1.2 m=0.3 @variables θ(t)=0 ω(t)=0 τ(t)=0 y(t) eqs = [ @@ -85,20 +85,27 @@ function generate_f_h(model, inputs, outputs) end return nothing end - println(bindings(io_sys)) - p = varmap_to_vars(bindings(io_sys), p_sym) - return f!, h!, p, x_sym, nu, nx, ny + ic = initial_conditions(io_sys) + p_map = Dict(sym => ic[sym] for sym in p_sym if haskey(ic, sym)) + p = ModelingToolkit.varmap_to_vars(p_map, p_sym) + return f!, h!, p, x_sym, p_sym, nu, nx, ny end inputs, outputs = [τ], [y] -f!, h!, p, x_sym, nu, nx, ny = generate_f_h(mtk_model, inputs, outputs) +f!, h!, p, x_sym, p_sym, nu, nx, ny = generate_f_h(mtk_model, inputs, outputs) x_sym ``` Since MTK is an acausal modeling framework, we do not have the control on the state realization chosen by the package. The content of `x_sym` above shows it settled for the state vector ``\mathbf{x}(t) = [\begin{smallmatrix}ω(t) && θ(t)\end{smallmatrix}]'``, -that is, the states of the [last section](@ref man_nonlin) in the reverse order. We can now -construct a [`NonLinModel`](@ref) with this specific state realization: +that is, the states of the [last section](@ref man_nonlin) in the reverse order. As the same +also applies for the parameters, the `p_sym` object informs on how the `p` vector is sorted: + +```@example 1 +[p_sym p] +``` + +We can now construct a [`NonLinModel`](@ref) with this specific state realization: ```@example 1 vu, vx, vy = ["\$τ\$ (Nm)"], ["\$ω\$ (rad/s)", "\$θ\$ (rad)"], ["\$θ\$ (°)"] @@ -106,14 +113,13 @@ Ts = 0.1 model = setname!(NonLinModel(f!, h!, Ts, nu, nx, ny; p); u=vu, x=vx, y=vy) ``` -We also instantiate a plant model with a 25 % larger friction coefficient ``K``: +We also instantiate a plant model with a 25 % larger friction coefficient ``K``, which is +the third element of `p`, as shown above: ```@example 1 -plant_bindings = merge(bindings(mtk_model), Dict(K => 1.25 * bindings(mtk_model)[K])) -@named mtk_plant = System(eqs, t, [θ, ω, τ, y], [g, L, K, m]; bindings=plant_bindings) -inputs, outputs = [mtk_plant.τ], [mtk_plant.y] -f2!, h2!, p2 = generate_f_h(mtk_plant, inputs, outputs) -plant = setname!(NonLinModel(f2!, h2!, Ts, nu, nx, ny; p=p2), u=vu, x=vx, y=vy) +p2 = copy(p) +p2[3] = 1.25*p[3] +plant = setname!(NonLinModel(f!, h!, Ts, nu, nx, ny; p=p2), u=vu, x=vx, y=vy) ``` ## Controller Design From 05d714cf162483327e73bcc8e13827aca09e2296 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 25 Mar 2026 17:37:30 -0400 Subject: [PATCH 3/6] doc: remove useless `haskey` --- docs/src/manual/mtk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/manual/mtk.md b/docs/src/manual/mtk.md index 6bb685ef7..ccb81ecea 100644 --- a/docs/src/manual/mtk.md +++ b/docs/src/manual/mtk.md @@ -86,7 +86,7 @@ function generate_f_h(model, inputs, outputs) return nothing end ic = initial_conditions(io_sys) - p_map = Dict(sym => ic[sym] for sym in p_sym if haskey(ic, sym)) + p_map = Dict(sym => ic[sym] for sym in p_sym) p = ModelingToolkit.varmap_to_vars(p_map, p_sym) return f!, h!, p, x_sym, p_sym, nu, nx, ny end From da3fbb63ef735d2b565f06131f5c4f360bf7c51f Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 25 Mar 2026 17:39:58 -0400 Subject: [PATCH 4/6] doc: remove `compat` admonition --- Project.toml | 2 +- docs/src/manual/mtk.md | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 4ce982d23..47531c58a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ModelPredictiveControl" uuid = "61f9bdb8-6ae4-484a-811f-bbf86720c31c" -version = "2.2.1" +version = "2.2.2" authors = ["Francis Gagnon"] [deps] diff --git a/docs/src/manual/mtk.md b/docs/src/manual/mtk.md index ccb81ecea..fcc71848e 100644 --- a/docs/src/manual/mtk.md +++ b/docs/src/manual/mtk.md @@ -22,10 +22,6 @@ the last section. as a basic starting template to combine both packages. There is no guarantee that it will work for all corner cases. -!!! compat - The example works on `ModelingToolkit.jl` v11 (corresponding to the following `[compat]` - entry: `ModelingToolkit = "11"`). - We first construct and instantiate the pendulum model: ```@example 1 From 1d566e4afa3281a501a2443fc853edbdc46040da Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 25 Mar 2026 17:58:41 -0400 Subject: [PATCH 5/6] changed: bump `MTK` compat in doc --- docs/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Project.toml b/docs/Project.toml index 32049a0fa..ed8b97618 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -18,5 +18,5 @@ JuMP = "1" LinearAlgebra = "1.10" LinearMPC = "0.8.0" Logging = "1.10" -ModelingToolkit = "10" +ModelingToolkit = "10, 11" Plots = "1" From 53c94faec7bd5cce8a76734617e17a6a028236d9 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 25 Mar 2026 18:14:58 -0400 Subject: [PATCH 6/6] doc: clear error for bounded parameters --- docs/src/manual/mtk.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/src/manual/mtk.md b/docs/src/manual/mtk.md index fcc71848e..fe367668d 100644 --- a/docs/src/manual/mtk.md +++ b/docs/src/manual/mtk.md @@ -82,7 +82,15 @@ function generate_f_h(model, inputs, outputs) return nothing end ic = initial_conditions(io_sys) - p_map = Dict(sym => ic[sym] for sym in p_sym) + p_map = try + Dict(sym => ic[sym] for sym in p_sym) + catch err + if err isa KeyError # the key presumably appears in `bindings(io_sys)`: + error("Non-constant parameter values are not supported (a.k.a. bindings)") + else + rethrow() + end + end p = ModelingToolkit.varmap_to_vars(p_map, p_sym) return f!, h!, p, x_sym, p_sym, nu, nx, ny end