@@ -77,3 +77,76 @@ prob = ODEProblem(sys, [], tspan, []; tofloat = false)
7777@test prob. p isa Tuple{Vector{Float64}, Vector{Int64}}
7878sol = solve (prob, ImplicitEuler ());
7979@test sol. retcode == ReturnCode. Success
80+
81+
82+
83+
84+
85+
86+ # ------------------------- Bug
87+ using ModelingToolkit, LinearAlgebra
88+ using ModelingToolkitStandardLibrary. Mechanical. Rotational
89+ using ModelingToolkitStandardLibrary. Blocks
90+ using ModelingToolkitStandardLibrary. Blocks: t
91+ using ModelingToolkit: connect
92+
93+ " A wrapper function to make symbolic indexing easier"
94+ function wr (sys)
95+ ODESystem (Equation[], ModelingToolkit. get_iv (sys), systems= [sys], name= :a_wrapper )
96+ end
97+ indexof (sym,syms) = findfirst (isequal (sym),syms)
98+
99+ # Parameters
100+ m1 = 1.
101+ m2 = 1.
102+ k = 10. # Spring stiffness
103+ c = 3. # Damping coefficient
104+
105+ @named inertia1 = Inertia (; J = m1)
106+ @named inertia2 = Inertia (; J = m2)
107+ @named spring = Spring (; c = k)
108+ @named damper = Damper (; d = c)
109+ @named torque = Torque (use_support= false )
110+
111+ function SystemModel (u= nothing ; name= :model )
112+ eqs = [
113+ connect (torque. flange, inertia1. flange_a)
114+ connect (inertia1. flange_b, spring. flange_a, damper. flange_a)
115+ connect (inertia2. flange_a, spring. flange_b, damper. flange_b)
116+ ]
117+ if u != = nothing
118+ push! (eqs, connect (torque. tau, u. output))
119+ return @named model = ODESystem (eqs, t; systems = [torque, inertia1, inertia2, spring, damper, u])
120+ end
121+ ODESystem (eqs, t; systems = [torque, inertia1, inertia2, spring, damper], name)
122+ end
123+
124+
125+ model = SystemModel () # Model with load disturbance
126+ @named d = Step (start_time= 1. , duration= 10. , offset= 0. , height= 1. ) # Disturbance
127+ model_outputs = [model. inertia1. w, model. inertia2. w, model. inertia1. phi, model. inertia2. phi] # This is the state realization we want to control
128+ inputs = [model. torque. tau. u]
129+ matrices, ssys = ModelingToolkit. linearize (wr (model), inputs, model_outputs)
130+
131+ # Design state-feedback gain using LQR
132+ # Define cost matrices
133+ x_costs = [
134+ model. inertia1. w => 1.
135+ model. inertia2. w => 1.
136+ model. inertia1. phi => 1.
137+ model. inertia2. phi => 1.
138+ ]
139+ L = randn (1 ,4 ) # Post-multiply by `C` to get the correct input to the controller
140+ @named state_feedback = MatrixGain (K= - L) # Build negative feedback into the feedback matrix
141+ @named add = Add (;k1= 1. , k2= 1. ) # To add the control signal and the disturbance
142+
143+ connections = [
144+ [state_feedback. input. u[i] ~ model_outputs[i] for i in 1 : 4 ]
145+ connect (d. output, :d , add. input1)
146+ connect (add. input2, state_feedback. output)
147+ connect (add. output, :u , model. torque. tau)
148+ ]
149+ closed_loop = ODESystem (connections, t, systems= [model, state_feedback, add, d], name= :closed_loop )
150+ S = get_sensitivity (closed_loop, :u )
151+
152+
0 commit comments