I'm trying to execute the following code
p, c = [], []
for z in mes:
print (z)
print (c)
print (p)
p.append(kf.x)
c.append(kf.P)
kf.predict()
kf.update(z) #error on this line
I get the error :
ValueError: Dimension mismatch: array 'cov' is of shape (1, 1), but 'mean' is a vector of length 2.
This is the ouput that shows on the screen
[512 102]
[array([[ 1000., 0., 0., 0.],
[ 0., 1000., 0., 0.],
[ 0., 0., 1000., 0.],
[ 0., 0., 0., 1000.]])]
[array([[ 396.],
[ 187.],
[ 0.],
[ 0.]])]
It works fine if I only take the first element of z
, however, that isn't the behavior I desire.
p, c = [], []
for z in mes:
print (z)
print (c)
print (p)
p.append(kf.x)
c.append(kf.P)
kf.predict()
kf.update(z[0])
Update additional info
This error is coming from multivariate.py
in scipy. I can't seem to be able to change the shape of cov
from (1,1)
. I can change the length of mean
by using z[0]
, however, that isn't desired. I would like to use z
as is. I've also posted the entire code as a gist here. I'm also utilizing the filterpy library for the Kalman filter. There is a live python notebook using this kalman filter, however, it isn't using the z
as in my scenario.
When using the filterpy library you're responsible for setting up the initial state of the Kalman filter yourself, and the dimensions of the various matrices need to be compatible. If you look into the KalmanFilter.update()
method, you can track the computations it does and come up with the following set of constraints on the matrix dimensions:
R.shape == (dim_z, dim_z)
H.shape == (dim_z, dim_x)
P.shape == (dim_x, dim_x)
x.shape == (dim_x, 1...)
z.shape == (dim_z, 1...)
where the 1...
can represent some sequence of dimensions of size 1 which is the same for both. For example, in your case, dim_x == 4
and dim_z == 2
so you could have x.shape == (4, 1)
and z.shape == (2, 1)
, or you could have x.shape == (4,)
and z.shape == (2,)
, but you can't mix and match. (Note that the KalmanFilter.__init__()
documentation appears to give the wrong required dimensions for H
.)
Your code sets the wrong dimensions in two places:
H
to be a 1x4 matrix instead of 2x4 as it should be. (I notice here you've got valid code commented out.)R
to be a scalar value instead of a 2x2 matrix. Arguably the Kalman filter implementation should account for this, but it only does so when you pass R
as a parameter to update()
, not when you set it in advance. (Be careful though: the code will still work if you set R
to be a scalar! It'll do what I believe to be the wrong thing, though: adding 2 to every element of a matrix instead of adding 2 times the identity matrix.)When you pass z
to the update()
method, you're passing a two-element list which gets converted into a 2-element vector, not a 2x1 matrix as it should be to be compatible with x
(which is 4x1). You can fix this by running z = np.array([z]).T
in the body of the loop before calling update()
. But I think there's a better way: leave z
as it is, and just make x
a 4-element vector:
x = np.array([measurements[0][0],measurements[0][1],0.,0.])
I'm not sure if this is meant to work by the author, but it does (at the moment), and it probably should. I think it's sort of silly to require converting each measurement to a 2x1 matrix before passing it in.
KalmanFilter
includes a test_matrix_dimensions()
method which you can use to check for errors in your setup. But I'm sort of ambivalent about it because if you set x
to be a 4-element vector, as I suggested in the last paragraph, it will flag that as incorrect.