UKF随笔与Python实现(无运动模型)

UKF介绍

预测

  1. 首先得到初始sigma点,并计算权重w:
    χ = sigma-function ( x , P ) W m , W c = weight-function ( n , p a r a m e t e r s ) \begin{aligned}\boldsymbol\chi &= \text{sigma-function}(\mathbf x, \mathbf P) \\ W^m, W^c &= \text{weight-function}(\mathtt{n, parameters})\end{aligned} χWm,Wc=sigma-function(x,P)=weight-function(n,parameters)
    λ = α 2 ( n + κ ) − n W 0 m = λ n + λ W 0 c = λ n + λ + 1 − α 2 + β W i m = W i c = 1 2 ( n + λ )        i = 1..2 n \begin{aligned} \lambda&=\alpha^2(n+\kappa)-n \\ W^m_0 &= \frac{\lambda}{n+\lambda} \\ W^c_0 &= \frac{\lambda}{n+\lambda} + 1 -\alpha^2 + \beta \\ W^m_i = W^c_i &= \frac{1}{2(n+\lambda)}\;\;\;i=1..2n \end{aligned} λW0mW0cWim=Wic=α2(n+κ)n=n+λλ=n+λλ+1α2+β=2(n+λ)1i=1..2n
    { X 0 = μ X i = μ + [ ( n + λ ) Σ ] i , i = 1... n X i = μ − [ ( n + λ ) Σ ] i − n i = ( n + 1 ) . . . 2 n \begin{cases} \mathcal{X}_0 = \mu \\ \mathcal{X}_i = \mu + \left[\sqrt{(n+\lambda)\Sigma} \right]_i, & i=1...n \\ \mathcal{X}_i = \mu - \left[\sqrt{(n+\lambda)\Sigma}\right]_{i-n} & i=(n+1)...2n \end{cases} X0=μXi=μ+[(n+λ)Σ ]i,Xi=μ[(n+λ)Σ ]ini=1...ni=(n+1)...2n
    对于获取Sigma点中矩阵求根,使用便于计算的定义: Σ = S S T \Sigma = \mathbf{SS}^\mathsf T Σ=SST, S \mathbf{S} S即为 Σ \Sigma Σ的根,通常用scipy.linalg.cholesky()计算,返回上三角矩阵,因此选用每1行为1个Sigma点.
    代码:
# 初始化权重:
def calc_weight(n, alpha, beta, kappa):
    lambda_ = alpha ** 2 * (n + kappa) - n
    Wc = np.full(2 * n + 1, 1. / (2 * (n + lambda_)))  # np.full 可以避免循环
    Wm = np.full(2 * n + 1, 1. / (2 * (n + lambda_)))
    Wc[0] = lambda_ / (n + lambda_) + (1. - alpha ** 2 + beta)
    Wm[0] = lambda_ / (n + lambda_)
    return Wc, Wm
# 获取Sigma点:
def get_sigma_pnt(n, X, P, lambda_):
    sigmas = np.zeros((2 * n + 1, n))
    U = scipy.linalg.cholesky((n + lambda_) * P)  # sqrt
    sigmas[0] = X
    for k in range(n):
        sigmas[k + 1] = X + U[k]
        sigmas[n + k + 1] = X - U[k]
  1. 计算先验预测: UT变换
    Y = f ( χ , Δ t ) x ˉ = ∑ i = 0 2 n w i m Y i P ˉ = ∑ i = 0 2 n w i c ( Y i − x ˉ ) ( Y i − x ˉ ) T + Q \begin{aligned} \boldsymbol{\mathcal{Y}} = f(\boldsymbol{\chi}, \Delta t)\\ \mathbf{\bar x} &= \sum_{i=0}^{2n} w^m_i\boldsymbol{\mathcal Y}_i\\ \mathbf{\bar P} &= \sum_{i=0}^{2n} w^c_i({\boldsymbol{\mathcal Y}_i - \mathbf{\bar x})(\boldsymbol{\mathcal Y}_i-\mathbf{\bar x})^\mathsf{T}} + \mathbf Q \end{aligned} Y=f(χ,Δt)xˉPˉ=i=02nwimYi=i=02nwic(Yixˉ)(Yixˉ)T+Q

代码:

def ukf_predict(Wm, Wc, sigmas, Q):  # ukf的预测也就是UT变换
	# 状态预测:
    x = np.dot(Wm, sigmas)  # sigmas应该是传参前投影
	# 协方差预测
    kmax, n = sigmas.shape
    P = np.zeros((n, n))
    for k in range(kmax):
        y = sigmas[k] - x
        P += Wc[k] * np.outer(y, y)  # numpy不区分一维矩阵的转置,所以调用此函数
    P += Q
    return x, P
def sigma_project(sigmas, fx, dt):  # get的sigma点集,需要投影到的空间函数,dt
    sigmas_f = sigmas
    for i in sigmas.shape[0]:
        sigmas_f[i] = fx(sigmas[i], dt)  # 可能需要改
    return sigmas_f

KF与UKF先验预测对比:
Kalman Unscented Y = f ( χ ) x ˉ = F x x ˉ = ∑ w m Y P ˉ = F P F T + Q P ˉ = ∑ w c ( Y − x ˉ ) ( Y − x ˉ ) T + Q \begin{array}{l|l} \text{Kalman} & \text{Unscented} \\ \hline & \boldsymbol{\mathcal Y} = f(\boldsymbol\chi) \\ \mathbf{\bar x} = \mathbf{Fx} & \mathbf{\bar x} = \sum w^m\boldsymbol{\mathcal Y} \\ \mathbf{\bar P} = \mathbf{FPF}^\mathsf T + \mathbf Q & \mathbf{\bar P} = \sum w^c({\boldsymbol{\mathcal Y} - \mathbf{\bar x})(\boldsymbol{\mathcal Y} - \mathbf{\bar x})^\mathsf T}+\mathbf Q \end{array} Kalmanxˉ=FxPˉ=FPFT+QUnscentedY=f(χ)xˉ=wmYPˉ=wc(Yxˉ)(Yxˉ)T+Q

更新

  1. 所有卡尔曼都是在测量空间更新,所以需要将预测Sigma点投影到测量空间: Z = h ( Y ) \boldsymbol{\mathcal{Z}} = h(\boldsymbol{\mathcal{Y}}) Z=h(Y) (调用sigma_project函数)
  2. 对于测量空间中的先验进行UT变换:(直接调用预测函数即可)
    μ z , P z = U T ( Z , w m , w c , R ) μ z = ∑ i = 0 2 n w i m Z i P z = ∑ i = 0 2 n w i c ( Z i − μ z ) ( Z i − μ z ) T + R \begin{aligned} \boldsymbol\mu_z, \mathbf P_z &= UT(\boldsymbol{\mathcal Z}, w_m, w_c, \mathbf R) \\ \boldsymbol\mu_z &= \sum_{i=0}^{2n} w^m_i\boldsymbol{\mathcal Z}_i \\ \mathbf P_z &= \sum_{i=0}^{2n} w^c_i{(\boldsymbol{\mathcal Z}_i-\boldsymbol{\mu}_z)(\boldsymbol{\mathcal Z}_i-\boldsymbol{\mu}_z)^\mathsf T} + \mathbf R \end{aligned} μz,PzμzPz=UT(Z,wm,wc,R)=i=02nwimZi=i=02nwic(Ziμz)(Ziμz)T+R
  3. 计算实际观测值与预测投影到观测空间的差值得到y(结合卡尔曼增益来更新预测):
    y = z − μ z \mathbf y = \mathbf z - \boldsymbol\mu_z y=zμz
  4. 计算卡尔曼增益:(1. 状态与测量的协方差;2. 结合预测协方差得到增益)
    P x z = ∑ i = 0 2 n w i c ( Y i − x ˉ ) ( Z i − μ z ) T \mathbf P_{xz} =\sum_{i=0}^{2n} w^c_i(\boldsymbol{\mathcal Y}_i-\mathbf{\bar x})(\boldsymbol{\mathcal Z}_i-\boldsymbol\mu_z)^\mathsf T Pxz=i=02nwic(Yixˉ)(Ziμz)T
    卡尔曼增益:(其实就是状态置信度与测量空间置信度之比)
    K = P x z P z − 1 \mathbf{K} = \mathbf P_{xz} \mathbf P_z^{-1} K=PxzPz1
  5. 最后得到后验:
    状态: x = x ˉ + K y ;方差: P = P ˉ − K P z K T 状态:\mathbf x = \bar{\mathbf x} + \mathbf{Ky};方差: \mathbf P = \mathbf{\bar P} - \mathbf{KP_z}\mathbf{K}^\mathsf{T} 状态:x=xˉ+Ky;方差:P=PˉKPzKT
    代码:
def ukf_update(sigmas_f, xp, Pp, hx, z, Wm, Wc, R, dt):
    # 1 投影
    sigmas_h = sigma_project(sigmas_f, hx, dt)
    # 2 投影后的预测值进行UT变换
    zp, Pz = ut_ukf_predict(sigmas_h, Wm, Wc, R)
    # 3 求差值
    y = z - zp
    # 4 状态与测量的交叉方差 与 卡尔曼增益
    Pxz = np.zeros((X_dim, Z_dim))
    for i in range(sigmas_f.shape[0]):
        Pxz += Wc[i] * np.outer(sigmas_f[i] - xp, sigmas_h[i] - zp)
    K = np.dot(Pxz, np.linalg.inv(Pz))  # Kalman 增益
    # 5 计算后验
    x_post = xp + np.dot(K, y)
    P_post = Pp - np.dot(K, Pz).dot(K.T)
    return x_post, P_post

后验对比:
Kalman Filter Unscented Kalman Filter Y = f ( χ ) x ˉ = F x x ˉ = ∑ w m Y P ˉ = F P F T + Q P ˉ = ∑ w c ( Y − x ˉ ) ( Y − x ˉ ) T + Q Z = h ( Y ) μ z = ∑ w m Z y = z − H x y = z − μ z S = H P ˉ H T + R P z = ∑ w c ( Z − μ z ) ( Z − μ z ) T + R K = P ˉ H T S − 1 K = [ ∑ w c ( Y − x ˉ ) ( Z − μ z ) T ] P z − 1 x = x ˉ + K y x = x ˉ + K y P = ( I − K H ) P ˉ P = P ˉ − K P z K T \begin{array}{l|l} \textrm{Kalman Filter} & \textrm{Unscented Kalman Filter} \\ \hline & \boldsymbol{\mathcal Y} = f(\boldsymbol\chi) \\ \mathbf{\bar x} = \mathbf{Fx} & \mathbf{\bar x} = \sum w^m\boldsymbol{\mathcal Y} \\ \mathbf{\bar P} = \mathbf{FPF}^\mathsf T+\mathbf Q & \mathbf{\bar P} = \sum w^c({\boldsymbol{\mathcal Y} - \mathbf{\bar x})(\boldsymbol{\mathcal Y} - \mathbf{\bar x})^\mathsf T}+\mathbf Q \\ \hline & \boldsymbol{\mathcal Z} = h(\boldsymbol{\mathcal{Y}}) \\ & \boldsymbol\mu_z = \sum w^m\boldsymbol{\mathcal{Z}} \\ \mathbf y = \mathbf z - \mathbf{Hx} & \mathbf y = \mathbf z - \boldsymbol\mu_z \\ \mathbf S = \mathbf{H\bar PH}^\mathsf{T} + \mathbf R & \mathbf P_z = \sum w^c{(\boldsymbol{\mathcal Z}-\boldsymbol\mu_z)(\boldsymbol{\mathcal{Z}}-\boldsymbol\mu_z)^\mathsf{T}} + \mathbf R \\ \mathbf K = \mathbf{\bar PH}^\mathsf T \mathbf S^{-1} & \mathbf K = \left[\sum w^c(\boldsymbol{\mathcal Y}-\bar{\mathbf x})(\boldsymbol{\mathcal{Z}}-\boldsymbol\mu_z)^\mathsf{T}\right] \mathbf P_z^{-1} \\ \mathbf x = \mathbf{\bar x} + \mathbf{Ky} & \mathbf x = \mathbf{\bar x} + \mathbf{Ky}\\ \mathbf P = (\mathbf{I}-\mathbf{KH})\mathbf{\bar P} & \mathbf P = \bar{\mathbf P} - \mathbf{KP_z}\mathbf{K}^\mathsf{T} \end{array} Kalman Filterxˉ=FxPˉ=FPFT+Qy=zHxS=HPˉHT+RK=PˉHTS1x=xˉ+KyP=(IKH)PˉUnscented Kalman FilterY=f(χ)xˉ=wmYPˉ=wc(Yxˉ)(Yxˉ)T+QZ=h(Y)μz=wmZy=zμzPz=wc(Zμz)(Zμz)T+RK=[wc(Yxˉ)(Zμz)T]Pz1x=xˉ+KyP=PˉKPzKT

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值