设计EKF(卡尔曼滤波器)系统用并C++实现

如何设计EKF(卡尔曼滤波器)系统用并C++实现

算法模型

飞机模型如下:
x k = [ x y x ˙ y ˙ x ¨ y ¨ ] x_{k}=\left[\begin{array}{c}x \\ y \\ \dot{x} \\ \dot{y} \\ \ddot{x} \\ \ddot{y}\end{array}\right] xk=xyx˙y˙x¨y¨
运动方程为:
x k + 1 = A ⋅ x k + B ⋅ u x_{k+1}=A \cdot x_{k}+B \cdot u xk+1=Axk+Bu
详细方程为:
x k + 1 = x k + x ˙ k ⋅ Δ t + x ¨ k ⋅ 1 2 Δ t 2 y k + 1 = y k + y ˙ k ⋅ Δ t + y ¨ k ⋅ 1 2 Δ t 2 x ˙ k + 1 = x ˙ k + x ¨ ⋅ Δ t y ˙ k + 1 = y ˙ k + y ¨ ⋅ Δ t x ¨ k + 1 = x ¨ k y ¨ k + 1 = y ¨ k \begin{aligned} x_{k+1}=& x_{k}+\dot{x}_{k} \cdot \Delta t+\ddot{x}_{k} \cdot \frac{1}{2} \Delta t^{2} \\ y_{k+1}=& y_{k}+\dot{y}_{k} \cdot \Delta t+\ddot{y}_{k} \cdot \frac{1}{2} \Delta t^{2} \\ \dot{x}_{k+1}=& \dot{x}_{k}+\ddot{x} \cdot \Delta t \\ \dot{y}_{k+1}=& \dot{y}_{k}+\ddot{y} \cdot \Delta t \\ \ddot{x}_{k+1}=& \ddot{x}_{k} \\ \ddot{y}_{k+1}=& \ddot{y}_{k} \end{aligned} xk+1=yk+1=x˙k+1=y˙k+1=x¨k+1=y¨k+1=xk+x˙kΔt+x¨k21Δt2yk+y˙kΔt+y¨k21Δt2x˙k+x¨Δty˙k+y¨Δtx¨ky¨k
这里是没有输入量u:
x k + 1 = [ 1 0 Δ t 0 1 2 Δ t 2 0 0 1 0 Δ t 0 1 2 Δ t 2 0 0 1 0 Δ t 0 0 0 0 1 0 Δ t 0 0 0 0 1 0 0 0 0 0 0 1 ] [ x y x ˙ y ˙ x ¨ y ¨ ] x_{k+1}=\left[\begin{array}{cccccc}1 & 0 & \Delta t & 0 & \frac{1}{2} \Delta t^{2} & 0 \\ 0 & 1 & 0 & \Delta t & 0 & \frac{1}{2} \Delta t^{2} \\ 0 & 0 & 1 & 0 & \Delta t & 0 \\ 0 & 0 & 0 & 1 & 0 & \Delta t \\ 0 & 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1\end{array}\right]\left[\begin{array}{c}x \\ y \\ \dot{x} \\ \dot{y} \\ \ddot{x} \\ \ddot{y}\end{array}\right] xk+1=100000010000Δt010000Δt010021Δt20Δt010021Δt20Δt01xyx˙y˙x¨y¨
测量方程:
y = [ 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 ] ⋅ x y=\left[\begin{array}{cccccc}1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1\end{array}\right] \cdot x y=100001000000000000100001x
确认过程噪声Q矩阵:
Q = G ⋅ G T ⋅ σ a 2 Q=G \cdot G^{T} \cdot \sigma_{a}^{2} Q=GGTσa2
DraggedImage.png
确认测量噪声R矩阵:

ra = 10.0**2   # Noise of Acceleration Measurement
rp = 100.0**2  # Noise of Position Measurement
R = np.matrix([[rp, 0.0, 0.0, 0.0],
               [0.0, rp, 0.0, 0.0],
               [0.0, 0.0, ra, 0.0],
               [0.0, 0.0, 0.0, ra]])
