Skip to content

Commit 6e74d65

Browse files
committed
test ESS with named ss
1 parent 47f4e58 commit 6e74d65

File tree

4 files changed

+74
-23
lines changed

4 files changed

+74
-23
lines changed

src/ExtendedStateSpace.jl

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,17 @@ function Base.getproperty(esys::ExtendedStateSpace, s::Symbol)
253253

254254
# Get the underlying system for matrix extraction
255255
sys = getfield(esys, :sys)
256-
w = getfield(esys, :w)
257-
u = getfield(esys, :u)
258-
z = getfield(esys, :z)
259-
y = getfield(esys, :y)
256+
if sys isa NamedStateSpace
257+
w = names2indices(getfield(esys, :w), sys.u)
258+
u = names2indices(getfield(esys, :u), sys.u)
259+
z = names2indices(getfield(esys, :z), sys.y)
260+
y = names2indices(getfield(esys, :y), sys.y)
261+
else
262+
w = getfield(esys, :w)
263+
u = getfield(esys, :u)
264+
z = getfield(esys, :z)
265+
y = getfield(esys, :y)
266+
end
260267

261268
# Extract matrices via indexing
262269
if s === :A
@@ -459,17 +466,7 @@ Base.eltype(::Type{S}) where {S<:ExtendedStateSpace} = S
459466
ControlSystemsBase.numeric_type(sys::ExtendedStateSpace) = eltype(sys.A)
460467

461468
function Base.getindex(sys::ExtendedStateSpace, inds...)
462-
if size(inds, 1) != 2
463-
error("Must specify 2 indices to index statespace model")
464-
end
465-
rows, cols = ControlSystemsBase.index2range(inds...) # FIXME: ControlSystemsBase.index2range(inds...)
466-
return ss(
467-
copy(sys.A),
468-
sys.B[:, cols],
469-
sys.C[rows, :],
470-
sys.D[rows, cols],
471-
sys.timeevol,
472-
)
469+
getindex(sys.sys, inds...)
473470
end
474471

475472
#####################################################################

src/lqg.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,8 @@ Note: the transfer function returned is only a representation of the controller
330330
See also [`ff_controller`](@ref) that generates ``C_{ff}``.
331331
"""
332332
function ControlSystemsBase.observer_controller(l::LQGProblem, L::AbstractMatrix = lqr(l), K::Union{AbstractMatrix, Nothing} = nothing; direct = false)
333-
A,B,C,D = ssdata(system_mapping(l, identity))
333+
sys = system_mapping(l, identity)
334+
A,B,C,D = ssdata(sys)
334335
if K === nothing
335336
K = kalman(l; direct)
336337
end
@@ -351,7 +352,12 @@ function ControlSystemsBase.observer_controller(l::LQGProblem, L::AbstractMatrix
351352
iszero(l.D22) || error("Nonzero D22 not supported. The _transformP2Pbar is not used for LQG, but perhaps shpuld be?")
352353
end
353354
# do we need some way to specify which non-controllable inputs are measurable? No, because they will automatically appear in the measured outputs :)
354-
ss(Ac, Bc, Cc, Dc, l.timeevol)
355+
Gc = ss(Ac, Bc, Cc, Dc, l.timeevol)
356+
if sys isa NamedStateSpace
357+
named_ss(Gc; u=sys.y, y=sys.u)
358+
else
359+
Gc
360+
end
355361
end
356362

357363
function ControlSystemsBase.observer_predictor(l::LQGProblem, K::Union{AbstractMatrix, Nothing} = nothing; direct = false, kwargs...)

src/named_systems2.jl

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -899,12 +899,7 @@ function names2indices(name::Symbol, allnames)
899899
end
900900

901901
function ExtendedStateSpace(P::NamedStateSpace; z=P.y, y=P.y, w=P.u, u=P.u)
902-
zi = names2indices(z, P.y)
903-
yi = names2indices(y, P.y)
904-
wi = names2indices(w, P.u)
905-
ui = names2indices(u, P.u)
906-
ss(P.A, P.B[:, wi], P.B[:, ui], P.C[zi, :], P.C[yi, :],
907-
P.D[zi, wi], P.D[zi, ui], P.D[yi, wi], P.D[yi, ui], P.timeevol)
902+
ExtendedStateSpace(P, w, u, z, y)
908903
end
909904

910905
"""

test/test_lqg.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,3 +535,56 @@ Ce, cl = extended_controller(lqg, z=[1, 2])
535535
Ce, cl = extended_controller(lqg, z=[1])
536536
@test pinv(dcgain(cl)[1,2]) dc_gain_compensation atol=1e-8
537537

538+
## Test LQGProblem with NamedStateSpace inside ExtendedStateSpace
539+
# This tests that the index-based ExtendedStateSpace preserves the type of the internal system
540+
541+
# Aircraft control
542+
543+
A = [-0.292 8.13 -201 9.77 0 -12.5 17.1
544+
-0.152 -2.54 0.561 -0.0004 0 107 7.68
545+
0.0364 -0.0678 -0.481 0.0012 0 4.67 -7.98
546+
0 1 0.0401 0 0 0 0
547+
0 0 1 0 0 0 0
548+
0 0 0 0 0 -20 0
549+
0 0 0 0 0 0 -20
550+
]
551+
552+
B = [
553+
0 -2.15
554+
-31.7 0.0274
555+
0 1.48
556+
0 0
557+
0 0
558+
20 0
559+
0 20
560+
]
561+
# Example 9.1
562+
M = [0 0 0 1 0 0 0
563+
0 0 0 0 1 0 0]
564+
C = M
565+
566+
N = I(7)
567+
nx,ny,nu = size(A,1), size(C, 1), size(B,2)
568+
569+
570+
Q1 = I(ny)
571+
Q2 = I(nu)
572+
R1 = I(nx)
573+
R2 = I(ny)
574+
575+
576+
sys = named_ss(ss(A, [N B], M, 0), x=:x, u=[:w^7; :u^2], y=:y^2)
577+
sys = ExtendedStateSpace(sys, w=:w^7, u=:u^2, z=:y^2, y=:y^2)
578+
G = LQGProblem(sys, Q1, Q2, R1, R2)
579+
@test lqr(G) [-0.0022 0.17 0.12 0.98 0.31 0.76 0.018
580+
-0.0038 0.028 -0.25 0.16 -0.95 0.072 0.10] rtol=0.01
581+
582+
583+
gangoffourplot(G)
584+
585+
@test system_mapping(G).y == :y^2
586+
@test system_mapping(G).u == :u^2
587+
@test performance_mapping(G).u == :w^7
588+
589+
@test observer_controller(G).y == :u^2 # Names of contorller are swapped compared to plant
590+
@test observer_controller(G).u == :y^2

0 commit comments

Comments
 (0)