VINS-mono 代码解析——IMU预积分processIMU( )实现

本文深入解析VINS-mono中的processIMU函数,涉及IntegrationBase类、push_back()、evaluate()、propagate()、midPointIntegration()以及repropagate()。介绍了预积分在IMU数据处理中的关键步骤,如状态变化量计算、残差与雅可比矩阵的构建,以及中值积分法的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在VINS-mono中,estimator/src/estimator_node.cpp中,从主函数依次为:

main( )---->process( )---->processIMU( )

其中,processIMU( )函数的原型为:

void Estimator::processIMU(double dt, const Vector3d &linear_acceleration, const Vector3d &angular_velocity)

一 processIMU()函数

// IMU预积分,中值积分得到当前PQV作为 优化 初值
void Estimator::processIMU(double dt, const Vector3d &linear_acceleration, const Vector3d &angular_velocity)
{
   
     // 1.判断是不是第一个imu消息,如果是第一个imu消息,则将当前传入的线加速度和角速度作为初始的加速度和角速度
    if (!first_imu)
    {
   
        first_imu = true;
        acc_0 = linear_acceleration;
        gyr_0 = angular_velocity;
    }

     // 2.IMU 预积分类对象还没出现,创建一个对象
    if (!pre_integrations[frame_count])
    {
   
        pre_integrations[frame_count] = new IntegrationBase{
   acc_0, gyr_0, Bas[frame_count], Bgs[frame_count]};
    }
    //当frame_count==0的时候表示滑动窗口中还没有图像帧数据,不需要进行预积分,只进行线加速度和角速度初始值的更新
    if (frame_count != 0)
    {
   
         // 3.预积分操作
        pre_integrations[frame_count]->push_back(dt, linear_acceleration, angular_velocity);
        //if(solver_flag != NON_LINEAR)
            tmp_pre_integration->push_back(dt, linear_acceleration, angular_velocity);

        // 4.dt、加速度、角速度加到buf中
        dt_buf[frame_count].push_back(dt);
        linear_acceleration_buf[frame_count].push_back(linear_acceleration);
        angular_velocity_buf[frame_count].push_back(angular_velocity);

        int j = frame_count;
        // 5.采用的是中值积分的传播方式         
        Vector3d un_acc_0 = Rs[j] * (acc_0 - Bas[j]) - g;// a0=Q(a^-ba)-g 已知上一帧imu速度
        Vector3d un_gyr = 0.5 * (gyr_0 + angular_velocity) - Bgs[j];// w=0.5(w0+w1)-bg
        Rs[j] *= Utility::deltaQ(un_gyr * dt).toRotationMatrix();
        Vector3d un_acc_1 = Rs[j] * (linear_acceleration - Bas[j]) - g;// a1 当前帧imu速度
        Vector3d un_acc = 0.5 * (un_acc_0 + un_acc_1);// 中值积分下的加速度a=1/2(a0+a1)
        Ps[j] += dt * Vs[j] + 0.5 * dt * dt * un_acc;// P=P+v*t+1/2*a*t^2
        Vs[j] += dt * un_acc;// V=V+a*t

    }
    // 6.当frame_count==0的时候表示滑动窗口中还没有图像帧数据,不需要进行预积分,只进行线加速度和角速度初始值的更新
    acc_0 = linear_acceleration;
    gyr_0 = angular_velocity;
}

1 IMU 预积分IntegrationBase类

预积分类:加速度计、陀螺仪、线性加速度计ba、陀螺仪bg、雅克比矩阵初始化、协方差矩阵15*15、dt、PVQ

IntegrationBase() = delete;
    IntegrationBase(const Eigen::Vector3d &_acc_0, const Eigen::Vector3d &_gyr_0,
                    const Eigen::Vector3d &_linearized_ba, const Eigen::Vector3d &_linearized_bg)
        : acc_0{
   _acc_0}, gyr_0{
   _gyr_0}, linearized_acc{
   _acc_0}, linearized_gyr{
   _gyr_0},
          linearized_ba{
   _linearized_ba}, linearized_bg{
   _linearized_bg},
            jacobian{
   Eigen::Matrix<double, 15, 15>::Identity()}, covariance{
   Eigen::Matrix<double, 15, 15>::Zero()},
          sum_dt{
   0.0}, delta_p{
   Eigen::Vector3d::Zero()}, delta_q{
   Eigen::Quaterniond::Identity()}, delta_v{
   Eigen::Vector3d::Zero()}

    {
   
        noise = Eigen::Matrix<double, 18, 18>::Zero();
        noise.block<3, 3>(0, 0) =  (ACC_N * ACC_N) * Eigen::Matrix3d::Identity();
        noise.block<3, 3>(3, 3) =  (GYR_N * GYR_N) * Eigen::Matrix3d::Identity();
        noise.block<3, 3>(6, 6) =  (ACC_N * ACC_N) * Eigen::Matrix3d::Identity();
        noise.block<3, 3>(9, 9) =  (GYR_N * GYR_N) * Eigen::Matrix3d::Identity();
        noise.block<3, 3>(12, 12) =  (ACC_W * ACC_W) * Eigen::Matrix3d::Identity();
        noise.block<3, 3>(15, 15) =  (GYR_W * GYR_W) * Eigen::Matrix3d::Identity();
    }

