7474
7575Init stochastic model matrices from integrator specifications for state estimation.
7676"""
77- function init_estimstoch (model, i_ym, nint_ym)
77+ function init_estimstoch (model, i_ym, nint_ym; nint_u = 0 )
7878 validate_ym (model, i_ym)
79- nx, ny = model. nx, model. ny
79+ nu, nx, ny = model . nu, model. nx, model. ny
8080 nym, nyu = length (i_ym), ny - length (i_ym)
81- Asm, Csm, nint_ym = init_integrators (i_ym, nint_ym)
82- nxs = size (Asm,1 )
81+ As_u , Cs_u , nint_u = init_integrators (nint_u , nu , " u" )
82+ As_ym, Cs_ym, nint_ym = init_integrators (nint_ym, nym, " ym" )
83+ As_y, _ , Cs_y = stoch_ym2y (model, i_ym, As_ym, [], Cs_ym, [])
84+ nxs_u, nxs_y = size (As_u, 1 ), size (As_y, 1 )
85+ # combines input and output stochastic models:
86+ As = [As_u zeros (nxs_u, nxs_y); zeros (nxs_y, nxs_u) As_y]
87+ Cs_u = [Cs_u zeros (nu, nxs_y)]
88+ Cs_y = [zeros (ny, nxs_u) Cs_y]
89+
90+ # Bs = B*Ks (nx × nxs)
91+ # Cs_u # nu x nxs_u
92+ # B # nx x nu
93+ # K_res = B*Cs_u # (nx × nu) * (nu × nxs_u) = (nx × nxs_u)
94+
95+ nxs = nxs_u + nxs_y
8396 nx̂ = nx + nxs
84- As, _ , Cs = stoch_ym2y (model, i_ym, Asm, [], Csm, [])
85- return nym, nyu, nxs, nx̂, As, Cs, nint_ym
97+ return nym, nyu, nx̂, nxs, As, Cs_u, Cs_y, nint_u, nint_ym
8698end
8799
88100" Validate the specified measured output indices `i_ym`."
@@ -108,74 +120,49 @@ function stoch_ym2y(model::SimModel, i_ym, Asm, Bsm, Csm, Dsm)
108120end
109121
110122@doc raw """
111- init_integrators(i_ym, nint_ym ::Vector{Int}) -> Asm, Csm, nint_ym
123+ init_integrators(nint ::Vector{Int}, nys, varname::String ) -> As, Cs, nint
112124
113- Calc stochastic model matrices from output integrators specifications for state estimation .
125+ Calc state-space matrices `As, Cs` (stochastic part) from integrator specifications `nint` .
114126
115- For closed-loop state estimators. `nint_ym` is a vector providing how many integrator should
116- be added for each measured output `` \m athbf{y^m}``. The argument generates the `Asm` and
117- `Csm` matrices :
127+ This function is used to initialize the stochastic part of the augmented model for the
128+ design of state estimators. The vector `nint` provides how many integrators (in series)
129+ should be incorporated for each stochastic output `` \m athbf{y_s}`` :
118130```math
119131\b egin{aligned}
120- \m athbf{x_s}(k+1) &= \m athbf{A_s^m x_s}(k) + \m athbf{B_s^m e}(k) \\
121- \m athbf{y_s^m }(k) &= \m athbf{C_s^m x_s}(k)
132+ \m athbf{x_s}(k+1) &= \m athbf{A_s x_s}(k) + \m athbf{B_s e}(k) \\
133+ \m athbf{y_s}(k) &= \m athbf{C_s x_s}(k)
122134\e nd{aligned}
123135```
124- where ``\m athbf{e}(k)`` is a conceptual and unknown zero mean white noise.
125- ``\m athbf{B_s^m}`` is not used for closed-loop state estimators thus ignored.
126- """
127- function init_integrators (i_ym, nint_ym)
128- if nint_ym == 0 # alias for no output integrator at all
129- nint_ym = fill (0 , length (i_ym))
130- end
131- nym = length (i_ym);
132- if length (nint_ym) ≠ nym
133- error (" nint_ym size ($(length (nint_ym)) ) ≠ measured output quantity nym ($nym )" )
134- end
135- any (nint_ym .< 0 ) && error (" nint_ym values should be ≥ 0" )
136- nxs = sum (nint_ym)
137- Asm, Csm = zeros (nxs, nxs), zeros (nym, nxs)
138- if nxs ≠ 0 # construct stochastic model state-space matrices (integrators) :
139- i_Asm, i_Csm = 1 , 1
140- for iym = 1 : nym
141- nint = nint_ym[iym]
142- if nint ≠ 0
143- rows_Asm = (i_Asm): (i_Asm + nint - 1 )
144- Asm[rows_Asm, rows_Asm] = Bidiagonal (ones (nint), ones (nint- 1 ), :L )
145- Csm[iym, i_Csm+ nint- 1 ] = 1
146- i_Asm += nint
147- i_Csm += nint
148- end
149- end
150- end
151- return Asm, Csm, nint_ym
152- end
136+ where ``\m athbf{e}(k)`` is an unknown zero mean white noise. The estimations does not use
137+ ``\m athbf{B_s}``, it is thus ignored. Note that this function is called twice :
153138
154- function init_integrators_u (nu, nint_u)
155- if nint_u == 0 # alias for no output integrator at all
156- nint_u = fill (0 , length (nu))
139+ 1. for the unmodeled disturbances at measured outputs ``\m athbf{y^m}``
140+ 2. for the unmodeled disturbances at manipulated inputs ``\m athbf{u}``
141+ """
142+ function init_integrators (nint:: Vector{Int} , nys, varname:: String )
143+ if nint == 0 # alias for no integrator at all
144+ nint = fill (0 , nys)
157145 end
158- # nym = length(i_ym);
159- if length (nint_u) ≠ nu
160- error (" nint_u size ($(length (nint_u)) ) ≠ manipulated input quantity nu ($nu )" )
146+ if length (nint) ≠ nys
147+ error (" nint_$(varname) size ($(length (nint)) ) ≠ n$(varname) ($nys )" )
161148 end
162- any (nint_u .< 0 ) && error (" nint_u values should be ≥ 0" )
163- nxs = sum (nint_u )
164- Asm, Csm = zeros (nxs, nxs), zeros (nym , nxs)
149+ any (nint .< 0 ) && error (" nint_ $(varname) values should be ≥ 0" )
150+ nxs = sum (nint )
151+ As, Cs = zeros (nxs, nxs), zeros (nys , nxs)
165152 if nxs ≠ 0 # construct stochastic model state-space matrices (integrators) :
166- i_Asm, i_Csm = 1 , 1
167- for iym = 1 : nym
168- nint = nint_u[iym ]
169- if nint ≠ 0
170- rows_Asm = (i_Asm ): (i_Asm + nint - 1 )
171- Asm[rows_Asm, rows_Asm ] = Bidiagonal (ones (nint ), ones (nint - 1 ), :L )
172- Csm[iym, i_Csm + nint - 1 ] = 1
173- i_Asm += nint
174- i_Csm += nint
153+ i_As, i_Cs = 1 , 1
154+ for i = 1 : nys
155+ nint_i = nint[i ]
156+ if nint_i ≠ 0
157+ rows_As = (i_As ): (i_As + nint_i - 1 )
158+ As[rows_As, rows_As ] = Bidiagonal (ones (nint_i ), ones (nint_i - 1 ), :L )
159+ Cs[i, i_Cs + nint_i - 1 ] = 1
160+ i_As += nint_i
161+ i_Cs += nint_i
175162 end
176163 end
177164 end
178- return Asm, Csm, nint_u
165+ return As, Cs, nint
179166end
180167
181168@doc raw """
@@ -195,13 +182,13 @@ returns the augmented matrices `Â`, `B̂u`, `Ĉ`, `B̂d` and `D̂d`:
195182```
196183An error is thrown if the augmented model is not observable and `verify_obsv == true`.
197184"""
198- function augment_model (model:: LinModel , As, Cs ; verify_obsv= true )
185+ function augment_model (model:: LinModel , As, Cs_u, Cs_y ; verify_obsv= true )
199186 nu, nx, nd = model. nu, model. nx, model. nd
200187 nxs = size (As, 1 )
201- Â = [model. A zeros (nx,nxs) ; zeros (nxs,nx) As]
202- B̂u = [model. Bu; zeros (nxs,nu)]
203- Ĉ = [model. C Cs ]
204- B̂d = [model. Bd; zeros (nxs,nd)]
188+ Â = [model. A model . Bu * Cs_u ; zeros (nxs,nx) As]
189+ B̂u = [model. Bu; zeros (nxs, nu)]
190+ Ĉ = [model. C Cs_y ]
191+ B̂d = [model. Bd; zeros (nxs, nd)]
205192 D̂d = model. Dd
206193 # observability on Ĉ instead of Ĉm, since it would always return false when nym ≠ ny:
207194 if verify_obsv && ! observability (Â, Ĉ)[:isobservable ]
@@ -269,8 +256,8 @@ function returns the next state of the augmented model, defined as:
269256"""
270257function f̂ (estim:: StateEstimator , x̂, u, d)
271258 # `@views` macro avoid copies with matrix slice operator e.g. [a:b]
272- nx = estim. model. nx
273- @views return [f (estim. model, x̂[ 1 : nx] , u, d); estim. As* x̂[nx + 1 : end ] ]
259+ @views x̂d, x̂s = x̂[ 1 : estim. model. nx], x̂[estim . model . nx + 1 : end ]
260+ return [f (estim. model, x̂d , u + estim . Cs_u * x̂s , d); estim. As* x̂s ]
274261end
275262
276263@doc raw """
@@ -280,8 +267,8 @@ Output function ``\mathbf{ĥ}`` of the augmented model, see [`f̂`](@ref) for d
280267"""
281268function ĥ (estim:: StateEstimator , x̂, d)
282269 # `@views` macro avoid copies with matrix slice operator e.g. [a:b]
283- nx = estim. model. nx
284- @views return h (estim. model, x̂[ 1 : nx] , d) + estim. Cs * x̂[nx + 1 : end ]
270+ @views x̂d, x̂s = x̂[ 1 : estim. model. nx], x̂[estim . model . nx + 1 : end ]
271+ return h (estim. model, x̂d , d) + estim. Cs_y * x̂s
285272end
286273
287274
0 commit comments