Skip to content

Commit de10475

Browse files
authored
Merge pull request #93 from JuliaControl/low_meas
add options to disturbance augmentation
2 parents ddcbb08 + adcb54b commit de10475

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

src/model_augmentation.jl

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ end
2323

2424
"""
2525
add_measurement_disturbance(sys::StateSpace{Continuous}, Ad::Matrix, Cd::Matrix)
26+
27+
Create the system
28+
```
29+
Ae = [A 0; 0 Ad]
30+
Be = [B; 0]
31+
Ce = [C Cd]
32+
```
2633
"""
2734
function add_measurement_disturbance(sys::AbstractStateSpace, Ad::AbstractMatrix, Cd::AbstractMatrix)
2835
A,B,C,D = ControlSystemsBase.ssdata(sys)
@@ -52,23 +59,28 @@ end
5259

5360
"""
5461
add_low_frequency_disturbance(sys::StateSpace; ϵ = 0, measurement = false)
62+
add_low_frequency_disturbance(sys::StateSpace, Cd; ϵ = 0, measurement = false)
5563
5664
Augment `sys` with a low-frequency (integrating if `ϵ=0`) disturbance model.
5765
If an integrating input disturbance is used together with an observer, the controller will have integral action.
5866
67+
- `Cd`: If adding an input disturbance. this matrix indicates how the disturbance states affect the states of `sys`, and defaults to `sys.B`. If `measurement=true`, this matrix indicates how the disturbance states affect the outputs of `sys`, and defaults to `I(sys.ny)`.
68+
5969
# Arguments:
6070
- `ϵ`: Move the integrator pole `ϵ` into the stable region.
6171
- `measurement`: If true, the disturbance is a measurement disturbance, otherwise it's an input diturbance.
6272
"""
63-
function add_low_frequency_disturbance(sys::AbstractStateSpace; ϵ=0, measurement=false)
73+
function add_low_frequency_disturbance(sys::AbstractStateSpace, Cd::Union{Nothing, AbstractMatrix} = nothing; ϵ=0, measurement=false)
6474
nx,nu,ny = sys.nx,sys.nu,sys.ny
65-
Ad = -ϵ*I(nu)
66-
isdiscrete(sys) && (Ad += I)
6775
if measurement
68-
Cd = I(nu)
76+
Ad = -ϵ*I(ny)
77+
isdiscrete(sys) && (Ad += I)
78+
Cd === nothing && (Cd = I(ny))
6979
add_measurement_disturbance(sys, Ad, Cd)
7080
else
71-
Cd = sys.B
81+
Ad = -ϵ*I(nu)
82+
isdiscrete(sys) && (Ad += I)
83+
Cd === nothing && (Cd = sys.B)
7284
add_disturbance(sys, Ad, Cd)
7385
end
7486
end

test/test_augmentation.jl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,42 @@ Gd.C[end] == 1
1515
@test rank(ctrb(Gd)) == 3
1616
@test any(isapprox(0, atol=eps()), poles(Gd))
1717

18+
G = ssrand(4,2,3, proper=true)
19+
Gd = add_low_frequency_disturbance(G)
20+
@test Gd.nx == G.nx + G.nu
21+
@test rank(obsv(Gd)) == Gd.nx
22+
@test rank(ctrb(Gd)) == G.nx
23+
@test any(isapprox(0, atol=eps()), poles(Gd))
24+
@test Gd.A[end-1:end, end-1:end] == 0I
25+
26+
G = ssrand(2,4,3, proper=true)
27+
Gd = add_low_frequency_disturbance(G, measurement=true)
28+
@test Gd.nx == G.nx + G.ny
29+
@test rank(obsv(Gd)) == G.nx + G.ny
30+
@test rank(ctrb(Gd)) == G.nx
31+
@test any(isapprox(0, atol=eps()), poles(Gd))
32+
@test Gd.C[:, end-1:end] == I
33+
@test Gd.A[end-1:end, end-1:end] == 0I
34+
35+
# Discrete time
36+
G = ssrand(4,2,3, proper=true, Ts=0.1)
37+
Gd = add_low_frequency_disturbance(G)
38+
@test Gd.nx == G.nx + G.nu
39+
@test rank(obsv(Gd)) == Gd.nx
40+
@test rank(ctrb(Gd)) == G.nx
41+
@test any(isapprox(1, atol=eps()), poles(Gd))
42+
@test Gd.A[end-1:end, end-1:end] == I
43+
44+
G = ssrand(2,4,3, proper=true, Ts=0.1)
45+
Gd = add_low_frequency_disturbance(G, measurement=true)
46+
@test Gd.nx == G.nx + G.ny
47+
@test rank(obsv(Gd)) == G.nx + G.ny
48+
@test rank(ctrb(Gd)) == G.nx
49+
@test any(isapprox(1, atol=eps()), poles(Gd))
50+
@test Gd.C[:, end-1:end] == I
51+
@test Gd.A[end-1:end, end-1:end] == I
52+
53+
1854
G = ssrand(1,1,3, proper=true)
1955
Gd = add_resonant_disturbance(G, 1, 0, 3)
2056
@test Gd.nx == 5

0 commit comments

Comments
 (0)