From e409e77a7d91b353b63dc7209fbf73b15295ab89 Mon Sep 17 00:00:00 2001 From: olof3 Date: Thu, 13 May 2021 16:00:36 +0200 Subject: [PATCH 1/7] Add tests for place. --- test/test_synthesis.jl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/test_synthesis.jl b/test/test_synthesis.jl index 457077a86..edb4b4610 100644 --- a/test/test_synthesis.jl +++ b/test/test_synthesis.jl @@ -57,6 +57,30 @@ z5,p5,k5 = zpkdata(ffb5) end + +@testset "place" begin + sys = ss(-4, 2, 3, 0) + A, B, C, _ = ssdata(sys) + + place(A, B, [-10]) == [3][:,:] + + A = [0 1; 0 0] + B = [0; 1] + C = [1 0] + sys = ss(A, B, C, 0) + + @test place(A, B, [-1.0, -1]) ≈ [1 2] + @test place(sys, [-1.0, -1]) ≈ [1 2] + + @test place(A, B, [-2 + im, -2 - im]) ≈ [5 4] + + A = ones(3,3) - diagm([3, 4, 5]) + B = [1; 0; 2] + C = [1 1 0] + @test place(A, B, [-2 + 2im, -2 - 2im, -4]) ≈ [-2.6 5.2 0.8] +end + + @testset "acker" begin Random.seed!(0) A = randn(3,3) From c83884379b4a79b4cb84dda8359dffb0e4b790c0 Mon Sep 17 00:00:00 2001 From: olof3 Date: Thu, 13 May 2021 16:11:53 +0200 Subject: [PATCH 2/7] Removed luenberger and updated improved place instead. --- src/ControlSystems.jl | 3 +- src/synthesis.jl | 63 +++++++++++++++++++++++------------------- test/test_synthesis.jl | 10 ++++++- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/ControlSystems.jl b/src/ControlSystems.jl index 244583d16..59dfa6aa0 100644 --- a/src/ControlSystems.jl +++ b/src/ControlSystems.jl @@ -32,7 +32,6 @@ export LTISystem, ctrb, obsv, place, - luenberger, # Model Simplification reduce_sys, sminreal, @@ -173,6 +172,8 @@ include("plotting.jl") @deprecate den denvec @deprecate norminf hinfnorm @deprecate diagonalize(s::AbstractStateSpace, digits) diagonalize(s::AbstractStateSpace) +@deprecate luenberger(sys, p) place(sys, p, :o) +@deprecate luenberger(A, C, p) place(A, C, p, :o) # There are some deprecations in pid_control.jl for laglink/leadlink/leadlinkat function covar(D::Union{AbstractMatrix,UniformScaling}, R) diff --git a/src/synthesis.jl b/src/synthesis.jl index 8228ea960..d5090e3bc 100644 --- a/src/synthesis.jl +++ b/src/synthesis.jl @@ -119,45 +119,52 @@ Calculate the optimal Kalman gain for discrete time systems dkalman(A, C, R1,R2) = Matrix(dlqr(A',C',R1,R2)') """ - place(A, B, p) - place(sys::StateSpace, p) + place(A, B, p, opt=:c) + place(sys::StateSpace, p, opt=:c) -Calculate gain matrix `K` such that -the poles of `(A-BK)` in are in `p`. +Calculate the gain matrix `K` such that `A - BK` has eigenvalues `p`. + + place(A, C, p, opt=:o) + place(sys::StateSpace, p, opt=:o) + +Calculate the observer gain matrix `L` such that `A - LC` has eigenvalues `p`. Uses Ackermann's formula. -For observer pole placement, see `luenberger`. +Currently handles only SISO systems. """ -function place(A, B, p) +function place(A, B, p, opt=:c) n = length(p) - n != size(A,1) && error("Must define as many poles as states") - n != size(B,1) && error("A and B must have same number of rows") - if size(B,2) == 1 - acker(A,B,p) + n != size(A,1) && error("Must specify as many poles as states") + if opt == :c + n != size(B,1) && error("A and B must have same number of rows") + if size(B,2) == 1 + acker(A, B, p) + else + error("place only implemented for SISO systems") + end + elseif opt == :o + C = B # B is really the "C matrix" + n != size(C,2) && error("A and C must have same number of rows") + if size(C,1) == 1 + acker(A', C', p)' + else + error("place only implemented for SISO systems") + end else - error("place only implemented for SISO systems") + error("fourth argument must be :c or :o") end end - -function place(sys::StateSpace, p) - return place(sys.A, sys.B, p) +function place(sys::StateSpace, p, opt=:c) + if opt == :c + return place(sys.A, sys.B, p, opt) + elseif opt == :o + return place(sys.A, sys.C, p, opt) + else + error("third argument must be :c or :o") + end end -""" - luenberger(A, C, p) - luenberger(sys::StateSpace, p) -Calculate gain matrix `L` such that the poles of `(A - LC)` are in `p`. -Uses sytem's dual form (Controllability-Observability duality) applied to Ackermann's formula. -That is, `(A - BK)` is indentic to `(A' - C'L') == (A - LC)`. -""" -function luenberger(A, C, p) - place(A', C', p)' -end - -function luenberger(sys::StateSpace, p) - return luenberger(sys.A, sys.C, p) -end #Implements Ackermann's formula for placing poles of (A-BK) in p function acker(A,B,P) diff --git a/test/test_synthesis.jl b/test/test_synthesis.jl index edb4b4610..6cfa2bbc7 100644 --- a/test/test_synthesis.jl +++ b/test/test_synthesis.jl @@ -62,7 +62,9 @@ end sys = ss(-4, 2, 3, 0) A, B, C, _ = ssdata(sys) - place(A, B, [-10]) == [3][:,:] + @test place(A, B, [-10]) == [3][:,:] + @test place(A, B, [-10], :c) == [3][:,:] + @test place(A, C, [-10], :o) == [2][:,:] A = [0 1; 0 0] B = [0; 1] @@ -71,13 +73,19 @@ end @test place(A, B, [-1.0, -1]) ≈ [1 2] @test place(sys, [-1.0, -1]) ≈ [1 2] + @test place(A, B, [-1.0, -1], :c) ≈ [1 2] + @test place(sys, [-1.0, -1], :c) ≈ [1 2] + @test place(A, C, [-2.0, -2], :o) ≈ [4; 4] + @test place(sys, [-2.0, -2], :o) ≈ [4; 4] @test place(A, B, [-2 + im, -2 - im]) ≈ [5 4] + @test place(A, C, [-4 + 2im, -4 - 2im], :o) ≈ [8; 20] A = ones(3,3) - diagm([3, 4, 5]) B = [1; 0; 2] C = [1 1 0] @test place(A, B, [-2 + 2im, -2 - 2im, -4]) ≈ [-2.6 5.2 0.8] + @test place(A, C, [-2 + 3im, -2 - 3im, -4], :o) ≈ [11; -12; 1] end From cae59e3851eca24dece3c896c566d0154178e54b Mon Sep 17 00:00:00 2001 From: olof3 Date: Thu, 13 May 2021 22:12:52 +0200 Subject: [PATCH 3/7] Update src/synthesis.jl Co-authored-by: Fredrik Bagge Carlson --- src/synthesis.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/synthesis.jl b/src/synthesis.jl index d5090e3bc..d77052631 100644 --- a/src/synthesis.jl +++ b/src/synthesis.jl @@ -135,7 +135,7 @@ Currently handles only SISO systems. function place(A, B, p, opt=:c) n = length(p) n != size(A,1) && error("Must specify as many poles as states") - if opt == :c + if opt === :c n != size(B,1) && error("A and B must have same number of rows") if size(B,2) == 1 acker(A, B, p) From 9bbe79b02804446a68ea3d1df454752d305afed2 Mon Sep 17 00:00:00 2001 From: olof3 Date: Thu, 13 May 2021 22:12:58 +0200 Subject: [PATCH 4/7] Update src/synthesis.jl Co-authored-by: Fredrik Bagge Carlson --- src/synthesis.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/synthesis.jl b/src/synthesis.jl index d77052631..fc24fa22a 100644 --- a/src/synthesis.jl +++ b/src/synthesis.jl @@ -144,7 +144,7 @@ function place(A, B, p, opt=:c) end elseif opt == :o C = B # B is really the "C matrix" - n != size(C,2) && error("A and C must have same number of rows") + n != size(C,2) && error("A and C must have same number of columns") if size(C,1) == 1 acker(A', C', p)' else From 3aab12ba141dbe6091c975117b4577c3bfb91477 Mon Sep 17 00:00:00 2001 From: olof3 Date: Thu, 13 May 2021 22:13:03 +0200 Subject: [PATCH 5/7] Update src/synthesis.jl Co-authored-by: Fredrik Bagge Carlson --- src/synthesis.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/synthesis.jl b/src/synthesis.jl index fc24fa22a..0ac7f7b19 100644 --- a/src/synthesis.jl +++ b/src/synthesis.jl @@ -157,7 +157,7 @@ end function place(sys::StateSpace, p, opt=:c) if opt == :c return place(sys.A, sys.B, p, opt) - elseif opt == :o + elseif opt === :o return place(sys.A, sys.C, p, opt) else error("third argument must be :c or :o") From 257a81b95eeb17a2534f8eb4c0a734cba62967cf Mon Sep 17 00:00:00 2001 From: olof3 Date: Thu, 13 May 2021 22:13:15 +0200 Subject: [PATCH 6/7] Update src/synthesis.jl Co-authored-by: Fredrik Bagge Carlson --- src/synthesis.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/synthesis.jl b/src/synthesis.jl index 0ac7f7b19..96f7ac889 100644 --- a/src/synthesis.jl +++ b/src/synthesis.jl @@ -155,7 +155,7 @@ function place(A, B, p, opt=:c) end end function place(sys::StateSpace, p, opt=:c) - if opt == :c + if opt === :c return place(sys.A, sys.B, p, opt) elseif opt === :o return place(sys.A, sys.C, p, opt) From 2344d420c994028470826d425be2694235d3b2a9 Mon Sep 17 00:00:00 2001 From: olof3 Date: Thu, 13 May 2021 22:13:23 +0200 Subject: [PATCH 7/7] Update src/synthesis.jl Co-authored-by: Fredrik Bagge Carlson --- src/synthesis.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/synthesis.jl b/src/synthesis.jl index 96f7ac889..95d1c99db 100644 --- a/src/synthesis.jl +++ b/src/synthesis.jl @@ -142,7 +142,7 @@ function place(A, B, p, opt=:c) else error("place only implemented for SISO systems") end - elseif opt == :o + elseif opt === :o C = B # B is really the "C matrix" n != size(C,2) && error("A and C must have same number of columns") if size(C,1) == 1