Skip to content

Commit 8a1b3c3

Browse files
committed
add additional test case
1 parent d7e7d3a commit 8a1b3c3

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

lib/ControlSystemsBase/src/synthesis.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,11 @@ function place_knvd(A::AbstractMatrix, B, λ; verbose=false, init=:s, method = 0
242242
λ = sort(vec(λ), by=LinearAlgebra.eigsortby)
243243
length(λ) == size(A, 1) == n || error("Must specify as many poles as the state dimension")
244244
Λ = diagm(λ)
245-
QRB = qr(B, ColumnNorm())
246-
U0, U1 = QRB.Q[:, 1:m], QRB.Q[:, m+1:end] # TODO: check dimension
247-
Z = QRB.R
248245
R = svdvals(B)
249246
m = count(>(100*eps()*R[1]), R) # Rank of B
247+
QRB = qr(B, ColumnNorm())
248+
U0, U1 = QRB.Q[:, 1:m], QRB.Q[:, m+1:end] # TODO: check dimension
249+
Z = (QRB.R*QRB.P')[:, 1:m]
250250
if m == n # Easy case, B is full rank
251251
r = count(e->imag(e) == 0, λ)
252252
ABF = diagm(real(λ))
@@ -264,10 +264,8 @@ function place_knvd(A::AbstractMatrix, B, λ; verbose=false, init=:s, method = 0
264264
# several inputs but not full column rank, this case must be handled separately
265265
# when B does not have full column rank but that rank is not 1. In that case, find B2 and T from rank-revealing QR (qr(B, ColumnNorm())
266266
verbose && @info "Projecting down to rank of B"
267-
# T = ones(mB)
268-
# B2 = B*T
269267
B2 = QRB.Q[:, 1:m]
270-
T = Z[1:m, :]'
268+
T = QRB.P * QRB.R[1:m, :]'
271269
F = place(A, B2, λ; verbose, init, method)
272270
return pinv(T)'*F
273271
end

lib/ControlSystemsBase/test/test_synthesis.jl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ end
114114
# @show cond(gram(sys, :c))
115115
(; A, B) = sys
116116
p = [-1.0, -2, -3]
117-
L = place(A, B, p)
117+
L = place(A, B, p, verbose=false)
118118
@test eltype(L) <: Real
119119
@test allin(eigvals(A - B*L), p)
120120

@@ -177,6 +177,28 @@ end
177177
@test allin(eigvals(A - B*L), p; tol=0.025) # Tolerance from paper
178178
# norm(L)
179179

180+
## Rank deficient multi-input B
181+
P = let
182+
tempA = [0.0 1.0; -4.0 -1.2]
183+
tempB = [0.0 0.0; 4.0 4.0]
184+
tempC = [1.0 0.0]
185+
tempD = [0.0 0.0]
186+
ss(tempA, tempB, tempC, tempD)
187+
end
188+
F = place(P, [-2, -2], verbose=true)
189+
@test allin(eigvals(P.A - P.B*F), [-2, -2])
190+
191+
192+
P = let
193+
tempA = [0.0 1.0; -4.0 -1.2]
194+
tempB = randn(2, 1) * randn(1, 10) # Rank deficient
195+
tempC = [1.0 0.0]
196+
tempD = zeros(1, 10)
197+
ss(tempA, tempB, tempC, tempD)
198+
end
199+
F = place(P, [-2, -2], verbose=true)
200+
@test allin(eigvals(P.A - P.B*F), [-2, -2])
201+
180202
end
181203

182204
@testset "LQR" begin

0 commit comments

Comments
 (0)