filterpy
filterpy copied to clipboard
Kalman Filter can accept matrices with the wrong shape
I was using KalmanFilter
for something fairly simple, and had an issue where I was assigning the Q
attribute a matrix with the incorrect shape (I believe I supplied a 1x2 whereas I should have supplied a 2x2). Unfortunately there looks to be no handling for this, and so the Kalman Filter continued to produce (wildly incorrect) results without throwing an exception, and finding the root issue proved to be quite difficult (especially for someone new to Kalman filtering like me).
As a result I wrote the below subclass of KalmanFilter
, but I don't currently see any reason not to make this the default behaviour in the main KalmanFilter
class. Thoughts?
class ShapelyKalmanFilter(KalmanFilter):
def assert_shape(self, matrix, shape, name):
assert matrix.shape == shape, f"{name} matrix must have shape {shape}, found shape {matrix.shape}"
def predict(self, u=None, B=None, F=None, Q=None):
if B is None:
B = self.B
if F is None:
F = self.F
if Q is None:
Q = self.Q
if np.isscalar(Q):
Q = np.eye(self.dim_x) * Q
self.assert_shape(Q, (self.dim_x, self.dim_x), "Q")
self.assert_shape(F, (self.dim_x, self.dim_x), "F")
super().predict(u=u, B=B, F=F, Q=Q)
def update(self, z, R=None, H=None):
if R is None:
R = self.R
if np.isscalar(R):
R = np.eye(self.dim_z) * R
if H is None:
H = self.H
self.assert_shape(R, (self.dim_z, self.dim_z), "R")
self.assert_shape(H, (self.dim_z, self.dim_x), "H")
super().update(z=z, R=R, H=H)
This class started out accepting either scalars (for zero order model), 1d arrays, or 2d arrays. In retrospect I'm not so happy with that decision. It made things 'easy', but how hard is it to type np.array([[2]]) instead of 2?
The function test_matrix_dimensions already exists. As you can see it is quite complex, and I am not convinced it covers all cases. In a sense, if the linear algebra 'works' it can be considered a correct formulation. It seemed that no matter how I wrote test_matrix_dimensions I could find a formulation that caused it to report a failure.
There is the possibility perhaps of asserts that the results of computations is correct. For example, is H @ x the same shape as the measurement vector? But again, you can pass in 2 or [2] or [[2]].
It's pretty unlikely that I will work on this further unless someone submits a bug against test_matrix_dimensions(), hence I have labelled it help wanted. Any change would require a very robust set of unit tests for me to consider it.
Possibly related to https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python/issues/366
I am very excited with this package, learning how to use it today. I will make a fix that and I will see if I can tidy this part as well to make easier for landing users :)
@rlabbe
I created a mechanism to validate matrix assignments to instance properties automatically. You can se how it can be used https://github.com/o-alexandre-felipe/filterpy/commit/68882790a23e13a5ca0e89ce24102112ee0b6a3f.
I was able to get the test_kf working in https://github.com/o-alexandre-felipe/filterpy/commit/72699b7704e7c9408948ffd032bb78369d3ff000 however I still have some failures. I am facing some decisions that I don't feel I am the right person to take. For instance, I noticed some problems when making x and z column vectors, these things must be made 1D arrays?
Thank you for this. I'm in the midst of moving, and have essentially no time to devote to this at the moment. Reach out at the end of the month if I haven't gotten to you by then.