@@ -909,10 +909,10 @@ struct ExtendedKalmanFilter{
909
909
F̂ :: Matrix{NT}
910
910
Ĥ :: Matrix{NT}
911
911
Ĥm :: Matrix{NT}
912
- direct:: Bool
913
- corrected:: Vector{Bool}
914
912
jacobian:: JB
915
913
linfunc!:: LF
914
+ direct:: Bool
915
+ corrected:: Vector{Bool}
916
916
buffer:: StateEstimatorBuffer{NT}
917
917
function ExtendedKalmanFilter {NT} (
918
918
model:: SM , i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂; jacobian:: JB , linfunc!:: LF , direct= true
@@ -935,7 +935,7 @@ struct ExtendedKalmanFilter{
935
935
Ĥ, Ĥm = zeros (NT, ny, nx̂), zeros (NT, nym, nx̂)
936
936
corrected = [false ]
937
937
buffer = StateEstimatorBuffer {NT} (nu, nx̂, nym, ny, nd)
938
- return new {NT, SM} (
938
+ return new {NT, SM, JB, LF } (
939
939
model,
940
940
lastu0, x̂op, f̂op, x̂0, P̂,
941
941
i_ym, nx̂, nym, nyu, nxs,
@@ -1005,7 +1005,7 @@ function ExtendedKalmanFilter(
1005
1005
P̂_0 = Hermitian (diagm (NT[σP_0; σPint_u_0; σPint_ym_0]. ^ 2 ), :L )
1006
1006
Q̂ = Hermitian (diagm (NT[σQ; σQint_u; σQint_ym ]. ^ 2 ), :L )
1007
1007
R̂ = Hermitian (diagm (NT[σR;]. ^ 2 ), :L )
1008
- linfunc! = get_ekf_linfunc (model, i_ym, nint_u, nint_ym, jacobian)
1008
+ linfunc! = get_ekf_linfunc (NT, model, i_ym, nint_u, nint_ym, jacobian)
1009
1009
return ExtendedKalmanFilter {NT} (
1010
1010
model, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂; jacobian, linfunc!, direct
1011
1011
)
@@ -1024,48 +1024,52 @@ function ExtendedKalmanFilter(
1024
1024
model:: SM , i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂; jacobian= AutoForwardDiff (), direct= true
1025
1025
) where {NT<: Real , SM<: SimModel{NT} }
1026
1026
P̂_0, Q̂, R̂ = to_mat (P̂_0), to_mat (Q̂), to_mat (R̂)
1027
- linfunc! = get_ekf_linfunc (model, i_ym, nint_u, nint_ym, jacobian)
1027
+ linfunc! = get_ekf_linfunc (NT, model, i_ym, nint_u, nint_ym, jacobian)
1028
1028
return ExtendedKalmanFilter {NT} (
1029
1029
model, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂; jacobian, direct, linfunc!
1030
1030
)
1031
1031
end
1032
1032
1033
- function get_ekf_linfunc (model, i_ym, nint_u, nint_ym, jacobian)
1033
+ """
1034
+ get_ekf_linfunc(NT, model, i_ym, nint_u, nint_ym, jacobian) -> linfunc!
1035
+
1036
+ Return the `linfunc!` function that computes the Jacobians of the augmented model.
1037
+
1038
+ The function has the following signature:
1039
+ ```
1040
+ linfunc!(x̂0next, ŷ0, F̂, Ĥ, backend, x̂0, cst_u0, cst_d0) -> nothing
1041
+ ```
1042
+ #TODO: continue here
1043
+ """
1044
+ function get_ekf_linfunc (NT, model, i_ym, nint_u, nint_ym, jacobian)
1034
1045
As, Cs_u, Cs_y = init_estimstoch (model, i_ym, nint_u, nint_ym)
1035
- function f̂_ekf! (x̂0next, x̂0, model, As, Cs_u, u0, d0, û0)
1036
- return f̂! (x̂next0, û0, model, As, Cs_u, x̂0, u0, d0)
1037
- end
1038
- function ĥ_ekf! (ŷ0, x̂0, model, Cs_y, d0)
1039
- return ĥ! (ŷ0, model, Cs_y, x̂0, d0)
1040
- end
1046
+ f̂_ekf! (x̂0next, x̂0, û0, u0, d0) = f̂! (x̂0next, û0, model, As, Cs_u, x̂0, u0, d0)
1047
+ ĥ_ekf! (ŷ0, x̂0, d0) = ĥ! (ŷ0, model, Cs_y, x̂0, d0)
1041
1048
strict = Val (true )
1042
- # TODO : continue here:
1043
- xnext = zeros (NT, nx)
1044
- y = zeros (NT, ny)
1045
- x = zeros (NT, nx)
1046
- u = zeros (NT, nu)
1047
- d = zeros (NT, nd)
1048
- cst_x = Constant (x)
1049
- cst_u = Constant (u)
1050
- cst_d = Constant (d)
1051
- A_prep = prepare_jacobian (f_x!, xnext, backend, x, cst_u, cst_d; strict)
1052
- Bu_prep = prepare_jacobian (f_u!, xnext, backend, u, cst_x, cst_d; strict)
1053
- Bd_prep = prepare_jacobian (f_d!, xnext, backend, d, cst_x, cst_u; strict)
1054
- C_prep = prepare_jacobian (h_x!, y, backend, x, cst_d ; strict)
1055
- Dd_prep = prepare_jacobian (h_d!, y, backend, d, cst_x ; strict)
1056
- function linfunc! (xnext, y, A, Bu, C, Bd, Dd, backend, x, u, d, cst_x, cst_u, cst_d)
1057
- # all the arguments before `x` are mutated in this function
1058
- jacobian! (f_x!, xnext, A, A_prep, backend, x, cst_u, cst_d)
1059
- jacobian! (f_u!, xnext, Bu, Bu_prep, backend, u, cst_x, cst_d)
1060
- jacobian! (f_d!, xnext, Bd, Bd_prep, backend, d, cst_x, cst_u)
1061
- jacobian! (h_x!, y, C, C_prep, backend, x, cst_d)
1062
- jacobian! (h_d!, y, Dd, Dd_prep, backend, d, cst_x)
1049
+ nu, ny, nd = model. nu, model. ny, model. nd
1050
+ nx̂ = model. nx + size (As, 1 )
1051
+ x̂0next = zeros (NT, nx̂)
1052
+ ŷ0 = zeros (NT, ny)
1053
+ x̂0 = zeros (NT, nx̂)
1054
+ tmp_û0 = Cache (zeros (NT, nu))
1055
+ cst_u0 = Constant (zeros (NT, nu))
1056
+ cst_d0 = Constant (zeros (NT, nd))
1057
+ F̂_prep = prepare_jacobian (f̂_ekf!, x̂0next, jacobian, x̂0, tmp_û0, cst_u0, cst_d0; strict)
1058
+ Ĥ_prep = prepare_jacobian (ĥ_ekf!, ŷ0, jacobian, x̂0, cst_d0; strict)
1059
+ # main method to compute both Jacobians, it mutates all args before `backend`:
1060
+ function linfunc! (x̂0next, ŷ0, F̂, Ĥ, backend, x̂0, cst_u0, cst_d0)
1061
+ jacobian! (f̂_ekf!, x̂0next, F̂, F̂_prep, backend, x̂0, tmp_û0, cst_u0, cst_d0)
1062
+ jacobian! (ĥ_ekf!, ŷ0, Ĥ, Ĥ_prep, backend, x̂0, cst_d0)
1063
1063
return nothing
1064
1064
end
1065
+ # two additional methods to only compute one of the two Jacobians at a time:
1066
+ function linfunc! (x̂0next, ŷ0:: Nothing , F̂, Ĥ:: Nothing , backend, x̂0, cst_u0, cst_d0)
1067
+ return jacobian! (f̂_ekf!, x̂0next, F̂, F̂_prep, backend, x̂0, tmp_û0, cst_u0, cst_d0)
1068
+ end
1069
+ function linfunc! (x̂0next:: Nothing , ŷ0, F̂:: Nothing , Ĥ, backend, x̂0, _ , cst_d0)
1070
+ return jacobian! (ĥ_ekf!, ŷ0, Ĥ, Ĥ_prep, backend, x̂0, cst_d0)
1071
+ end
1065
1072
return linfunc!
1066
-
1067
-
1068
-
1069
1073
end
1070
1074
1071
1075
"""
@@ -1075,15 +1079,10 @@ Do the same but for the [`ExtendedKalmanFilter`](@ref).
1075
1079
"""
1076
1080
function correct_estimate! (estim:: ExtendedKalmanFilter , y0m, d0)
1077
1081
model, x̂0 = estim. model, estim. x̂0
1078
- ŷ0 = estim. buffer. ŷ
1079
-
1080
-
1081
- ĥAD! = (ŷ0, x̂0) -> ĥ! (ŷ0, estim, model, x̂0, d0)
1082
- ForwardDiff. jacobian! (estim. Ĥ, ĥAD!, ŷ0, x̂0)
1083
-
1084
-
1082
+ cst_d0 = Constant (d0)
1083
+ ŷ0, Ĥ = estim. buffer. ŷ, estim. Ĥ
1084
+ estim. linfunc! (nothing , ŷ0, nothing , Ĥ, estim. jacobian, x̂0, nothing , cst_d0)
1085
1085
estim. Ĥm .= @views estim. Ĥ[estim. i_ym, :]
1086
-
1087
1086
return correct_estimate_kf! (estim, y0m, d0, estim. Ĥm)
1088
1087
end
1089
1088
@@ -1129,22 +1128,16 @@ prediction step equations are provided below. The correction step is skipped if
1129
1128
function update_estimate! (estim:: ExtendedKalmanFilter{NT} , y0m, d0, u0) where NT<: Real
1130
1129
model, x̂0 = estim. model, estim. x̂0
1131
1130
nx̂, nu = estim. nx̂, model. nu
1131
+ cst_u0, cst_d0 = Constant (u0), Constant (d0)
1132
1132
if ! estim. direct
1133
- ŷ0 = estim. buffer. ŷ
1134
- ĥAD! = (ŷ0, x̂0) -> ĥ! (ŷ0, estim, model, x̂0, d0)
1135
- ForwardDiff. jacobian! (estim. Ĥ, ĥAD!, ŷ0, x̂0)
1133
+ ŷ0, Ĥ = estim. buffer. ŷ, estim. Ĥ
1134
+ estim. linfunc! (nothing , ŷ0, nothing , Ĥ, estim. jacobian, x̂0, nothing , cst_d0)
1136
1135
estim. Ĥm .= @views estim. Ĥ[estim. i_ym, :]
1137
1136
correct_estimate_kf! (estim, y0m, d0, estim. Ĥm)
1138
1137
end
1139
1138
x̂0corr = estim. x̂0
1140
- # concatenate x̂0next and û0 vectors to allows û0 vector with dual numbers for AD:
1141
- # TODO : remove this allocation using estim.buffer
1142
- x̂0nextû = Vector {NT} (undef, nx̂ + nu)
1143
- f̂AD! = (x̂0nextû, x̂0corr) -> @views f̂! (
1144
- x̂0nextû[1 : nx̂], x̂0nextû[nx̂+ 1 : end ], estim, model, x̂0corr, u0, d0
1145
- )
1146
- ForwardDiff. jacobian! (estim. F̂_û, f̂AD!, x̂0nextû, x̂0corr)
1147
- estim. F̂ .= @views estim. F̂_û[1 : estim. nx̂, :]
1139
+ x̂0next, F̂ = estim. buffer. x̂, estim. F̂
1140
+ estim. linfunc! (x̂0next, nothing , F̂, nothing , estim. jacobian, x̂0corr, cst_u0, cst_d0)
1148
1141
return predict_estimate_kf! (estim, u0, d0, estim. F̂)
1149
1142
end
1150
1143
0 commit comments