Skip to content

Commit fc6c413

Browse files
add parameters to PID controllers (#336)
* add parameters to PID controllers * workaround for scoping issue * remove a_end parameter * test: fix depwarn * format --------- Co-authored-by: Aayush Sabharwal <[email protected]>
1 parent 37b5157 commit fc6c413

File tree

4 files changed

+52
-30
lines changed

4 files changed

+52
-30
lines changed

src/Blocks/continuous.jl

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -258,13 +258,21 @@ See also [`LimPID`](@ref)
258258
with_D = !isequal(Td, false)
259259
@named err_input = RealInput() # control error
260260
@named ctr_output = RealOutput() # control signal
261-
!isequal(Ti, false) &&
262-
(Ti 0 || throw(ArgumentError("Ti out of bounds, got $(Ti) but expected Ti ≥ 0")))
263-
!isequal(Td, false) &&
264-
(Td 0 || throw(ArgumentError("Td out of bounds, got $(Td) but expected Td ≥ 0")))
265-
Nd > 0 || throw(ArgumentError("Nd out of bounds, got $(Nd) but expected Nd > 0"))
261+
@symcheck Ti 0 ||
262+
throw(ArgumentError("Ti out of bounds, got $(Ti) but expected Ti ≥ 0"))
263+
@symcheck Td 0 ||
264+
throw(ArgumentError("Td out of bounds, got $(Td) but expected Td ≥ 0"))
265+
@symcheck Nd > 0 ||
266+
throw(ArgumentError("Nd out of bounds, got $(Nd) but expected Nd > 0"))
267+
268+
pars = @parameters begin
269+
k = k, [description = "Proportional gain"]
270+
Ti = Ti, [description = "Integrator time constant"]
271+
Td = Td, [description = "Derivative time constant"]
272+
Nd = Nd, [description = "Derivative limit"]
273+
end
266274

267-
@named gainPID = Gain(k)
275+
@named gainPID = Gain(; k)
268276
@named addPID = Add3()
269277
if with_I
270278
@named int = Integrator(k = 1 / Ti, x = int__x)
@@ -304,7 +312,7 @@ See also [`LimPID`](@ref)
304312
else
305313
push!(eqs, connect(Dzero.output, addPID.input3))
306314
end
307-
ODESystem(eqs, t, [], []; name = name, systems = sys)
315+
ODESystem(eqs, t, [], pars; name = name, systems = sys)
308316
end
309317

310318
"""
@@ -334,15 +342,22 @@ The simplified expression above is given without the anti-windup protection.
334342
throw(ArgumentError("Time constant `Ta` has to be strictly positive"))
335343
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
336344
@symcheck u_max u_min || throw(ArgumentError("u_min must be smaller than u_max"))
345+
pars = @parameters begin
346+
k = k, [description = "Proportional gain"]
347+
T = T, [description = "Integrator time constant"]
348+
Ta = Ta, [description = "Tracking time constant"]
349+
u_max = u_max, [description = "Upper saturation limit"]
350+
u_min = u_min, [description = "Lower saturation limit"]
351+
end
337352
@named err_input = RealInput() # control error
338353
@named ctr_output = RealOutput() # control signal
339-
@named gainPI = Gain(k)
354+
@named gainPI = Gain(; k)
340355
@named addPI = Add()
341356
@named addTrack = Add()
342357
@named int = Integrator(k = 1 / T, x = int__x)
343358
@named limiter = Limiter(y_max = u_max, y_min = u_min)
344359
@named addSat = Add(k1 = 1, k2 = -1)
345-
@named gainTrack = Gain(1 / Ta)
360+
@named gainTrack = Gain(k = 1 / Ta)
346361
sys = [err_input, ctr_output, gainPI, addPI, int, addTrack, limiter, addSat, gainTrack]
347362
eqs = [
348363
connect(err_input, addPI.input1),
@@ -357,7 +372,7 @@ The simplified expression above is given without the anti-windup protection.
357372
connect(addTrack.output, int.input),
358373
connect(int.output, addPI.input2)
359374
]
360-
ODESystem(eqs, t, [], []; name = name, systems = sys)
375+
ODESystem(eqs, t, [], pars; name = name, systems = sys)
361376
end
362377

363378
"""
@@ -408,18 +423,25 @@ where the transfer function for the derivative includes additional filtering, se
408423
Ti = k / Ti
409424
Td = Td / k
410425
end
411-
0 wp 1 ||
412-
throw(ArgumentError("wp out of bounds, got $(wp) but expected wp ∈ [0, 1]"))
413-
0 wd 1 ||
414-
throw(ArgumentError("wd out of bounds, got $(wd) but expected wd ∈ [0, 1]"))
415-
!isequal(Ti, false) &&
416-
(Ti 0 || throw(ArgumentError("Ti out of bounds, got $(Ti) but expected Ti ≥ 0")))
417-
!isequal(Td, false) &&
418-
(Td 0 || throw(ArgumentError("Td out of bounds, got $(Td) but expected Td ≥ 0")))
426+
@symcheck Ti 0 ||
427+
throw(ArgumentError("Ti out of bounds, got $(Ti) but expected Ti ≥ 0"))
428+
@symcheck Td 0 ||
429+
throw(ArgumentError("Td out of bounds, got $(Td) but expected Td ≥ 0"))
419430
@symcheck u_max u_min || throw(ArgumentError("u_min must be smaller than u_max"))
420431
@symcheck Nd > 0 ||
421432
throw(ArgumentError("Nd out of bounds, got $(Nd) but expected Nd > 0"))
422433

434+
pars = @parameters begin
435+
k = k, [description = "Proportional gain"]
436+
Ti = Ti, [description = "Integrator time constant"]
437+
Td = Td, [description = "Derivative time constant"]
438+
wp = wp, [description = "Set-point weighting in the proportional part"]
439+
wd = wd, [description = "Set-point weighting in the derivative part"]
440+
Ni = Ni, [description = "Anti-windup tracking gain"]
441+
Nd = Nd, [description = "Derivative limit"]
442+
u_max = u_max, [description = "Upper saturation limit"]
443+
u_min = u_min, [description = "Lower saturation limit"]
444+
end
423445
@named reference = RealInput()
424446
@named measurement = RealInput()
425447
@named ctr_output = RealOutput() # control signal
@@ -431,7 +453,7 @@ where the transfer function for the derivative includes additional filtering, se
431453
if with_AWM
432454
@named addI = Add3(k1 = 1, k2 = -1, k3 = 1)
433455
@named addSat = Add(k1 = 1, k2 = -1)
434-
@named gainTrack = Gain(1 / (k * Ni))
456+
@named gainTrack = Gain(k = 1 / (k * Ni))
435457
else
436458
@named addI = Add(k1 = 1, k2 = -1)
437459
end
@@ -492,7 +514,7 @@ where the transfer function for the derivative includes additional filtering, se
492514
push!(eqs, connect(Dzero.output, addPID.input2))
493515
end
494516

495-
ODESystem(eqs, t, [], []; name = name, systems = sys)
517+
ODESystem(eqs, t, [], pars; name = name, systems = sys)
496518
end
497519

498520
"""
@@ -611,13 +633,13 @@ See also [`StateSpace`](@ref) which handles MIMO systems, as well as [ControlSys
611633
description = "Denominator coefficients of transfer function (e.g., `s² + 2ωs + ω^2` is specified as [1, 2ω, ω^2])"
612634
]
613635
bb[1:(nbb + nb)] = [zeros(nbb); b]
614-
d = bb[1] / a[1], [description = "Direct feedthrough gain"]
615636
end
637+
d = bb[1] / a[1]# , [description = "Direct feedthrough gain"]
616638

617639
a = collect(a)
618-
@parameters a_end = ifelse(a[end] > 100 * symbolic_eps(sqrt(a' * a)), a[end], 1.0)
640+
a_end = ifelse(a[end] > 100 * symbolic_eps(sqrt(a' * a)), a[end], 1.0)
619641

620-
pars = [collect(b); a; collect(bb); d; a_end]
642+
pars = [collect(b); a; collect(bb)]
621643
@variables begin
622644
x(t)[1:nx] = zeros(nx),
623645
[description = "State of transfer function on controller canonical form"]

src/Blocks/nonlinear.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Limit the range of a signal.
1919
@component function Limiter(; name, y_max, y_min = y_max > 0 ? -y_max : -Inf)
2020
@symcheck y_max y_min || throw(ArgumentError("`y_min` must be smaller than `y_max`"))
2121
m = (y_max + y_min) / 2
22-
@named siso = SISO(u_start = m, y_start = m) # Default signals to center of saturation to minimize risk of saturation while linearizing etc.
22+
siso = SISO(u_start = m, y_start = m, name = :siso) # Default signals to center of saturation to minimize risk of saturation while linearizing etc.
2323
@unpack u, y = siso
2424
pars = @parameters y_max=y_max [description = "Maximum allowed output of Limiter $name"] y_min=y_min [
2525
description = "Minimum allowed output of Limiter $name"

test/Blocks/continuous.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ end
430430
@named pt1 = TransferFunction(b = [1.2], a = [3.14, 1])
431431
@named iosys = ODESystem(connect(c.output, pt1.input), t, systems = [pt1, c])
432432
sys = structural_simplify(iosys)
433-
prob = ODEProblem(sys, Pair[pt1.a_end => 1], (0.0, 100.0))
433+
prob = ODEProblem(sys, Pair[], (0.0, 100.0))
434434
sol = solve(prob, Rodas4())
435435
@test sol.retcode == Success
436436
@test sol[pt1.output.u]pt1_func.(sol.t, 1.2, 3.14) atol=1e-3
@@ -440,7 +440,7 @@ end
440440
@named pt1 = TransferFunction(b = [1.2], a = [3.14, 0])
441441
@named iosys = ODESystem(connect(c.output, pt1.input), t, systems = [pt1, c])
442442
sys = structural_simplify(iosys)
443-
prob = ODEProblem(sys, Pair[pt1.a_end => 1], (0.0, 100.0))
443+
prob = ODEProblem(sys, Pair[], (0.0, 100.0))
444444
sol = solve(prob, Rodas4())
445445
@test sol.retcode == Success
446446
@test sol[pt1.output.u] sol.t .* (1.2 / 3.14)
@@ -464,7 +464,7 @@ end
464464
@named pt1 = TransferFunction(b = [w^2], a = [1, 2d * w, w^2])
465465
@named iosys = ODESystem(connect(c.output, pt1.input), t, systems = [pt1, c])
466466
sys = structural_simplify(iosys)
467-
prob = ODEProblem(sys, Pair[pt1.a_end => 1], (0.0, 100.0))
467+
prob = ODEProblem(sys, Pair[], (0.0, 100.0))
468468
sol = solve(prob, Rodas4())
469469
@test sol.retcode == Success
470470
@test sol[pt1.output.u]pt2_func.(sol.t, k, w, d) atol=1e-3
@@ -474,7 +474,7 @@ end
474474
@named pt1 = TransferFunction(b = [1, 0], a = [1, 1])
475475
@named iosys = ODESystem(connect(c.output, pt1.input), t, systems = [pt1, c])
476476
sys = structural_simplify(iosys)
477-
prob = ODEProblem(sys, Pair[pt1.a_end => 1], (0.0, 100.0))
477+
prob = ODEProblem(sys, Pair[], (0.0, 100.0))
478478
sol = solve(prob, Rodas4())
479479
@test sol.retcode == Success
480480
@test sol[pt1.output.u]1 .- pt1_func.(sol.t, 1, 1) atol=1e-3
@@ -484,7 +484,7 @@ end
484484
@named pt1 = TransferFunction(b = [2.7], a = [pi])
485485
@named iosys = ODESystem(connect(c.output, pt1.input), t, systems = [pt1, c])
486486
sys = structural_simplify(iosys)
487-
prob = ODEProblem(sys, Pair[pt1.a_end => 1], (0.0, 100.0))
487+
prob = ODEProblem(sys, Pair[], (0.0, 100.0))
488488
sol = solve(prob, Rodas4())
489489
@test sol.retcode == Success
490490
@test all(==(2.7 / pi), sol[pt1.output.u])

test/Mechanical/translational_modelica.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,5 @@ end
105105
prob = ODEProblem(sys, [], (0, 2pi))
106106
sol = solve(prob, Rodas4())
107107
tv = 0:0.1:(2pi)
108-
@test sol(tv, idxs = sys.mass.s)@.(2sin(2pi * tv * 3)) atol=1e-2
108+
@test sol(tv, idxs = sys.mass.s).u@.(2sin(2pi * tv * 3)) atol=1e-2
109109
end

0 commit comments

Comments
 (0)