Skip to content

Commit 5caf9d6

Browse files
committed
add direct option to LQGProblem
1 parent abd6f8a commit 5caf9d6

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
2525
[compat]
2626
ChainRulesCore = "1"
2727
ComponentArrays = "0.9, 0.10, 0.11, 0.12, 0.13"
28-
ControlSystemsBase = "1.4.1"
28+
ControlSystemsBase = "1.7"
2929
DescriptorSystems = "1.2"
3030
Distributions = "0.25"
3131
GenericSchur = "0.5.2"

src/lqg.jl

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ function LQGProblem(P::ExtendedStateSpace)
171171
LQGProblem(P, Q1, Q2, R1, R2; SQ, SR)
172172
end
173173

174-
function ControlSystemsBase.kalman(l::LQGProblem)
174+
function ControlSystemsBase.kalman(l::LQGProblem; direct = false)
175175
@unpack A, C2, B1, R1, qR, B2, R2, SR = l
176176
# We do not apply the transformation D21*R2*D21' since when the user has provided an ESS, R2 == D21*D21', and when the user provides covariance matrices, R2 is provided directly.
177-
K = kalman(l.timeevol, A, C2, Hermitian(B1*R1*B1' + qR * B2 * B2'), R2, SR)
177+
K = kalman(l.timeevol, A, C2, Hermitian(B1*R1*B1' + qR * B2 * B2'), R2, SR; direct)
178178
end
179179

180180
function ControlSystemsBase.lqr(l::LQGProblem)
@@ -306,14 +306,27 @@ Note: the transfer function returned is only a representation of the controller
306306
307307
See also [`ff_controller`](@ref) that generates ``C_{ff}``.
308308
"""
309-
function ControlSystemsBase.observer_controller(l::LQGProblem, L::AbstractMatrix = lqr(l), K::AbstractMatrix = kalman(l))
309+
function ControlSystemsBase.observer_controller(l::LQGProblem, L::AbstractMatrix = lqr(l), K::Union{AbstractMatrix, Nothing} = nothing; direct = false)
310310
A,B,C,D = ssdata(system_mapping(l, identity))
311-
Ac = A - B*L - K*C + K*D*L # 8.26b
312-
Bc = K
313-
Cc = L
314-
Dc = 0
315-
iszero(l.D11) || error("Nonzero D11 not supported")
316-
iszero(l.D22) || error("Nonzero D22 not supported. The _transformP2Pbar is not used for LQG, but perhaps shpuld be?")
311+
if K === nothing
312+
K = kalman(l; direct)
313+
end
314+
if direct && isdiscrete(sys)
315+
iszero(D) || throw(ArgumentError("D must be zero when using direct formulation of `observer_controller`"))
316+
IKC = (I - K*C)
317+
ABL = (A - B*L)
318+
Ac = IKC*ABL
319+
Bc = IKC*ABL*K
320+
Cc = L
321+
Dc = L*K
322+
else
323+
Ac = A - B*L - K*C + K*D*L # 8.26b
324+
Bc = K
325+
Cc = L
326+
Dc = 0
327+
iszero(l.D11) || error("Nonzero D11 not supported")
328+
iszero(l.D22) || error("Nonzero D22 not supported. The _transformP2Pbar is not used for LQG, but perhaps shpuld be?")
329+
end
317330
# do we need some way to specify which non-controllable inputs are measurable? No, because they will automatically appear in the measured outputs :)
318331
ss(Ac, Bc, Cc, Dc, l.timeevol)
319332
end

0 commit comments

Comments
 (0)