Skip to content

Commit d7e7d3a

Browse files
committed
handle B matrix with non-full column rank in place
1 parent 7c91ecc commit d7e7d3a

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

lib/ControlSystemsBase/src/synthesis.jl

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ 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)
245+
QRB = qr(B, ColumnNorm())
246246
U0, U1 = QRB.Q[:, 1:m], QRB.Q[:, m+1:end] # TODO: check dimension
247247
Z = QRB.R
248248
R = svdvals(B)
@@ -259,9 +259,23 @@ function place_knvd(A::AbstractMatrix, B, λ; verbose=false, init=:s, method = 0
259259
return B\(A - ABF) # Solve for F in (A - BF) = Λ
260260
end
261261

262+
mB = size(B, 2)
263+
if mB > m
264+
# several inputs but not full column rank, this case must be handled separately
265+
# 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())
266+
verbose && @info "Projecting down to rank of B"
267+
# T = ones(mB)
268+
# B2 = B*T
269+
B2 = QRB.Q[:, 1:m]
270+
T = Z[1:m, :]'
271+
F = place(A, B2, λ; verbose, init, method)
272+
return pinv(T)'*F
273+
end
274+
262275
S = Matrix{CT}[]
263276
for j = 1:n
264-
qj = qr((U1'*(A- λ[j]*I))')
277+
H = (U1'*(A- λ[j]*I))
278+
qj = qr(H')
265279
# Ŝj = qj.Q[:, 1:n-m] # Needed for method 2
266280
Sj = qj.Q[:, n-m+1:n]
267281
push!(S, Sj)

0 commit comments

Comments
 (0)