2 push_back()函数

void push_back(double dt, const Eigen::Vector3d &acc, const Eigen::Vector3d &gyr)
    {
   
        dt_buf.push_back(dt);
        acc_buf.push_back(acc);
        gyr_buf.push_back(gyr);
        //进入预积分阶段
        propagate(dt, acc, gyr);
    }

3 evaluate()函数

预计分量
在这里插入图片描述
构建残差
在这里插入图片描述


    Eigen::Matrix<double, 15, 1> evaluate(const Eigen::Vector3d &Pi, const Eigen::Quaterniond &Qi, const Eigen::Vector3d &Vi, const Eigen::Vector3d &Bai, const Eigen::Vector3d &Bgi,
                                          const Eigen::Vector3d &Pj, const Eigen::Quaterniond &Qj, const Eigen::Vector3d &Vj, const Eigen::Vector3d &Baj, const Eigen::Vector3d &Bgj)
    {
   
        Eigen::Matrix<double, 15, 1> residuals;// 残差

        Eigen::Matrix3d dp_dba = jacobian.block<3, 3>(O_P, O_BA);
        Eigen::Matrix3d dp_dbg = jacobian.block<3, 3>(O_P, O_BG);

        Eigen::Matrix3d dq_dbg = jacobian.block<3, 3>(O_R, O_BG
VINS-Mono系统中,IMU预积分与图像特征点的融合对于优化状态估计至关重要。推荐您深入阅读《VINS-Mono算法解析:从观测值处理到回环检测》以获得详细的理论和实践指导。 参考资源链接:[VINS-Mono算法解析:从观测值处理到回环检测](https://wenku.youkuaiyun.com/doc/oeigaoo91m?spm=1055.2569.3001.10343) 首先,IMU预积分是处理连续多帧IMU数据的过程,它将IMU测量值通过积分转换为状态转移矩阵F和雅克比矩阵jacobian。这一过程有助于获得连续帧之间的运动估计,为融合图像特征点提供一个运动学基础。VINS-Mono通过`processIMU()`函数实现IMU预积分,该函数会在每个时间步更新这些矩阵,为后续的融合步骤准备必要的信息。 接着,图像特征点的提取和匹配是构建视觉观测的基础。在初始化阶段,系统会利用这些特征点来获得初始的姿态估计。视觉初始化只依赖于特征点,而视觉惯性联合初始化则结合IMU预积分结果,通常能提供更稳定和快速的初始化过程。 在局部视觉惯性BA阶段,系统采用滑动窗口优化策略,对当前窗口内的图像特征点和IMU数据进行同时优化。这里,IMU预积分结果提供了连续帧之间的约束,而图像特征点则提供了空间上的约束。通过优化这些约束,系统能够获得更为准确和稳定的状态估计。 最后,在全局图优化阶段,系统会对整个轨迹进行优化,以修正累积误差。这个阶段,IMU预积分和图像特征点的融合对于确保长期运行的稳定性至关重要。回环检测可以进一步通过角点匹配和光流跟踪来修正全局路径,进一步提升定位的准确性。 整个过程中,IMU预积分和图像特征点的有效融合,结合了IMU的短期精度高和图像特征点的长期稳定性好的优点,极大提高了VINS-Mono系统的导航精度和鲁棒性。 在掌握了IMU预积分与图像特征点融合的基本原理和方法后,想要进一步深入学习VINS-Mono的高级应用和优化技术,建议继续参考《VINS-Mono算法解析:从观测值处理到回环检测》。该资源全面覆盖了VINS-Mono的关键部分,包括观测数据预处理、初始化、局部视觉惯性BA与重定位、全局图优化以及回环检测等,能够为想要深化理解或实际应用VINS-Mono系统的研究者和开发者提供宝贵的指导。 参考资源链接:[VINS-Mono算法解析:从观测值处理到回环检测](https://wenku.youkuaiyun.com/doc/oeigaoo91m?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值