Skip to content

Commit 9dc532b

Browse files
committed
Kalaman filter script including plot code (not in book)
1 parent 07b0b67 commit 9dc532b

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

Ch07/kalman_filter.r

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
## rocket will take 100 time steps
2+
ts.length <- 100
3+
4+
## the acceleration will drive the motion
5+
a <- rep(0.5, ts.length)
6+
7+
## position and velocity start at 0
8+
x <- rep(0, ts.length)
9+
v <- rep(0, ts.length)
10+
for (ts in 2:ts.length) {
11+
x[ts] <- v[ts - 1] * 2 + x[ts - 1] + 1/2 * a[ts - 1] ^ 2
12+
x[ts] <- x[ts] + rnorm(1, sd = 20) ## stochastic component
13+
v[ts] <- v[ts - 1] + 2 * a[ts - 1]
14+
}
15+
16+
par(mfrow = c(3, 1))
17+
plot(x, main = "Position", type = 'l')
18+
plot(v, main = "Velocity", type = 'l')
19+
plot(a, main = "Acceleration", type = 'l')
20+
21+
## simulate noisy sensor measurement
22+
z <- x + rnorm(ts.length, sd = 300)
23+
par(mfrow = c(1, 1))
24+
plot(x, ylim = range(c(x, z)))
25+
lines(z)
26+
27+
## apply a Kalman filter
28+
kalman.motion <- function(z, Q, R, A, H) {
29+
dimState = dim(Q)[1]
30+
31+
xhatminus <- array(rep(0, ts.length * dimState),
32+
c(ts.length, dimState))
33+
xhat <- array(rep(0, ts.length * dimState),
34+
c(ts.length, dimState))
35+
36+
Pminus <- array(rep(0, ts.length * dimState * dimState),
37+
c(ts.length, dimState, dimState))
38+
P <- array(rep(0, ts.length * dimState * dimState),
39+
c(ts.length, dimState, dimState))
40+
41+
K <- array(rep(0, ts.length * dimState),
42+
c(ts.length, dimState)) # Kalman gain
43+
44+
# initial guesses = starting at 0 for all metrics
45+
xhat[1, ] <- rep(0, dimState)
46+
P[1, , ] <- diag(dimState)
47+
48+
for (k in 2:ts.length) {
49+
# time update
50+
xhatminus[k, ] <- A %*% matrix(xhat[k-1, ])
51+
Pminus[k, , ] <- A %*% P[k-1, , ] %*% t(A) + Q
52+
53+
K[k, ] <- Pminus[k, , ] %*% H %*%
54+
solve( t(H) %*% Pminus[k, , ] %*% H + R )
55+
xhat[k, ] <- xhatminus[k, ] + K[k, ] %*%
56+
(z[k] - t(H) %*% xhatminus[k, ])
57+
P[k, , ] <- (diag(dimState) - K[k, ] %*% t(H)) %*% Pminus[k, , ]
58+
}
59+
60+
## we return both the forecast and the smoothed value
61+
return(list(xhat = xhat, xhatminus = xhatminus))
62+
}
63+
64+
## noise parameters
65+
R <- 10^2 ## measurement variance - this value should be set
66+
## according to known physical limits of measuring tool
67+
## we set it consistent with the noise we added to x
68+
## to produce x in the data generation above
69+
Q <- 10 ## process variance - usually regarded as hyperparameter
70+
## to be used to maximize performance
71+
72+
## dynamical parameters
73+
A <- matrix(1) ## x_t = A * x_t - 1 (how prior x affects later x)
74+
H <- matrix(1) ## y_t = H * x_t (translating state to measurement)
75+
76+
## run the data through the Kalman filtering method
77+
xhat <- kalman.motion(z, diag(1) * Q, R, A, H)[[1]]
78+
xhatminus <- kalman.motion(z, diag(1) * Q, R, A, H)[[2]]
79+
80+
## visualization
81+
plot(z, ylim = range(c(x, z)), type = 'l',
82+
col = "black", lwd = 2)
83+
lines(x, col = "red", lwd = 2, lty = 2)
84+
lines(xhat, col = "orange", lwd = 1, lty = 3)
85+
lines(xhatminus, col = "blue", lwd = 1, lty = 4)
86+
legend("topleft",
87+
legend = c("Measured", "Actual", "Filtered", "Forecast"),
88+
col = c("black", "red", "orange", "blue"),
89+
lty = 1:4)

Ch07/kalman_filter_plot.png

49.8 KB
Loading

0 commit comments

Comments
 (0)