基于导航信息的EKF滤波算法实现(附源码)
2022/3/20 20:29:19
本文主要是介绍基于导航信息的EKF滤波算法实现(附源码),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
继上一篇实现了Joan Sola大神的ESKF之后,就想着举一反三,也实现一下EKF算法,因此就研究了一下深蓝学院的《多传感器融合定位》算法中基于导航信息的滤波算法,同时对算法进行代码实现。先附上两张效果图(看起来跟前一篇文章ESKF的差不多)。
下面对公式进行详细的推导,也给出我自己的一些理解。
1. 前言
卡尔曼滤波的主要方程就是预测方程和观测方程的构建。两个方程如下:
有的模型可以很容易推出运动方程,而有的模型不好直接构建两个状态之间的关系,没法推导出运动方程,因此这里也可以使用状态量的微分方程来间接推导出运动方程。
2. 基于导航信息的滤波
1)导航信息的微分方程
这里使用的状态量为,其中为角速度的bias,为加速度的bias。值得注意的是,这里的四元数的顺序是实部在前,虚步在后,这个顺序也可以从后面求解F矩阵时可以看出。
导航信息的微分方程如下:
因此可以将状态方程写成如下的微分形式:
它具有非线性,所以需要进行线形话,可以得到
2) 雅可比矩阵求解
将微分方程进行线性化
雅可比矩阵推导:
这里需要说明一下四元数乘积:
3)连续系统微分方程离散化
因为得到的是连续时间微分方程,所以这里需要进行离散化。这里参考的是:机器人动力学仿真——状态空间模型的离散化
3-1)精确离散化
3-2)近似离散化
3-3)本系统离散化结果
3. 代码说明
代码里面是严格按按照公式进行推导的,这里只贴出预测和更新方程的关键代码
预测:
// IMU数据预测 bool EKF::Predict(const IMUData &curr_imu_data) { imu_data_buff_.push_back(curr_imu_data); double delta_t = curr_imu_data.time - imu_data_buff_.front().time; // dt Eigen::Vector3d curr_accel = curr_imu_data.linear_accel; // 局部坐标系下加速度 Eigen::Vector3d curr_angle_velocity = curr_imu_data.angle_velocity; // 局部坐标系下的角速度 Eigen::Quaterniond curr_ori = Eigen::Quaterniond(pose_.block<3, 3>(0, 0)); UpdateEkfState(delta_t, curr_accel,curr_angle_velocity,curr_ori); UpdateState(); //! 每次都需要更新位姿 imu_data_buff_.pop_front(); return true; } bool EKF::UpdateEkfState(const double t, const Eigen::Vector3d &accel, const Eigen::Vector3d& curr_angle_velocity, const Eigen::Quaterniond& curr_ori ) { F_.setZero(); // 初始化为零矩阵 F_.block<3,3>(INDEX_STATE_POSI, INDEX_STATE_VEL) = Eigen::Matrix3d::Identity(); double q0 = curr_ori.w(); double q1 = curr_ori.x(); double q2 = curr_ori.y(); double q3 = curr_ori.z(); double FVq0 = 2 * Eigen::Vector3d(q0,-q3,q2).transpose()*accel; double FVq1 = 2 * Eigen::Vector3d(q1,q2,q3).transpose()*accel; double FVq2 = 2 * Eigen::Vector3d(-q2,q1,q0).transpose()*accel; double FVq3 = 2 * Eigen::Vector3d(-q3,-q0,q1).transpose()*accel; Eigen::Matrix<double,3,4> FVq = (Eigen::Matrix<double,3,4>()<< FVq0,FVq1,FVq2,FVq3, -FVq3,-FVq2,FVq1,FVq0, FVq2,-FVq3,-FVq0,FVq1).finished(); F_.block<3,4>(INDEX_STATE_VEL, INDEX_STATE_ORI) = FVq; F_.block<3,3>(INDEX_STATE_VEL, INDEX_STATE_ACC_BIAS) = pose_.block<3,3>(0,0); Eigen::Vector3d w = curr_angle_velocity; Eigen::Matrix<double,4,4> Fqq = 0.5* (Eigen::Matrix<double,4,4>()<<0,-w.x(),-w.y(),-w.z(), w.x(),0,w.z(),-w.y(), w.y(),-w.z(),0,w.x(), w.z(),w.y(),-w.x(),0).finished(); F_.block<4,4>(INDEX_STATE_ORI,INDEX_STATE_ORI) = Fqq; Eigen::Matrix<double,4,3> Fqkesi = 0.5 * (Eigen::Matrix<double,4,3>()<<-q1,-q2,-q3, q0,-q3,q2, q3,q0,-q1, -q2,q1,q0).finished(); F_.block<4,3>(INDEX_STATE_ORI,INDEX_STATE_GYRO_BIAS) = Fqkesi; B_.setZero(); B_.block<3,3>(INDEX_STATE_VEL, 3) = pose_.block<3,3>(0,0); B_.block<4,3>(INDEX_STATE_ORI, 0) = Fqkesi; TypeMatrixF Fk = TypeMatrixF::Identity() + F_ * t; TypeMatrixB Bk = B_ * t; X_ = Fk * X_ + Bk * W_+ gt_*t ; P_ = Fk * P_ * Fk.transpose() + Bk * Q_ * Bk.transpose(); return true; }
更新:
bool EKF::Correct(const GPSData &curr_gps_data) { curr_gps_data_ = curr_gps_data; C_.setIdentity(); // 单位矩阵 G_.setZero(); G_.block<3,3>(INDEX_MEASUREMENT_POSI, INDEX_MEASUREMENT_POSI) = Eigen::Matrix3d::Identity(); Y_ = curr_gps_data.position_ned; //Y_measure K_ = P_ * G_.transpose() * (G_ * P_ * G_.transpose() + C_ * R_ * C_.transpose()).inverse(); // kalman增益 P_ = (TypeMatrixP::Identity() - K_ * G_) * P_; // P_ = (TypeMatrixP::Identity() - K_ * G_) * P_ * (TypeMatrixP::Identity() - K_ * G_).transpose()+K_*C_*K_.transpose(); X_ = X_ + K_ * (Y_ - G_ * X_); UpdateState(); return true; }
4. 总结
EKF和ESKF的区别:
1)ESKF每次需要根据运动方程算里程计,而EKF的预测方程就代替了里程计的计算
2)ESKF的状态量更紧凑,没有冗余,而EKF表示旋转的四元数有冗余
5.参考文献
机器人动力学仿真——状态空间模型的离散化 - 古月居
【附源码+代码注释】误差状态卡尔曼滤波(error-state Kalman Filter),扩展卡尔曼滤波,实现GPS+IMU融合,EKF ESKF GPS+IMU_一点儿也不萌的萌萌的博客-CSDN博客_误差卡尔曼
Quaternion kinematics for error state kalman filter实现GPS+IMU融合,(附源码)_qq_38650944的博客-CSDN博客
多传感器融合定位第四章
这篇关于基于导航信息的EKF滤波算法实现(附源码)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南