扩展卡尔曼滤波(Extended Kalman Filter, EKF)是一种常用的状态估计方法,适用于非线性系统。在 C++ 中实现 EKF,可以通过类和函数的方式更好地组织代码。下面是一个简单的 C++ 实现示例,涵盖了 EKF 的基本步骤:状态预测、协方差预测、状态更新和协方差更新。
1. 头文件和类定义
#include <iostream>
#include <vector>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
class ExtendedKalmanFilter {
public:
ExtendedKalmanFilter(int state_dim, int measurement_dim);
void predict();
void update(const VectorXd& z);
VectorXd getState() const { return x_; }
MatrixXd getCovariance() const { return P_; }
private:
int state_dim_; // 状态维度
int measurement_dim_; // 测量维度
VectorXd x_; // 状态向量
MatrixXd P_; // 协方差矩阵
MatrixXd F_; // 状态转移矩阵
MatrixXd H_; // 测量矩阵
MatrixXd Q_; // 过程噪声协方差矩阵
MatrixXd R_; // 测量噪声协方差矩阵
MatrixXd I_; // 单位矩阵
};
// 构造函数
ExtendedKalmanFilter::ExtendedKalmanFilter(int state_dim, int measurement_dim)
: state_dim_(state_dim), measurement_dim_(measurement_dim),
x_(VectorXd::Zero(state_dim)), P_(MatrixXd::Identity(state_dim, state_dim)),
F_(MatrixXd::Identity(state_dim, state_dim)), H_(MatrixXd::Zero(measurement_dim, state_dim)),
Q_(MatrixXd::Identity(state_dim, state_dim)), R_(MatrixXd::Identity(measurement_dim, measurement_dim)),
I_(MatrixXd::Identity(state_dim, state_dim)) {
// 初始化矩阵
// 这里可以根据实际需要初始化 F_, H_, Q_, R_
}
2、预测步骤
void ExtendedKalmanFilter::predict() {
// 状态预测
x_ = F_ * x_;
// 协方差预测
P_ = F_ * P_ * F_.transpose() + Q_;
}
3、更新步骤
void ExtendedKalmanFilter::update(const VectorXd& z) {
// 计算测量预测
VectorXd y = z - H_ * x_;
MatrixXd Ht = H_.transpose();
MatrixXd S = H_ * P_ * Ht + R_;
MatrixXd Si = S.inverse();
MatrixXd K = P_ * Ht * Si;
// 更新状态
x_ = x_ + K * y;
// 更新协方差
MatrixXd I_KH = I_ - K * H_;
P_ = I_KH * P_;
}
4、主函数示例
int main() {
int state_dim = 4; // 例如 4 维状态
int measurement_dim = 2; // 例如 2 维测量
ExtendedKalmanFilter ekf(state_dim, measurement_dim);
// 初始化矩阵 F, H, Q, R
// 假设系统模型和测量模型如下
ekf.F_ << 1, 0, 1, 0,
0, 1, 0, 1,
0, 0, 1, 0,
0, 0, 0, 1;
ekf.H_ << 1, 0, 0, 0,
0, 1, 0, 0;
ekf.Q_ << 0.01, 0, 0, 0,
0, 0.01, 0, 0,
0, 0, 0.01, 0,
0, 0, 0, 0.01;
ekf.R_ << 0.1, 0,
0, 0.1;
// 进行预测和更新
for (int i = 0; i < 10; ++i) {
ekf.predict();
// 这里是测量值示例
VectorXd z(measurement_dim);
z << sin(i * 0.1), cos(i * 0.1);
ekf.update(z);
// 打印状态和协方差矩阵
cout << "Step " << i << ":\n";
cout << "State:\n" << ekf.getState() << endl;
cout << "Covariance:\n" << ekf.getCovariance() << endl;
}
return 0;
}
代码解释
-
类定义:
ExtendedKalmanFilter
类包含 EKF 所需的矩阵和向量,并提供预测和更新方法。- 构造函数初始化了状态向量、协方差矩阵和噪声矩阵。
-
预测步骤:
- 使用状态转移矩阵
F_
预测下一个状态。 - 更新协方差矩阵
P_
。
- 使用状态转移矩阵
-
更新步骤:
- 计算测量预测的残差
y
。 - 计算卡尔曼增益
K
。 - 更新状态和协方差矩阵。
- 计算测量预测的残差
-
主函数:
- 初始化 EKF 对象,设置模型矩阵。
- 进行若干次预测和更新循环,并打印结果。
依赖库
示例代码使用了 Eigen 库来处理矩阵运算。你可以通过以下命令安装 Eigen 库:
sudo apt-get install libeigen3-dev
在编译时,记得链接 Eigen 库:
g++ -I /usr/include/eigen3 -o ekf_example ekf_example.cpp
结论
这个示例代码展示了如何在 C++ 中实现扩展卡尔曼滤波算法。实际应用中,你需要根据系统和测量模型调整矩阵和算法的具体实现。Eigen 库是处理线性代数运算的一个强大工具,能帮助简化矩阵操作。