numpy 慢卡尔曼滤波器-如何加速计算2x2矩阵的逆矩阵(np.linalg.inv())?

e37o9pze  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(117)

我目前正在做一个图像处理项目,我正在使用卡尔曼滤波器的算法,除其他外。然而,卡尔曼滤波器的计算时间是非常慢的相比,其他软件组件,尽管使用numpy。
预测函数非常快。然而更新函数却不是。我认为原因可能是计算2 × 2矩阵np.linalg.inv()的逆矩阵。
有没有人有更快计算的想法?可能是硬编码的或者如何重新排列方程以避免逆计算?
我也很感激其他关于如何更快地获得代码的评论。我可能也忽略了一些东西。
非常感谢你提前!

卡尔曼滤波器.py:

class KalmanFilter(object):
    def __init__(self, dt, u_x,u_y, std_acc, x_std_meas, y_std_meas):
        """
        :param dt: sampling time (time for 1 cycle)
        :param u_x: acceleration in x-direction
        :param u_y: acceleration in y-direction
        :param std_acc: process noise magnitude
        :param x_std_meas: standard deviation of the measurement in x-direction
        :param y_std_meas: standard deviation of the measurement in y-direction
        """

        # Define sampling time
        self.dt = dt

        # Define the  control input variables
        self.u = np.array([u_x,u_y])

        # Intial State
        self.x = np.array([0.,0.,0.,0.,0.,0.])   # x, x', x'', y, y', y''

        # Define the State Transition Matrix A
        self.A = np.array([[1., self.dt, 0.5*self.dt**2., 0., 0., 0.],
                            [0., 1., self.dt, 0., 0., 0.],
                            [0., 0., 1., 0., 0., 0.],
                            [0., 0., 0., 1., self.dt, 0.5*self.dt**2.],
                            [0., 0., 0., 0., 1., self.dt],
                            [0., 0., 0., 0., 0., 1.]])

        # Define the Control Input Matrix B
        self.B = np.array([[(self.dt**2.)/2., 0.],
                            [0.,(self.dt**2.)/2.],
                            [self.dt,0.],
                            [0.,self.dt]])

        # Define Measurement Mapping Matrix
        self.H = np.array([[1., 0., 0., 0., 0., 0.],
                            [0., 0., 0., 1., 0., 0.]])

        # Initial Process Noise Covariance
        self.Q = np.array([[(self.dt**4.)/4., (self.dt**3.)/2., (self.dt**2.)/2., 0., 0., 0.],
                            [(self.dt**3.)/2., self.dt**2., self.dt, 0., 0., 0.],
                            [(self.dt**2.)/2., self.dt, 1., 0., 0., 0.],
                            [0., 0., 0., (self.dt**4.)/4., (self.dt**3.)/2., (self.dt**2.)/2.],
                            [0., 0., 0., (self.dt**3.)/2., self.dt**2., self.dt],
                            [0., 0., 0., (self.dt**2.)/2., self.dt, 1.]]) * std_acc**2.

        # Initial Measurement Noise Covariance
        self.R = np.array([[x_std_meas**2.,0.],
                           [0., y_std_meas**2.]])

        # Initial Covariance Matrix
        self.P = np.array([[500., 0., 0., 0., 0., 0.],  
                            [0., 500., 0., 0., 0., 0.],
                            [0., 0., 500., 0., 0., 0.],
                            [0., 0., 0., 500., 0., 0.],
                            [0., 0., 0., 0., 500., 0.],
                            [0., 0., 0., 0., 0., 500.]])

        # Initial Kalman Gain                
        self.K = np.zeros((6, 2))

        # Initial System uncertainity
        self.S = np.zeros((2, 2))

    def predict(self):

        # Update time state
        if self.A is not None and self.u[0] is not None:
            self.x = dot(self.A, self.x) + dot(self.B, self.u)
        else:
            self.x = dot(self.A, self.x)

        # Calculate error covariance
        self.P = np.dot(np.dot(self.A, self.P), self.A.T) + self.Q
        return self.x[0], self.x[3]

    def update(self, z):

        self.S = np.dot(self.H, np.dot(self.P, self.H.T)) + self.R

        # Calculate the Kalman Gain
        self.K = np.dot(np.dot(self.P, self.H.T), np.linalg.inv(self.S))

        self.x = self.x + np.dot(self.K, (z - np.dot(self.H, self.x)))

        I = np.eye(self.H.shape[1])

        # Update error covariance matrix
        helper = I - np.dot(self.K, self.H)
        self.P = np.dot(np.dot(helper, self.P), helper.T) + np.dot(self.K, np.dot(self.R, self.K.T))

        return self.x[0], self.x[3]
  • 我用numpy替换了所有现有的函数,但没有太大的变化。
  • 在我之前的网上搜索中,我发现np.linalg.inv()可能是它运行缓慢的原因,但是我找不到一个解决方法来摆脱它。
ee7vknir

ee7vknir1#

您可能会通过以下方式获得一些加速:

def __init__(self, dt, u_x,u_y, std_acc, x_std_meas, y_std_meas):
    
    # your existing code

    self.I = np.eye(self.H.shape[1])

而且,

def update(self, z):
    # you can cut down on 1 dot product if you save P@H.T in an intermediate variable
    P_HT = np.dot(self.P, self.H.T)

    self.S = np.dot(self.H, P_HT) + self.R

    # Calculate the Kalman Gain
    self.K = np.dot(P_HT, np.linalg.inv(self.S))

    self.x = self.x + np.dot(self.K, (z - np.dot(self.H, self.x)))

    # Update error covariance matrix >>> use self.I
    helper = self.I - np.dot(self.K, self.H)
    self.P = np.dot(np.dot(helper, self.P), helper.T) + np.dot(self.K, np.dot(self.R, self.K.T))

    return self.x[0], self.x[3]

相关问题