-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
EKF_func.R
113 lines (100 loc) · 3.36 KB
/
EKF_func.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
extendedkalmanf = function(y, A, B, Q, C, R, mu0, Sigma0, alpha) {
library(numDeriv)
dy = nrow(y)
T = ncol(y)
dx = length(mu0)
I = diag(dx)
## p = PREDICTOR / f = KALMAN FILTER / s = SMOOTHED KALMAN FILTER##
##INITIALISE##
mu.p = matrix(0, nrow = dx, ncol = T)
Sigma.p = array(0, c(dx, dx, T))
ci.p = matrix(0, nrow = 2, ncol = T)
mu.f = matrix(0, nrow = dx, ncol = T)
Sigma.f = array(0, c(dx, dx, T))
ci.f = matrix(0, nrow = 2, ncol = T)
mu.s = matrix(0, nrow = dx, ncol = T)
Sigma.s = array(0, c(dx, dx, T))
ci.s = matrix(0, nrow = 2, ncol = T)
##TIME 1##
#PREDICTION#
dA = grad(A, mu0)
mu.p[, 1] = dA %*% mu0
Sigma.p[,, 1] = dA %*% Sigma0 %*% t(dA) + B %*% Q %*% t(B)
#UPDATE#
dC = grad(C, mu.p[, 1])
nu = y[, 1] - dC %*% mu.p[, 1]
S = dC %*% Sigma.p[,, 1] + R
K = Sigma.p[,, 1] %*% t(dC) %*% solve(S)
mu.f[, 1] = mu.p[, 1] + K %*% nu
Sigma.f[,, 1] = (I - K %*% dC) %*% Sigma.p[,, 1]
##RECURSION TIME 2:T##
for (t in (2:T)) {
#PREDICTION#
dA = grad(A, mu.f[, t - 1])
mu.p[, t] = dA %*% mu.f[, t - 1]
Sigma.p[,, t] = dA %*% Sigma.f[,, t - 1] %*% t(dA) + B %*% Q %*% t(B)
#UPDATE#
dC = grad(C, mu.p[, t])
nu = y[, t] - dC %*% mu.p[, t]
S = dC %*% Sigma.p[,, t] + R
K = Sigma.p[,, t] %*% t(dC) %*% solve(S)
mu.f[, t] = mu.p[, t] + K %*% nu
Sigma.f[,, t] = (I - K %*% dC) %*% Sigma.p[,, t]
}
##SMOOTHING/BACKWARD RECURSION##
mu.s[, T] = mu.f[, T]
Sigma.s[,, T] = Sigma.f[,, T]
for (t in (T - 1):1) {
dA = grad(A, mu.s[, t + 1])
J = Sigma.f[,, t] %*% t(dA) %*% solve(Sigma.p[,, t + 1])
mu.s[, t] = mu.f[, t] + J %*% (mu.s[, t + 1] - mu.p[, t + 1])
Sigma.s[,, t] = Sigma.f[,, t] + J %*% (Sigma.s[,, t + 1] - Sigma.p[,, t + 1]) %*% t(J)
}
##CREDIBLE INTERVAL##
#UPPER = 1/LOWER = 2#
for (t in (1:T)) {
ci.p[1, t] = qnorm(alpha / 2, mean = mu.p[, t], sd = Sigma.p[1, 1, t])
ci.p[2, t] = qnorm(1 - alpha / 2, mean = mu.p[, t], sd = Sigma.p[1, 1, t])
ci.f[1, t] = qnorm(alpha / 2, mean = mu.f[, t], sd = Sigma.f[1, 1, t])
ci.f[2, t] = qnorm(1 - alpha / 2, mean = mu.f[, t], sd = Sigma.f[1, 1, t])
ci.s[1, t] = qnorm(alpha / 2, mean = mu.s[, t], sd = Sigma.s[1, 1, t])
ci.s[2, t] = qnorm(1 - alpha / 2, mean = mu.s[, t], sd = Sigma.s[1, 1, t])
}
##PLOT##
png(filename = "ekalmanfilter.png", width = 768, height = 1280)
par(mfrow = c(3, 1))
#p#
matplot((1:T),
t(rbind(mu.p, ci.p, y)),
type = "l",
col = c(1, 2, 2, 3),
lty = c(1, 2, 2, 3),
main = "Predictor",
xlab = "Time",
ylab = "mu.p",
cex = 8
)
#f#
matplot((1:T),
t(rbind(mu.f, ci.f, y)),
type = "l",
col = c(1, 2, 2, 3),
lty = c(1, 2, 2, 3),
main = "Kalman Filter",
xlab = "Time",
ylab = "mu.f",
cex = 8
)
#s#
matplot((1:T),
t(rbind(mu.s, ci.s, y)),
type = "l",
col = c(1, 2, 2, 3),
lty = c(1, 2, 2, 3),
main = "Smoothed Kalman Filter",
xlab = "Time",
ylab = "mu.s",
cex = 8
)
dev.off()
}