print(R, R.shape)

算法仿真

import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
from scipy.stats import norm
x = np.matrix([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]).T
print(x, x.shape)
n=x.size # States

P = np.diag([100.0, 100.0, 10.0, 10.0, 1.0, 1.0])
dt = 0.1 # Time Step between Filter Steps

A = np.matrix([[1.0, 0.0, dt, 0.0, 1/2.0*dt**2, 0.0],
              [0.0, 1.0, 0.0, dt, 0.0, 1/2.0*dt**2],
              [0.0, 0.0, 1.0, 0.0, dt, 0.0],
              [0.0, 0.0, 0.0, 1.0, 0.0, dt],
              [0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
              [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]])
H = np.matrix([[1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
               [0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
               [0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
              [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]])

ra = 10.0**2   # Noise of Acceleration Measurement
rp = 100.0**2  # Noise of Position Measurement
R = np.matrix([[rp, 0.0, 0.0, 0.0],
               [0.0, rp, 0.0, 0.0],
               [0.0, 0.0, ra, 0.0],
               [0.0, 0.0, 0.0, ra]])
from sympy import Symbol, Matrix
from sympy.interactive import printing
printing.init_printing()
dts = Symbol('\Delta t')
Qs = Matrix([[0.5*dts**2],[0.5*dts**2],[dts],[dts],[1.0],[1.0]])

sa = 0.001
G = np.matrix([[1/2.0*dt**2],
               [1/2.0*dt**2],
               [dt],
               [dt],
               [1.0],
               [1.0]])
Q = G*G.T*sa**2
I = np.eye(n)
m = 500 # Measurements

sp= 1.0 # Sigma for position
px= 0.0 # x Position
py= 0.0 # y Position

# mpx = np.array(px+sp*np.random.randn(m))
# mpy = np.array(py+sp*np.random.randn(m))

# Generate GPS Trigger
GPS=np.ndarray(m,dtype='bool')
GPS[0]=True
# Less new position updates
for i in range(1,m):
    if i%10==0:
        GPS[i]=True
    else:
        GPS[i]=False
        
# Acceleration
sa= 0.1 # Sigma for acceleration
ax= 0.0 # in X
ay= 0.0 # in Y
import numpy as np
data = np.loadtxt("data1.txt")
mpx = data[:,0]
mpy = data[:,1]
mx = data[:,2]
my = data[:,3]
measurements = np.vstack((mpx,mpy,mx,my))
# Preallocation for Plotting
xt = []
yt = []
dxt= []
dyt= []
ddxt=[]
ddyt=[]
Zx = []
Zy = []
Px = []
Py = []
Pdx= []
Pdy= []
Pddx=[]
Pddy=[]
Kx = []
Ky = []
Kdx= []
Kdy= []
Kddx=[]
Kddy=[]


def savestates(x, Z, P, K):
    xt.append(float(x[0]))
    yt.append(float(x[1]))
    dxt.append(float(x[2]))
    dyt.append(float(x[3]))
    ddxt.append(float(x[4]))
    ddyt.append(float(x[5]))
    Zx.append(float(Z[0]))
    Zy.append(float(Z[1]))
    Px.append(float(P[0,0]))
    Py.append(float(P[1,1]))
    Pdx.append(float(P[2,2]))
    Pdy.append(float(P[3,3]))
    Pddx.append(float(P[4,4]))
    Pddy.append(float(P[5,5]))
    Kx.append(float(K[0,0]))
    Ky.append(float(K[1,0]))
    Kdx.append(float(K[2,0]))
    Kdy.append(float(K[3,0]))
    Kddx.append(float(K[4,0]))
    Kddy.append(float(K[5,0]))
for filterstep in range(m):
    
    # Time Update (Prediction)
    # ========================
    # Project the state ahead
    x = A*x
    
    # Project the error covariance ahead
    P = A*P*A.T + Q    
    
    
    # Measurement Update (Correction)
    # ===============================
    # if there is a GPS Measurement
#     就这样简单的处理
    if GPS[filterstep]:
        # Compute the Kalman Gain
        S = H*P*H.T + R
        K = (P*H.T) * np.linalg.pinv(S)
    
        
        # Update the estimate via z
        Z = measurements[:,filterstep].reshape(H.shape[0],1)
        y = Z - (H*x)                            # Innovation or Residual
        x = x + (K*y)
        
        # Update the error covariance
        P = (I - (K*H))*P

   
    
    # Save states for Plotting
    savestates(x, Z, P, K)
def plot_x():
    
    fig = plt.figure(figsize=(16,16))

    plt.subplot(311)
    plt.step(range(len(measurements[0])),ddxt, label='$\ddot x$')
    plt.step(range(len(measurements[0])),ddyt, label='$\ddot y$')

    plt.title('Estimate (Elements from State Vector $x$)')
    plt.legend(loc='best',prop={'size':22})
    plt.ylabel(r'Acceleration $m/s^2$')
    plt.ylim([-.1,.1])

    plt.subplot(312)
    plt.step(range(len(measurements[0])),dxt, label='$\dot x$')
    plt.step(range(len(measurements[0])),dyt, label='$\dot y$')

    plt.ylabel('')
    plt.legend(loc='best',prop={'size':22})
    plt.ylabel(r'Velocity $m/s$')
    plt.ylim([-1,1])

    plt.subplot(313)
    plt.step(range(len(measurements[0])),xt, label='$x$')
    plt.step(range(len(measurements[0])),yt, label='$y$')

    plt.xlabel('Filter Step')
    plt.ylabel('')
    plt.legend(loc='best',prop={'size':22})
    plt.ylabel(r'Position $m$')
    plt.ylim([-1,1])

    plt.savefig('Kalman-Filter-CA-StateEstimated.png', dpi=72, transparent=True, bbox_inches='tight')
plot_x()

最终的结果如下:
DraggedImage-1.png
DraggedImage-2.png

C++实现

提供代码下载:GPS_kalmanFilter_reference.zip链接

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
EKF-SLAM(Extended Kalman Filter SLAM)是一种基于扩展卡尔曼滤波器的SLAM算法,可以实现同时定位和建图。以下是使用C++实现EKF-SLAM的基本步骤: 1. 定义状态向量和观测向量 在EKF-SLAM中,状态向量包括机器人的位姿和地图中的特征点位置。观测向量包括机器人的传感器测量值和地图中已知的特征点位置。 2. 初始化协方差矩阵和状态向量 协方差矩阵表示状态变量不确定性的度量,初始时应设置为较大的值,以便在后续更新过程中逐渐收敛。状态向量的初始值可以从机器人的传感器数据中估计出来。 3. 实现运动模型 运动模型用于估计机器人的位姿随时间的变化。常见的运动模型包括里程计模型和惯性导航模型。 4. 实现观测模型 观测模型用于预测机器人观测到的特征点位置。常见的观测模型包括单个特征点的距离或角度测量值,以及多个特征点的距离或角度测量值。 5. 实现EKF算法 EKF算法用于更新状态向量和协方差矩阵。在每个时间步骤中,先使用运动模型预测下一个状态向量和协方差矩阵,然后使用观测模型将当前状态向量和协方差矩阵更新为最新的估计值。 6. 更新地图 当机器人观测到新的特征点时,应该将这些点添加到地图中。可以使用一些技术来确定新观测到的特征点是否已经在地图中存在,例如最近邻搜索或图像配准。 7. 重复执行步骤3-6,直到SLAM问题收敛。 以上是使用C++实现EKF-SLAM的基本步骤,但实现过程中需要深入了解卡尔曼滤波器理论和SLAM算法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

擦擦擦大侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值