1
1
function manifoldupdate! (integ, residualf; maxiters= 100 , ϵ₁= 1e-25 , ϵ₂= 1e-15 )
2
- @unpack x, SolProj = integ. cache
3
- f (m) = residualf (SolProj * m)
4
- return copy! (x, manifoldupdate (x, f; maxiters= maxiters, ϵ₁= ϵ₁, ϵ₂= ϵ₂))
5
- end
2
+ m, C = integ. cache. x
6
3
7
- function manifoldupdate (x, f; maxiters= 100 , ϵ₁= 1e-25 , ϵ₂= 1e-15 )
8
- m, C = x
9
- m_i = copy (m)
4
+ # Create some caches
5
+ @unpack SolProj, tmp, H, x_tmp, x_tmp2 = integ. cache
6
+ z_tmp = residualf (mul! (tmp, SolProj, m))
7
+ result = DiffResults. JacobianResult (z_tmp, tmp)
8
+ d = length (z_tmp)
9
+ H = H[1 : d, :]
10
+ S = SquarerootMatrix (C. squareroot[1 : d, :], C. mat[1 : d, 1 : d])
11
+ m_tmp, C_tmp = x_tmp
10
12
13
+ m_i = copy (m)
11
14
local m_i_new, C_i_new
12
15
for i in 1 : maxiters
13
- z = f (m_i)
14
- J = ForwardDiff. jacobian (f, m_i)
15
- S = X_A_Xt (C, J)
16
+ u_i = mul! (tmp, SolProj, m_i)
17
+
18
+ ForwardDiff. jacobian! (result, residualf, u_i)
19
+ z = DiffResults. value (result)
20
+ J = DiffResults. jacobian (result)
16
21
17
- m_i_new, C_i_new = update (x, Gaussian (z .+ (J * (m - m_i)), S), J)
22
+ mul! (H, J, SolProj)
23
+ X_A_Xt! (S, C, H)
18
24
19
- if norm (m_i_new .- m_i) < ϵ₁ && norm (z) < ϵ₂
25
+ # m_i_new, C_i_new = update(x, Gaussian(z .+ (H * (m - m_i)), S), H)
26
+ # More efficient update with less allocations:
27
+ K = C * (H' / S)
28
+ m_tmp .= m_i .- m
29
+ mul! (z_tmp, H, m_tmp)
30
+ z_tmp .- = z
31
+ mul! (m_tmp, K, z_tmp)
32
+ m_i_new = m_tmp .+ = m
33
+
34
+ if (norm (m_i_new .- m_i) < ϵ₁ && norm (z) < ϵ₂) || (i == maxiters)
35
+ C_i_new = X_A_Xt! (C_tmp, C, (I - K * H))
20
36
break
21
37
end
22
38
m_i = m_i_new
23
39
end
24
- return Gaussian (m_i_new, C_i_new)
40
+
41
+ copy! (integ. cache. x, Gaussian (m_i_new, C_i_new))
42
+
43
+ return nothing
25
44
end
26
45
27
46
"""
@@ -33,6 +52,11 @@ Update the state to satisfy a zero residual function via iterated extended Kalma
33
52
performs an iterated extended Kalman filter update to keep the residual measurement to be
34
53
zero. Additional arguments and keyword arguments for the `DiscreteCallback` can be passed.
35
54
55
+ The residual function should be `residual(u::AbstractVector)::AbstractVector`, that is
56
+ _it should not be in-place_ (whereas DiffEqCallback.jl's `ManifoldProjection`) is.
57
+ If you encounter `SingularException`s, make sure that the residual function is such that
58
+ its Jacobian has full rank.
59
+
36
60
# Additional keyword arguments
37
61
- `maxiters::Int`: Maximum number of IEKF iterations.
38
62
Setting this to 1 results in a single standard EKF update.
0 commit comments