State formation
In SLAM, the device's pose (position and orientation) x, and the positions (but not orientation) of various landmarks (loosely defined as things that can be identified from camera images) mi--both in the world frame are captured as the state vector πtrue = [xtrue; mtrue1; ...; mtrueN], or more compactly πtrue = [xtrue; mtrue]. Since I don't know where the device or the landmarks are initially my initial state estimate is π[0] = [0; 0]. Most text will annotate this vector with a hat (^) for the estimate, but again due to the Formatting constraint in the Blogger editor, I will just omit the hat, and instead denote the (unknowable) as true, as I've done above.Ignoring for now the management of the landmark associations (they are sometimes unobservable as the device moves around the world frame), it is clear that the initial covariance matrix πΊmm[0] = diag(∞, ..., ∞) because at the outset I know nothing about the landmark positions--except the landmark positions are independent of each other, and the device position, for that matter. So πΊππ[0] = diag(0, 0, 0, ∞, ..., ∞). Note that this initialization of the device pose covariance (setting to 0) is different than what may be found in other Kalman filter textbooks (which uses ∞) because of the different initialization method in the book (coming up shortly below). In linear (the original) Kalman filter formulation, the state evolution and observable generation are linear stochastic processes, but in EKF, they are Gaussian nonlinear processes (that can nevertheless be linearized):
where r ~ π(0, R[k]) and qk[k] ~ π(0, Qk[k]). The subscripts k in the measurement model is necessary in SLAM because landmarks come and go at every time step: to me, it means "pertaining to all observations at time step k".
Kalman Filter Extended Kalman Filter Process (state change) model πtrue = A πtrue + B u + r πtrue = g(πtrue, u) + r Measurement model zk[k]= H πtrue + qk[k] zk[k]= hk(πtrue) + qk[k]
The zero initial value of the states pretty much assure that the prediction of the state for the next time step is still zero--unless the system is such that zero is not an equilibrium, or if there is an external input AKA control input. In this example of a planar robot movement using odometer model, there is apparently a non-zero initial external input (the odometry data):
u[0] = [rot1; trans; rot2] = [0.1007 0.1001 0.0002]T.
Prediction step
When first studying Kalman filter, I was confused whether to perform prediction right after outputting the control command, or at the beginning of the next step, right before processing the fresh measurement. Because of my background in real-time control, I perform the non-time-critical tasks such as prediction after outputting the control command (i.e. minimize time delay between sensor measurement available and when the control command is output). But in this case, the external input is not the control command but rather another sensor reading (odometry reading), which is only available at the next time step. That is why the "prediction" step uses the a-posteriori estimate from the last time step x+[k-1] = [x+[k-1]; y+[[k-1]; π+[k-1] ], which in this example:π-[k] = g(u[k]; π+[k-1])For additional clarity, I adopted the "-" and "+" superscripts for the a-priori and a-posteriori estimates.
Even though g(u[k]; π+[k-1]) can be a BHF (big hairy function) in general, stationarity assumption for the landmarks (m[k] = m[k-1]) in SLAM simplifies the state update to only the device pose update:
π-[k] = π+[k-1] + [trans * cos(π+[k-1] + rot1) ; trans * sin(π+[k-1] + rot1) ; rot1 + rot2]
Observation prediction: has to wait till landmark observation in SLAM
We will see shortly the a-posterior update (correction) driven by the sensor measurement (observation). The prediction of the observation h(π[k]) is only necessary at that time, but in the spirit of calculating everything possible outside the time critical path from sensor measurement being available to outputting control command, I want to pre-calculate h(π[k]) now--except that in SLAM, I don't know a-priori which landmarks I will observe, so I have to wait till discovering all observations for the time step.
Covariance prediction
To update the covariance, I need the Jacobian matrix G-[k]:G-[k] = ∂π[k] / ∂π[k-1] @ π-[k] = ∂g(u[k]; π[k-1]) / ∂π[k-1] @ π-[k]Note that the partial derivative is derived from the prediction (i.e. without the new sensor input), AT π[k-1]--the last optimal state estimate. Once again, the landmark stationarity and independence assumption allows simplification:
G-[k] = diag(G-x[k], I2N); where G-x[k] = ∂x[k] / ∂x[k-1] @ x-[k]
In the prediction equation above, only π affects change of x, so that only the dx/dπ and dy/dπ need to be considered for the Jacobian calculation:
In SLAM, the huge covariance prediction calculation above in the first term above can be broken up into 3 isolated portions (the off-diagonal terms are transpose of each other) for simplicity.
This formulation better shows the correlation between the device pose and individual landmark, and the inter-landmark correlation; it might be a better suited to the when landmarks rapidly come in and out of view, but might be an overkill for the simple case of fixed and unchanging landmarks.dx/dπ = -trans * sin(π + rot1); dy/dπ = trans * cos(π + rot1)
G-x[k] = I3 + trans * [ -sin(π-[k] + rot1) ; cos(π-[k] + rot1) ; 0]I think it is helpful to remember separation of the device pose and the landmark positions manifest in the covariance matrix structure as well:
πΊππ = [πΊxx πΊxm ; πΊTxm πΊmm], since πΊmx = πΊTxm.Covariance prediction step involves this huge matrix (dimension (3+2N)2 in this example):
πΊ-ππ[k] = G-[k] πΊ+ππ[k-1] G-T[k] + R[k]In R[k] = diag(R-x[k], 0), R-x characterizes the random noise in the device pose (imagine the device being knocked around by an accident), evaluated at π-[k]. I have not seen a noise covariance modeled with such fidelity as to be sensitive to the current state estimate, but wanted clarity for now. Note that unless the physical process has no noise (i.e. R[k] is 0: impossible!), the state uncertainly always grows during the prediction step, as you can see in the following plot of the robot location estimate overlaid against the known landmarks.
Red: prior device pose estimate and uncertainly (a-posteriori estimate from previous time step) Magenta: predicted device pose and uncertainty, which is larger than the red ellipse |
In fact, the independence of the landmarks allows even more factoring of G-[k] πΊ-ππ[k-1] G-T[k]:
G-[k] πΊ+ππ[k-1] G-T[k] = G-x[k] πΊ+xx[k-1] G-T[k] , G-x[k] πΊ+xm[k-1] (G-x[k] πΊ+xm[k-1])T , πΊ+mm[k-1]]
G-x[k] πΊ+xx[k-1] G-T[k] , G-x[k] πΊ+x1[k-1] , ... , G-x[k] πΊ+xN[k-1] (G-x[k] πΊ+x1[k-1])T , πΊ+11[k-1] , ... , πΊ+1N[k-1] ... , ... , ... , ... (G-x[k] πΊ+xN[k-1])T , πΊ+N1[k-1] , ... , πΊ+NN[k-1]
Correction step
In this example problem, the range and bearing of a subset of the known landmarks are observed at each time step. Assuming that the association problem (which landmark is this for?) is solved somehow, we can calculate the difference between the measured observation and the predicted observation, which is called innovation. If a given landmark was previously observed, its estimated position is already in π-[k]. But a newly discovered landmark i's state m-i[k] is initialized with yet another function:m-i[k] = initial(π-[k], zi[k])There doesn't seem to be a lot of discussion on this initialization function, but if we can initialize, then we can use the completed π-[k] to calculate the predicted observation hp(πtrue) and the measurement Jacobian Hp[k], which is the gradient of the observables z[k] WRT πtrue:
Hp[k] = ∂hp(π[k]) / ∂π[k] @ π-[k]Just like the process Jacobian, there are many ways to estimate the measurement Jacobian (analytical, numerical, and their respective children), but I've only used analytical models so far.
State correction
Kp[k] is the optimal gain under the zero-mean Gaussian noise hypothesis--called Kalman gain.Kp[k] = πΊ-ππ[k] HpT[k] / (Hp[k] πΊ-ππ[k] HpT[k] + Qp[k])
Note that the "/" operator is in fact matrix inversion. I find Kalman "weight" to be a better reminder of its true nature, because that is how much weight is given to the innovation z[k] - hp(π-[k]) to update the state estimate:
Note that the unobserved landmarks do not contribute to correcting the state estimate.π+[k] = π-[k] + Kp[k] ( z[k] - hp(π-[k]) )
Covariance correction
The Kalman weight also contributes to the state covariance correction:πΊ+pp[k] = (Ipp - Kp[k] Hp[k]) πΊ-pp[k] = πΊ-pp[k] - Kp[k] Hp[k] πΊ-pp[k]where πΊpp = [πΊxx πΊxp ; πΊTxp πΊpp] is the combination of the device pose to device pose covariance, device pose to observed (at k) landmark positions, and the landmark position to landmark position covariance. Note that the covariance decreases commensurate to the Kalman weight, in reverse of the always increasing covariance during the prediction step earlier.
If I reduced the sensor covariance too much, the final landmark (at 9,2) doesn't even fall within the 2π ellipse. The drift might be due to the sensor bias, and probably uncorrectable without another sensor or a loop closure (coming later in the course).