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]
代码:
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(Y−xˉ)(Y−xˉ)T+Q
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=z−HxS=HPˉHT+RK=PˉHTS−1x=xˉ+KyP=(I−KH)PˉUnscented Kalman FilterY=f(χ)xˉ=∑wmYPˉ=∑wc(Y−xˉ)(Y−xˉ)T+QZ=h(Y)μz=∑wmZy=z−μzPz=∑wc(Z−μz)(Z−μz)T+RK=[∑wc(Y−xˉ)(Z−μz)T]Pz−1x=xˉ+KyP=Pˉ−KPzKT