@@ -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)
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 (λ))
@@ -259,9 +259,21 @@ 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+ B2 = QRB. Q[:, 1 : m]
268+ T = QRB. P * QRB. R[1 : m, :]'
269+ F = place (A, B2, λ; verbose, init, method)
270+ return pinv (T)' * F
271+ end
272+
262273 S = Matrix{CT}[]
263274 for j = 1 : n
264- qj = qr ((U1' * (A- λ[j]* I))' )
275+ H = (U1' * (A- λ[j]* I))
276+ qj = qr (H' )
265277 # Ŝj = qj.Q[:, 1:n-m] # Needed for method 2
266278 Sj = qj. Q[:, n- m+ 1 : n]
267279 push! (S, Sj)
0 commit comments