Skip to content

Commit e56de20

Browse files
author
Brad Carman
committed
split parameters linearize bug
1 parent 1aa4806 commit e56de20

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

test/split_parameters.jl

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,76 @@ prob = ODEProblem(sys, [], tspan, []; tofloat = false)
7777
@test prob.p isa Tuple{Vector{Float64}, Vector{Int64}}
7878
sol = 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

Comments
 (0)