Skip to content

Commit 3336938

Browse files
committed
Functions for quick setup of test systems: ssrand and systemdepot
1 parent 3f243c0 commit 3336938

File tree

4 files changed

+154
-1
lines changed

4 files changed

+154
-1
lines changed

src/ControlSystems.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ export LTISystem,
7676
# delay systems
7777
delay,
7878
pade,
79+
# demo systems
80+
ssrand,
81+
systemdepot,
7982
# utilities
8083
num, #Deprecated
8184
den, #Deprecated
@@ -93,7 +96,7 @@ using OrdinaryDiffEq, DelayDiffEq
9396
export Plots
9497
import Base: +, -, *, /, (==), (!=), isapprox, convert, promote_op
9598
import Base: getproperty
96-
import Base: exp # for exp(-)
99+
import Base: exp # for exp(-s)
97100
import LinearAlgebra: BlasFloat
98101
export lyap # Make sure LinearAlgebra.lyap is available
99102
import Printf, Colors
@@ -143,6 +146,8 @@ include("synthesis.jl")
143146
include("simulators.jl")
144147
include("pid_design.jl")
145148

149+
include("demo_systems.jl")
150+
146151
include("delay_systems.jl")
147152

148153
include("plotting.jl")

src/demo_systems.jl

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
"""
2+
ssrand(T::Type, ny::Int, nu::Int, nstates::Int; proper=false, stable=true, Ts=nothing)
3+
4+
Returns a random `StateSpace` model with `ny` outputs, `nu` inputs, and `nstates` states,
5+
whose matrix elements are normally distributed.
6+
7+
It is possible to specify if the system should be `proper` or `stable`.
8+
9+
Specify a sample time `Ts` to obtain a discrete-time system.
10+
"""
11+
function ssrand(T::Type, ny::Int, nu::Int, nstates::Int; proper=false, stable=true, Ts=nothing)
12+
A = randn(T, nstates, nstates)
13+
if stable
14+
Λ = eigvals(A)
15+
A = isnothing(Ts) ? A - 1.1*maximum(real(Λ))*I : A*0.9/maximum(abs.(Λ))
16+
end
17+
18+
B = randn(T, nstates, nu)
19+
C = randn(T, ny, nstates)
20+
D = (proper ? zeros(T, ny, nu) : randn(T, ny, nu))
21+
return isnothing(Ts) ? StateSpace(A, B, C, D) : StateSpace(A, B, C, D, Ts)
22+
end
23+
ssrand(ny::Int, nu::Int, nstates::Int; kwargs...) = ssrand(Float64, ny::Int, nu::Int, nstates::Int; kwargs...)
24+
ssrand(n; kwargs...) = ssrand(n, n, 2*n; kwargs...)
25+
ssrand(T::Type, n; kwargs...) = ssrand(T, n, n, 2*n; kwargs...)
26+
27+
28+
"""
29+
systemdepot(sysname::String; Ts=nothing, kwargs...)
30+
31+
Convenience function for setting up some different systems
32+
that are commonly used as examples in the control literature.
33+
34+
Change the default parameter values by using keyword arguments.
35+
36+
SISO systems
37+
============
38+
1) `fo` First-order system `1/(sT+1)`
39+
2) `fotd` First-order system with time-delay `exp(-sτ)/(sT+1)`
40+
3) `sotd` Second-order non-resonant system with time-delay `exp(-sτ)/(sT+1)/(sT2 + 1)`
41+
4) `resonant` Second-order resonant systems `ω0^2/(s^2 + 2ζ*ω0*s + ω0^2)`
42+
43+
MIMO systems
44+
============
45+
5) `woodberry` Wood--Berry distillation column
46+
6) `doylesat` Doyle's spinning body example
47+
"""
48+
function systemdepot(sysname::String; Ts=nothing, kwargs...)
49+
if sysname == "woodberry" # The Wood--Berry distillation column
50+
sys = woodberry(;kwargs...)
51+
elseif sysname == "fotd"
52+
sys = fotd(;kwargs...)
53+
elseif sysname == "sotd"
54+
sys = sotd(;kwargs...)
55+
elseif sysname == "fo"
56+
sys = first_order_system(;kwargs...)
57+
elseif sysname == "resonant"
58+
sys = resonant(;kwargs...)
59+
elseif sysname == "doylesat"
60+
sys = doylesat(;kwargs...)
61+
else
62+
error("Unknown system name: $sysname")
63+
end
64+
65+
if isnothing(Ts)
66+
return sys
67+
else
68+
Tsc2d(sys, Ts)
69+
end
70+
end
71+
72+
first_order_system(;T=1) = ss(-1/T, 1, 1/T, 0)
73+
fotd(;T=1, τ=1) = ss(-1/T, 1, 1/T, 0) * delay(τ)
74+
sotd(;T=1, T2=10, τ=1) = ss(-1/T, 1, 1/T, 0)*ss(-1/T2, 1, 1/T2, 0)*delay(τ)
75+
resonant(;ω0=1, ζ=0.25) = ss([-ζ -ω0; ω0 -ζ], [ω0; 0], [0 ω0], 0) # QUESTION: Is this the form that we like? Perhhaps not.
76+
77+
78+
"""
79+
Doyle's spinning body (satellite) example
80+
======================
81+
A classic example that illustrates that robustness analysis of MIMO systems
82+
is more involved than for SISO systems.
83+
84+
*References:*
85+
86+
**Zhou, K., J. C. Doyle, and K. Glover**, Robust and optimal control,
87+
Prentice hall (NJ), 1996.
88+
89+
**Skogestad, S, and I. Postlethwaite**, Multivariable feedback control:
90+
analysis and design, Wiley (NY), 2007.
91+
"""
92+
doylesat(;a=10) = ss([0 a; -a 0], I(2), [1 a; -a 1], 0)
93+
94+
95+
"""
96+
Wood--Berry distillation column
97+
======================
98+
A classic example from the literature on process control of MIMO process.
99+
100+
*References:*
101+
102+
**Wood, R. K., and M. W. Berry**, Terminal composition control of a binary
103+
distillation column, Chemical Engineering Science, 28.9, 1973, pp. 1707-1717.
104+
105+
"""
106+
function woodberry()
107+
s = tf("s")
108+
return [12.8/(1 + 16.7*s)*delay(1.0) -18.9/(1 + 21*s) * delay(3.0)
109+
6.6/(1 + 10.9*s) * delay(7.0) -19.4/(1 + 14.4*s) * delay(3.0)]
110+
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ my_tests = [
2727
"test_lqg",
2828
"test_synthesis",
2929
"test_partitioned_statespace",
30+
"test_demo_systems",
3031
]
3132

