From 6928f51d52cbe613aa08d2bb55cbebc11e5af835 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Fri, 19 Sep 2025 08:55:38 -0400 Subject: [PATCH 1/2] Fix warnings in DC Motor PI tutorial MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add complete initial conditions for all state variables (L1.i, inertia.w, inertia.phi, pi_controller.int.x) to avoid underdetermined system warning - Add note about Pluto-specific variable naming requirements - Use unique variable names in sensitivity analysis to avoid conflicts Fixes #410 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- docs/src/tutorials/dc_motor_pi.md | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/src/tutorials/dc_motor_pi.md b/docs/src/tutorials/dc_motor_pi.md index e2190816..6f32a7f3 100644 --- a/docs/src/tutorials/dc_motor_pi.md +++ b/docs/src/tutorials/dc_motor_pi.md @@ -75,9 +75,20 @@ Now the model can be simulated. Typical rotational mechanical systems are descri (differential algebraic equations), however in this case, ModelingToolkit can simplify the model enough so that it can be represented as a system of `ODEs` (ordinary differential equations). +!!! note "Initial Conditions" + We provide complete initial conditions for all state variables to avoid initialization warnings. + These include the inductor current, inertia angular velocity and position, and the PI controller integrator state. + ```@example dc_motor_pi sys = mtkcompile(model) -prob = ODEProblem(sys, [sys.L1.i => 0.0], (0, 6.0)) +# Provide complete initial conditions for all state variables +u0 = Dict( + sys.L1.i => 0.0, # Initial inductor current + sys.inertia.w => 0.0, # Initial angular velocity + sys.inertia.phi => 0.0, # Initial angle + sys.pi_controller.int.x => 0.0 # Initial PI integrator state +) +prob = ODEProblem(sys, u0, (0, 6.0)) sol = solve(prob) p1 = plot(sol.t, sol[sys.inertia.w], ylabel = "Angular Vel. in rad/s", @@ -87,6 +98,11 @@ p2 = plot(sol.t, sol[sys.load.tau.u], ylabel = "Disturbance in Nm", label = "") plot(p1, p2, layout = (2, 1)) ``` +!!! note "Pluto Notebooks" + If you're using this example in a Pluto notebook, note that Pluto requires each variable to have a unique name. + If you encounter "Multiple definitions" errors, rename variables accordingly (e.g., `simplified_sys1`, `simplified_sys2`, etc.). + This is due to Pluto's reactive behavior where all variables must be uniquely named for automatic dependency tracking. + ## Closed-loop analysis When implementing and tuning a control system in simulation, it is a good practice to analyze the closed-loop properties and verify robustness of the closed-loop with respect to, e.g., modeling errors. To facilitate this, we added two analysis points to the set of connections above, more specifically, we added the analysis points named `:y` and `:u` to the connections (for more details on analysis points, see [Linear Analysis](@ref)) @@ -107,12 +123,14 @@ T(s) &= \dfrac{P(s)C(s)}{I + P(s)C(s)} ```@example dc_motor_pi using ControlSystemsBase +# Get sensitivity function matrices_S, -simplified_sys = Blocks.get_sensitivity( +simplified_sys_S = Blocks.get_sensitivity( model, :y, op = Dict(unknowns(sys) .=> 0.0)) So = ss(matrices_S...) |> minreal # The output-sensitivity function as a StateSpace system +# Get complementary sensitivity function matrices_T, -simplified_sys = Blocks.get_comp_sensitivity( +simplified_sys_T = Blocks.get_comp_sensitivity( model, :y, op = Dict(unknowns(sys) .=> 0.0)) To = ss(matrices_T...)# The output complementary sensitivity function as a StateSpace system bodeplot([So, To], label = ["S" "T"], plot_title = "Sensitivity functions", @@ -123,7 +141,7 @@ Similarly, we may compute the loop-transfer function and plot its Nyquist curve ```@example dc_motor_pi matrices_L, -simplified_sys = Blocks.get_looptransfer( +simplified_sys_L = Blocks.get_looptransfer( model, :y, op = Dict(unknowns(sys) .=> 0.0)) L = -ss(matrices_L...) # The loop-transfer function as a StateSpace system. The negative sign is to negate the built-in negative feedback Ms, ωMs = hinfnorm(So) # Compute the peak of the sensitivity function to draw a circle in the Nyquist plot From 6da4fa985a97284802a190e4422ac4070030725c Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sun, 5 Oct 2025 08:47:45 -0400 Subject: [PATCH 2/2] Update dc_motor_pi.md --- docs/src/tutorials/dc_motor_pi.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docs/src/tutorials/dc_motor_pi.md b/docs/src/tutorials/dc_motor_pi.md index 6f32a7f3..1ebc59f4 100644 --- a/docs/src/tutorials/dc_motor_pi.md +++ b/docs/src/tutorials/dc_motor_pi.md @@ -75,10 +75,6 @@ Now the model can be simulated. Typical rotational mechanical systems are descri (differential algebraic equations), however in this case, ModelingToolkit can simplify the model enough so that it can be represented as a system of `ODEs` (ordinary differential equations). -!!! note "Initial Conditions" - We provide complete initial conditions for all state variables to avoid initialization warnings. - These include the inductor current, inertia angular velocity and position, and the PI controller integrator state. - ```@example dc_motor_pi sys = mtkcompile(model) # Provide complete initial conditions for all state variables @@ -98,11 +94,6 @@ p2 = plot(sol.t, sol[sys.load.tau.u], ylabel = "Disturbance in Nm", label = "") plot(p1, p2, layout = (2, 1)) ``` -!!! note "Pluto Notebooks" - If you're using this example in a Pluto notebook, note that Pluto requires each variable to have a unique name. - If you encounter "Multiple definitions" errors, rename variables accordingly (e.g., `simplified_sys1`, `simplified_sys2`, etc.). - This is due to Pluto's reactive behavior where all variables must be uniquely named for automatic dependency tracking. - ## Closed-loop analysis When implementing and tuning a control system in simulation, it is a good practice to analyze the closed-loop properties and verify robustness of the closed-loop with respect to, e.g., modeling errors. To facilitate this, we added two analysis points to the set of connections above, more specifically, we added the analysis points named `:y` and `:u` to the connections (for more details on analysis points, see [Linear Analysis](@ref))