PDR/1.Software/Simualator/Src/Kalman.cpp

130 lines
4.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <string.h>
#include "Kalman.h"
#include "Matrix.h"
// 扩展卡尔曼向量缓存
static double EkfVecBuf[5][N] = { {0.0} };
// 扩展卡尔曼矩阵缓存
static double EkfMatBuf[7][N][N] = { { {0.0} } };
/**----------------------------------------------------------------------
* Function : EKF_Init
* Description : 初始化卡尔曼滤波器相关
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void EKF_Init(void) {
memset(EkfMatBuf, 0, sizeof(double) * 7 * N * N);
memset(EkfVecBuf, 0, sizeof(double) * 5 * N);
}
/**----------------------------------------------------------------------
* Function : EKFCalQRMatrix
* Description : 根据GPS信号特征调整卡尔曼滤波噪声矩阵q矩阵是过程噪声矩阵
* 需要跟惯导预测位置精度相关。r矩阵为GNSS观测噪声跟GPS输出的
* 信息精度有关。
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void EKFCalQRMatrix() {
memset(EkfMatBuf, 0, sizeof(double) * 7 * N * N);
memset(EkfVecBuf, 0, sizeof(double) * 5 * N);
}
/**----------------------------------------------------------------------
* Function : EKFStateUpdate
* Description : 扩展卡尔曼滤波器的状态更新方程
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
void EKFStateUpdate(EKFPara_t* kf) {
double lambda = 0;
// NxN矩阵定义
double(*H)[N] = (double(*)[N]) & (EkfMatBuf[0][0][0]);
double(*I)[N] = (double(*)[N]) & (EkfMatBuf[1][0][0]);
double(*pvec1)[N] = (double(*)[N]) & (EkfMatBuf[2][0][0]);
double(*Ht)[N] = (double(*)[N]) & (EkfMatBuf[3][0][0]);
double(*pvec3)[N] = (double(*)[N]) & (EkfMatBuf[4][0][0]);
double(*pvec4)[N] = (double(*)[N]) & (EkfMatBuf[5][0][0]);
double(*pv3)[N] = (double(*)[N]) & (EkfMatBuf[6][0][0]);
memset(EkfMatBuf, 0, sizeof(double) * 7 * N * N);
memset(EkfVecBuf, 0, sizeof(double) * 5 * N);
// Nx1向量定义
double* z = &(EkfVecBuf[0][0]);
double(*pvec5) = &(EkfVecBuf[1][0]);
double(*pvec6) = &(EkfVecBuf[2][0]);
double(*pv1) = &(EkfVecBuf[3][0]);
double(*pv2) = &(EkfVecBuf[4][0]);
// 创建单位矩阵
for (char i = 0; i < 4; i++) {
H[i][i] = 1;
I[i][i] = 1;
}
//z[0] = pgnss->xNed; // 北向位置
//z[1] = pgnss->yNed; // 东向位置
//z[2] = 0.5; // 步长默认0.5
//z[3] = pgnss->yaw * PI / 180;
// 计算 K = K = PHt / (R + H*P*H^T)
MatrixTrans(H, Ht); // 计算Ht
MatrixMultiply(H, kf->pPk, pvec1); // 计算HP
MatrixMultiply(pvec1, Ht, pvec3); // pvec3 = H*P*H^T
MatrixAdd(pvec3, kf->R, pvec4); // pvec4 = R + H*P*H^T
MatrixInverse(pvec4, pvec1); // 计算 1 / (R + H*P*H^T)
for (char i = 0; i < N; i++) {
for (char j = 0; j < N; j++) {
pv3[i][j] = pvec3[i][j];
}
}
MatrixMultiply(kf->pPk, Ht, pvec3); // 计算PHt
MatrixMultiply(pvec3, pvec1, kf->Kk); // 计算增益K = PHt / (R + H*P*H^T)
VecMatMultiply(kf->pXk, H, pvec5); // pvec5 = Hx'
VectorSub(z, pvec5, pvec6); // pvec6 = Z - Hx'
//modAngle(&pvec6[3], -PI, PI);
for (char i = 0; i < N; i++) {
pv1[i] = pvec6[i];
}
VecMatMultiply(pvec6, kf->Kk, pvec5); // pvec5 = K*( z - Hx')
// Get the optimally updated state estimation
VectorAdd(kf->pXk, pvec5, kf->Xk);
// pvec1 = K*H
MatrixMultiply(kf->Kk, H, pvec1);
// pvec2 = (I - K*H)
MatrixSub(I, pvec1, Ht);
// pvec3 = (I - K*H)*P
MatrixMultiply(Ht, kf->pPk, pvec3);
// pvec4 = (I- K*H)^T
MatrixTrans(Ht, pvec4);
// pvec1 = (I - K*H)*P*(I- K*H)^T
MatrixMultiply(pvec3, pvec4, pvec1);
// pvec2 = K*R
MatrixMultiply(kf->Kk, kf->R, Ht);
// pvec3 = K^T
MatrixTrans(kf->Kk, pvec3);
// pvec4 = K*R*K^T
MatrixMultiply(Ht, pvec3, pvec4);
// Get the updated estimate covariance: P' = (I - K*H)*P*(I- K*H)^T + K*R*K^T
MatrixAdd(pvec1, pvec4, kf->Pk);
// pv2 = (z - Hx')*( H*P*H^T )
VecMatMultiply(pv1, pv3, pv2);
}
/**----------------------------------------------------------------------
* Function : EKFUpdateInsState
* Description : 扩展卡尔曼滤波器更新INS状态
* Date : 2022/09/23 logzhan
*---------------------------------------------------------------------**/
void EKFUpdateInsState() {
}