3233

test/test_demo_systems.jl

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@testset "test_demosystems" begin
2+
3+
4+
# Just some very simple tests of systemdepot
5+
@test size(systemdepot("woodberry")) == (2,2)
6+
@test size(systemdepot("fotd")) == (1,1)
7+
@test size(systemdepot("fotd")) == (1,1)
8+
@test freqresp(systemdepot("fotd", τ=2, T=5), [0.0])[:] == [1.0]
9+
10+
11+
Random.seed!(10)
12+
13+
sys = ssrand(1,proper=true)
14+
@test size(sys) == (1,1)
15+
@test ControlSystems.nstates(sys) == 2
16+
@test iszero(sys.D)
17+
18+
sys = ssrand(2,2,5,proper=false,stable=true)
19+
@test size(sys) == (2,2)
20+
@test ControlSystems.nstates(sys) == 5
21+
@test isstable(sys)
22+
@test !iszero(sys.D)
23+
24+
Random.seed!(20)
25+
sys = ssrand(2,2,5,stable=false)
26+
@test !isstable(sys)
27+
28+
sys = ssrand(2,2,5,proper=false,stable=true, Ts=0.5)
29+
@test size(sys) == (2,2)
30+
@test ControlSystems.nstates(sys) == 5
31+
@test isstable(sys)
32+
@test !iszero(sys.D)
33+
34+
sys = ssrand(2,2,5,proper=false,stable=false, Ts=0.5)
35+
@test !isstable(sys)
36+
37+
end

0 commit comments

Comments
 (0)