水军大提督 发表于 2025-1-12 10:09:57

LIO-SAM代码解析:imuPreintegration.cpp(一)

1.imuHandler

imuHandler 函数用于处理IMU(惯性丈量单元)数据,通过积分IMU丈量值预测当前的位姿与速度,并将IMU位姿转换到激光雷达坐标系,最终发布惯导里程计数据。

[*]接收并处理IMU丈量值;
[*]对IMU数据进行积分,预测当前位姿与速度;
[*]将IMU位姿转换到激光雷达坐标系;
[*]发布激光雷达坐标系下的惯导里程计。
// IMU 数据处理回调函数
void imuHandler(const sensor_msgs::Imu::ConstPtr& imu_raw)
{
    // 加锁,确保线程安全
    std::lock_guard<std::mutex> lock(mtx);

    // 转换原始 IMU 数据
    sensor_msgs::Imu thisImu = imuConverter(*imu_raw);

    // 将转换后的 IMU 数据加入优化队列和 IMU 队列
    imuQueOpt.push_back(thisImu);
    imuQueImu.push_back(thisImu);

    // 如果尚未完成第一次优化,则退出函数
    if (doneFirstOpt == false)
      return;

    // 获取当前 IMU 数据的时间戳
    double imuTime = ROS_TIME(&thisImu);
   
    // 计算时间间隔 dt
    double dt = (lastImuT_imu < 0) ? (1.0 / 500.0) : (imuTime - lastImuT_imu);
    lastImuT_imu = imuTime;

    // 积分当前 IMU 测量数据
    imuIntegratorImu_->integrateMeasurement(
      gtsam::Vector3(thisImu.linear_acceleration.x, thisImu.linear_acceleration.y, thisImu.linear_acceleration.z),
      gtsam::Vector3(thisImu.angular_velocity.x,    thisImu.angular_velocity.y,    thisImu.angular_velocity.z),
      dt
    );

    // 使用积分后的状态预测当前的导航状态
    gtsam::NavState currentState = imuIntegratorImu_->predict(prevStateOdom, prevBiasOdom);

    // 创建并初始化里程计消息
    nav_msgs::Odometry odometry;
    odometry.header.stamp = thisImu.header.stamp;
    odometry.header.frame_id = odometryFrame;
    odometry.child_frame_id = "odom_imu";

    // 将 IMU 位姿转换到激光雷达坐标系
    gtsam::Pose3 imuPose = gtsam::Pose3(currentState.quaternion(), currentState.position());
    gtsam::Pose3 lidarPose = imuPose.compose(imu2Lidar);

    // 填充里程计位置信息
    odometry.pose.pose.position.x = lidarPose.translation().x();
    odometry.pose.pose.position.y = lidarPose.translation().y();
    odometry.pose.pose.position.z = lidarPose.translation().z();
    odometry.pose.pose.orientation.x = lidarPose.rotation().toQuaternion().x();
    odometry.pose.pose.orientation.y = lidarPose.rotation().toQuaternion().y();
    odometry.pose.pose.orientation.z = lidarPose.rotation().toQuaternion().z();
    odometry.pose.pose.orientation.w = lidarPose.rotation().toQuaternion().w();
   
    // 填充里程计速度信息
    odometry.twist.twist.linear.x = currentState.velocity().x();
    odometry.twist.twist.linear.y = currentState.velocity().y();
    odometry.twist.twist.linear.z = currentState.velocity().z();
    odometry.twist.twist.angular.x = thisImu.angular_velocity.x + prevBiasOdom.gyroscope().x();
    odometry.twist.twist.angular.y = thisImu.angular_velocity.y + prevBiasOdom.gyroscope().y();
    odometry.twist.twist.angular.z = thisImu.angular_velocity.z + prevBiasOdom.gyroscope().z();
   
    // 发布里程计消息
    pubImuOdometry.publish(odometry);
}
1. IMU丈量值积分
IMU数据包含线加速度                                              a                            imu                                       \mathbf{a}_{\text{imu}}                  aimu​ 和角速度                                              ω                            imu                                       \boldsymbol{\omega}_{\text{imu}}                  ωimu​,函数通过GTSAM库的 integrateMeasurement 方法对IMU丈量值进行积分,公式为:
                                                                                           v                                                       k                                           +                                           1                                                                                                                                     =                                                       v                                           k                                                      +                                        (                                                       R                                           k                                                      ⋅                                        (                                                       a                                           imu                                                      −                                                       b                                           a                                                      )                                        +                                        g                                        )                                        ⋅                                        Δ                                        t                                        ,                                                                                                                            p                                                       k                                           +                                           1                                                                                                                                     =                                                       p                                           k                                                      +                                                       v                                           k                                                      ⋅                                        Δ                                        t                                        +                                                       1                                           2                                                      (                                                       R                                           k                                                      ⋅                                        (                                                       a                                           imu                                                      −                                                       b                                           a                                                      )                                        +                                        g                                        )                                        ⋅                                        Δ                                                       t                                           2                                                      ,                                                                                                                            R                                                       k                                           +                                           1                                                                                                                                     =                                                       R                                           k                                                      ⋅                                        exp                                        ⁡                                        (                                        (                                                       ω                                           imu                                                      −                                                       b                                           ω                                                      )                                        ⋅                                        Δ                                        t                                        )                                        ,                                                                              \begin{aligned} \mathbf{v}_{k+1} &= \mathbf{v}_k + (\mathbf{R}_k \cdot (\mathbf{a}_{\text{imu}} - \mathbf{b}_a) + \mathbf{g}) \cdot \Delta t, \\ \mathbf{p}_{k+1} &= \mathbf{p}_k + \mathbf{v}_k \cdot \Delta t + \frac{1}{2} (\mathbf{R}_k \cdot (\mathbf{a}_{\text{imu}} - \mathbf{b}_a) + \mathbf{g}) \cdot \Delta t^2, \\ \mathbf{R}_{k+1} &= \mathbf{R}_k \cdot \exp((\boldsymbol{\omega}_{\text{imu}} - \mathbf{b}_\omega) \cdot \Delta t), \end{aligned}                     vk+1​pk+1​Rk+1​​=vk​+(Rk​⋅(aimu​−ba​)+g)⋅Δt,=pk​+vk​⋅Δt+21​(Rk​⋅(aimu​−ba​)+g)⋅Δt2,=Rk​⋅exp((ωimu​−bω​)⋅Δt),​
此中:


[*]                                                   v                               k                                          \mathbf{v}_k                     vk​ 和                                                    p                               k                                          \mathbf{p}_k                     pk​ 分别为速度和位置;
[*]                                                   R                               k                                          \mathbf{R}_k                     Rk​ 为姿态的旋转矩阵;
[*]                                                   b                               a                                          \mathbf{b}_a                     ba​ 和                                                    b                               ω                                          \mathbf{b}_\omega                     bω​ 分别为加速度和角速度的偏置;
[*]                                        g                                  \mathbf{g}                     g 为重力加速度;
[*]                                        Δ                            t                                  \Delta t                     Δt 为时间隔断。
2. 位姿预测
通过上述积分盘算,预测得到当前状态:
                                                    State                                           k                                  +                                  1                                                 =                                       [                                                                                                   p                                                               k                                                 +                                                 1                                                                                                                                                                  v                                                               k                                                 +                                                 1                                                                                                                                                                  R                                                               k                                                 +                                                 1                                                                                                                ]                                    .                                  \text{State}_{k+1} = \begin{bmatrix} \mathbf{p}_{k+1} \\ \mathbf{v}_{k+1} \\ \mathbf{R}_{k+1} \end{bmatrix}.                     Statek+1​=               ​pk+1​vk+1​Rk+1​​               ​.
函数中调用 imuIntegratorImu_->predict 实现此预测。
3. 位姿转换(IMU到激光雷达坐标系)
通过以下公式将IMU的位姿                                              T                            imu                                       \mathbf{T}_{\text{imu}}                  Timu​ 转换为激光雷达位姿                                              T                            lidar                                       \mathbf{T}_{\text{lidar}}                  Tlidar​:
                                                    T                               lidar                                    =                                       T                               imu                                    ⋅                                       T                               imu2lidar                                    ,                                  \mathbf{T}_{\text{lidar}} = \mathbf{T}_{\text{imu}} \cdot \mathbf{T}_{\text{imu2lidar}},                     Tlidar​=Timu​⋅Timu2lidar​,
此中                                              T                            imu2lidar                                       \mathbf{T}_{\text{imu2lidar}}                  Timu2lidar​ 是IMU到激光雷达的静态外参。
对于位姿                                    T                              \mathbf{T}                  T,其包含旋转                                    R                              \mathbf{R}                  R 宁静移                                    t                              \mathbf{t}                  t,即:
                                       T                            =                                       [                                                                                     R                                                                                             t                                                                                                                   0                                                                                             1                                                                                 ]                                    .                                  \mathbf{T} = \begin{bmatrix} \mathbf{R} & \mathbf{t} \\ \mathbf{0} & 1 \end{bmatrix}.                     T=.
4. 惯导里程计发布
最终通过以下公式将预测得到的激光雷达位姿和速度发布为惯导里程计数据:


[*]位置:
                                                          p                                  odom                                          =                                           T                                  lidar                                          .                               translation()                               .                                    \mathbf{p}_{\text{odom}} = \mathbf{T}_{\text{lidar}}.\text{translation()}.                        podom​=Tlidar​.translation().
[*]姿态:
                                                          q                                  odom                                          =                                           T                                  lidar                                          .                               rotation()                               .                                    \mathbf{q}_{\text{odom}} = \mathbf{T}_{\text{lidar}}.\text{rotation()}.                        qodom​=Tlidar​.rotation().
[*]线速度:
                                                          v                                  odom                                          =                                           v                                             k                                     +                                     1                                                      .                                    \mathbf{v}_{\text{odom}} = \mathbf{v}_{k+1}.                        vodom​=vk+1​.
[*]角速度:
                                                          ω                                  odom                                          =                                           ω                                  imu                                          +                                           b                                  ω                                          .                                    \boldsymbol{\omega}_{\text{odom}} = \boldsymbol{\omega}_{\text{imu}} + \mathbf{b}_\omega.                        ωodom​=ωimu​+bω​.
2. odometryHandler

odometryHandler 函数的重要功能是接收激光里程计数据,结合IMU预积分对系统状态进行优化,并更新系统的位姿、速度和偏置。以下为具体的数学过程。

[*]里程计与IMU初始对齐,构建优化图;
[*]集成IMU数据,构建IMU因子;
[*]添加里程计因子,调用优化器求解;
[*]提取优化效果,更新系统状态。
void odometryHandler(const nav_msgs::Odometry::ConstPtr& odomMsg)
{
    std::lock_guard<std::mutex> lock(mtx);// 保护共享资源,防止多线程访问时出现竞争条件

    double currentCorrectionTime = ROS_TIME(odomMsg);// 获取当前里程计消息的时间戳

    // 确保有IMU数据可供积分
    if (imuQueOpt.empty())
      return;

    // 从里程计消息中提取位置和姿态信息
    float p_x = odomMsg->pose.pose.position.x;
    float p_y = odomMsg->pose.pose.position.y;
    float p_z = odomMsg->pose.pose.position.z;
    float r_x = odomMsg->pose.pose.orientation.x;
    float r_y = odomMsg->pose.pose.orientation.y;
    float r_z = odomMsg->pose.pose.orientation.z;
    float r_w = odomMsg->pose.pose.orientation.w;
    bool degenerate = (int)odomMsg->pose.covariance == 1 ? true : false;// 检查是否为退化情况
    gtsam::Pose3 lidarPose = gtsam::Pose3(gtsam::Rot3::Quaternion(r_w, r_x, r_y, r_z), gtsam::Point3(p_x, p_y, p_z));// 构造激光雷达的位姿


    // 0. 初始化系统
    if (systemInitialized == false)
    {
      resetOptimization();// 重置优化器

      // 弹出旧的IMU消息
      while (!imuQueOpt.empty())
      {
            if (ROS_TIME(&imuQueOpt.front()) < currentCorrectionTime - delta_t)
            {
                lastImuT_opt = ROS_TIME(&imuQueOpt.front());
                imuQueOpt.pop_front();
            }
            else
                break;
      }
      // 初始位姿
      prevPose_ = lidarPose.compose(lidar2Imu);// 将激光雷达位姿转换为IMU位姿
      gtsam::PriorFactor<gtsam::Pose3> priorPose(X(0), prevPose_, priorPoseNoise);// 添加初始位姿先验因子
      graphFactors.add(priorPose);
      // 初始速度
      prevVel_ = gtsam::Vector3(0, 0, 0);// 初始速度为零
      gtsam::PriorFactor<gtsam::Vector3> priorVel(V(0), prevVel_, priorVelNoise);// 添加初始速度先验因子
      graphFactors.add(priorVel);
      // 初始偏差
      prevBias_ = gtsam::imuBias::ConstantBias();// 初始偏差为零
      gtsam::PriorFactor<gtsam::imuBias::ConstantBias> priorBias(B(0), prevBias_, priorBiasNoise);// 添加初始偏差先验因子
      graphFactors.add(priorBias);
      // 添加初始值
      graphValues.insert(X(0), prevPose_);
      graphValues.insert(V(0), prevVel_);
      graphValues.insert(B(0), prevBias_);
      // 优化一次
      optimizer.update(graphFactors, graphValues);
      graphFactors.resize(0);
      graphValues.clear();

      imuIntegratorImu_->resetIntegrationAndSetBias(prevBias_);// 重置IMU积分器并设置偏差
      imuIntegratorOpt_->resetIntegrationAndSetBias(prevBias_);

      key = 1;
      systemInitialized = true;// 标记系统已初始化
      return;
    }


    // 重置图以提高速度
    if (key == 100)
    {
      // 获取重置前的噪声模型
      gtsam::noiseModel::Gaussian::shared_ptr updatedPoseNoise = gtsam::noiseModel::Gaussian::Covariance(optimizer.marginalCovariance(X(key-1)));
      gtsam::noiseModel::Gaussian::shared_ptr updatedVelNoise= gtsam::noiseModel::Gaussian::Covariance(optimizer.marginalCovariance(V(key-1)));
      gtsam::noiseModel::Gaussian::shared_ptr updatedBiasNoise = gtsam::noiseModel::Gaussian::Covariance(optimizer.marginalCovariance(B(key-1)));
      // 重置图
      resetOptimization();
      // 添加位姿
      gtsam::PriorFactor<gtsam::Pose3> priorPose(X(0), prevPose_, updatedPoseNoise);
      graphFactors.add(priorPose);
      // 添加速度
      gtsam::PriorFactor<gtsam::Vector3> priorVel(V(0), prevVel_, updatedVelNoise);
      graphFactors.add(priorVel);
      // 添加偏差
      gtsam::PriorFactor<gtsam::imuBias::ConstantBias> priorBias(B(0), prevBias_, updatedBiasNoise);
      graphFactors.add(priorBias);
      // 添加值
      graphValues.insert(X(0), prevPose_);
      graphValues.insert(V(0), prevVel_);
      graphValues.insert(B(0), prevBias_);
      // 优化一次
      optimizer.update(graphFactors, graphValues);
      graphFactors.resize(0);
      graphValues.clear();

      key = 1;
    }


    // 1. 积分IMU数据并优化
    while (!imuQueOpt.empty())
    {
      // 弹出并积分两个优化之间的IMU数据
      sensor_msgs::Imu *thisImu = &imuQueOpt.front();
      double imuTime = ROS_TIME(thisImu);
      if (imuTime < currentCorrectionTime - delta_t)
      {
            double dt = (lastImuT_opt < 0) ? (1.0 / 500.0) : (imuTime - lastImuT_opt);
            imuIntegratorOpt_->integrateMeasurement(
                  gtsam::Vector3(thisImu->linear_acceleration.x, thisImu->linear_acceleration.y, thisImu->linear_acceleration.z),
                  gtsam::Vector3(thisImu->angular_velocity.x,    thisImu->angular_velocity.y,    thisImu->angular_velocity.z), dt);
            
            lastImuT_opt = imuTime;
            imuQueOpt.pop_front();
      }
      else
            break;
    }
    // 向图中添加IMU因子
    const gtsam::PreintegratedImuMeasurements& preint_imu = dynamic_cast<const gtsam::PreintegratedImuMeasurements&>(*imuIntegratorOpt_);
    gtsam::ImuFactor imu_factor(X(key - 1), V(key - 1), X(key), V(key), B(key - 1), preint_imu);
    graphFactors.add(imu_factor);
    // 添加IMU偏差之间的因子
    graphFactors.add(gtsam::BetweenFactor<gtsam::imuBias::ConstantBias>(B(key - 1), B(key), gtsam::imuBias::ConstantBias(),
                         gtsam::noiseModel::Diagonal::Sigmas(sqrt(imuIntegratorOpt_->deltaTij()) * noiseModelBetweenBias)));
    // 添加位姿因子
    gtsam::Pose3 curPose = lidarPose.compose(lidar2Imu);
    gtsam::PriorFactor<gtsam::Pose3> pose_factor(X(key), curPose, degenerate ? correctionNoise2 : correctionNoise);
    graphFactors.add(pose_factor);
    // 插入预测值
    gtsam::NavState propState_ = imuIntegratorOpt_->predict(prevState_, prevBias_);
    graphValues.insert(X(key), propState_.pose());
    graphValues.insert(V(key), propState_.v());
    graphValues.insert(B(key), prevBias_);
    // 优化
    optimizer.update(graphFactors, graphValues);
    optimizer.update();
    graphFactors.resize(0);
    graphValues.clear();
    // 为下一步重置预积分
    gtsam::Values result = optimizer.calculateEstimate();
    prevPose_= result.at<gtsam::Pose3>(X(key));
    prevVel_   = result.at<gtsam::Vector3>(V(key));
    prevState_ = gtsam::NavState(prevPose_, prevVel_);
    prevBias_= result.at<gtsam::imuBias::ConstantBias>(B(key));
    // 重置优化预积分对象
    imuIntegratorOpt_->resetIntegrationAndSetBias(prevBias_);
    // 检查优化是否失败
    if (failureDetection(prevVel_, prevBias_))
    {
      resetParams();
      return;
    }


    // 2. 优化后,重新传播IMU里程计预积分
    prevStateOdom = prevState_;
    prevBiasOdom= prevBias_;
      // 首先弹出比当前校正数据旧的IMU消息
      double lastImuQT = -1;
      while (!imuQueImu.empty() && ROS_TIME(&imuQueImu.front()) < currentCorrectionTime - delta_t)
      {
            lastImuQT = ROS_TIME(&imuQueImu.front());
            imuQueImu.pop_front();
      }
      // 重新传播
      if (!imuQueImu.empty())
      {
            // 使用新优化的偏差重置偏差
            imuIntegratorImu_->resetIntegrationAndSetBias(prevBiasOdom);
            // 从本次优化的开始处积分IMU消息
            for (int i = 0; i < (int)imuQueImu.size(); ++i)
            {
                sensor_msgs::Imu *thisImu = &imuQueImu;
                double imuTime = ROS_TIME(thisImu);
                double dt = (lastImuQT < 0) ? (1.0 / 500.0) : (imuTime - lastImuQT);

                imuIntegratorImu_->integrateMeasurement(gtsam::Vector3(thisImu->linear_acceleration.x, thisImu->linear_acceleration.y, thisImu->linear_acceleration.z),
                                                      gtsam::Vector3(thisImu->angular_velocity.x,    thisImu->angular_velocity.y,    thisImu->angular_velocity.z), dt);
                lastImuQT = imuTime;
            }
      }

      ++key;
      doneFirstOpt = true;
    }
1. 里程计与IMU的初始对齐
接收到的里程计位姿由以下参数表现:


[*]位置:                                                   p                               lidar                                    =                            [                                       p                               x                                    ,                                       p                               y                                    ,                                       p                               z                                                 ]                               T                                          \mathbf{p}_{\text{lidar}} = ^T                     plidar​=T,
[*]姿态:四元数                                                    q                               lidar                                    =                            [                                       r                               w                                    ,                                       r                               x                                    ,                                       r                               y                                    ,                                       r                               z                                                 ]                               T                                          \mathbf{q}_{\text{lidar}} = ^T                     qlidar​=T。
激光雷达的位姿用 GTSAM 表现为:
                                                    T                               lidar                                    =                                       [                                                                                                   R                                              lidar                                                                                                                            p                                              lidar                                                                                                                                  0                                                                                             1                                                                                 ]                                    ,                                  \mathbf{T}_{\text{lidar}} = \begin{bmatrix} \mathbf{R}_{\text{lidar}} & \mathbf{p}_{\text{lidar}} \\ \mathbf{0} & 1 \end{bmatrix},                     Tlidar​=,
此中                                              R                            lidar                                       \mathbf{R}_{\text{lidar}}                  Rlidar​ 由四元数                                              q                            lidar                                       \mathbf{q}_{\text{lidar}}                  qlidar​ 转换得到。
激光雷达位姿转换为IMU位姿:
                                                    T                               imu                                    =                                       T                               lidar                                    ⋅                                       T                               lidar2imu                                    ,                                  \mathbf{T}_{\text{imu}} = \mathbf{T}_{\text{lidar}} \cdot \mathbf{T}_{\text{lidar2imu}},                     Timu​=Tlidar​⋅Tlidar2imu​,
此中                                              T                            lidar2imu                                       \mathbf{T}_{\text{lidar2imu}}                  Tlidar2imu​ 为外参。
2. 系统初始化
初始位姿、速度和偏置,初始位姿                                              T                            0                                       \mathbf{T}_0                  T0​:
                                                    T                               0                                    =                                       T                               imu                                    .                                  \mathbf{T}_0 = \mathbf{T}_{\text{imu}}.                     T0​=Timu​.
初始速度                                              v                            0                                       \mathbf{v}_0                  v0​ 和偏置                                              b                            0                                       \mathbf{b}_0                  b0​ 设为零向量:
                                                    v                               0                                    =                            [                            0                            ,                            0                            ,                            0                                       ]                               T                                    ,                                                b                               0                                    =                                       [                                                                                                   b                                              a                                                                                                                                                b                                              ω                                                                                                ]                                    =                            0.                                  \mathbf{v}_0 = ^T, \quad \mathbf{b}_0 = \begin{bmatrix} \mathbf{b}_a \\ \mathbf{b}_\omega \end{bmatrix} = \mathbf{0}.                     v0​=T,b0​==0.
初始优化图: 利用先验因子初始化优化图:

[*]位姿先验因子:
                                              PriorFactor                               (                                           T                                  0                                          ,                                           T                                  prior                                          ,                                           Q                                  pose                                          )                               ,                                    \text{PriorFactor}(\mathbf{T}_0, \mathbf{T}_{\text{prior}}, \mathbf{Q}_{\text{pose}}),                        PriorFactor(T0​,Tprior​,Qpose​),
此中                                                    Q                               pose                                          \mathbf{Q}_{\text{pose}}                     Qpose​ 为位姿噪声协方差。
[*]速度先验因子:
                                              PriorFactor                               (                                           v                                  0                                          ,                                           v                                  prior                                          ,                                           Q                                  vel                                          )                               .                                    \text{PriorFactor}(\mathbf{v}_0, \mathbf{v}_{\text{prior}}, \mathbf{Q}_{\text{vel}}).                        PriorFactor(v0​,vprior​,Qvel​).
[*]偏置先验因子:
                                              PriorFactor                               (                                           b                                  0                                          ,                                           b                                  prior                                          ,                                           Q                                  bias                                          )                               .                                    \text{PriorFactor}(\mathbf{b}_0, \mathbf{b}_{\text{prior}}, \mathbf{Q}_{\text{bias}}).                        PriorFactor(b0​,bprior​,Qbias​).
       // 初始位姿
      prevPose_ = lidarPose.compose(lidar2Imu);// 将激光雷达位姿转换为IMU位姿
      gtsam::PriorFactor<gtsam::Pose3> priorPose(X(0), prevPose_, priorPoseNoise);// 添加初始位姿先验因子
      graphFactors.add(priorPose);
      // 初始速度
      prevVel_ = gtsam::Vector3(0, 0, 0);// 初始速度为零
      gtsam::PriorFactor<gtsam::Vector3> priorVel(V(0), prevVel_, priorVelNoise);// 添加初始速度先验因子
      graphFactors.add(priorVel);
      // 初始偏差
      prevBias_ = gtsam::imuBias::ConstantBias();// 初始偏差为零
      gtsam::PriorFactor<gtsam::imuBias::ConstantBias> priorBias(B(0), prevBias_, priorBiasNoise);// 添加初始偏差先验因子
      graphFactors.add(priorBias);
      // 添加初始值
      graphValues.insert(X(0), prevPose_);
      graphValues.insert(V(0), prevVel_);
      graphValues.insert(B(0), prevBias_);
3. IMU积分与因子添加
IMU预积分,将IMU丈量值                                              a                            imu                                  ,                                 ω                            imu                                       \mathbf{a}_{\text{imu}}, \boldsymbol{\omega}_{\text{imu}}                  aimu​,ωimu​ 进行预积分,得到状态更新:
                                                                                           v                                                       k                                           +                                           1                                                                                                                                     =                                                       v                                           k                                                      +                                        (                                                       R                                           k                                                      ⋅                                        (                                                       a                                           imu                                                      −                                                       b                                           a                                                      )                                        +                                        g                                        )                                        ⋅                                        Δ                                        t                                        ,                                                                                                                            p                                                       k                                           +                                           1                                                                                                                                     =                                                       p                                           k                                                      +                                                       v                                           k                                                      ⋅                                        Δ                                        t                                        +                                                       1                                           2                                                      (                                                       R                                           k                                                      ⋅                                        (                                                       a                                           imu                                                      −                                                       b                                           a                                                      )                                        +                                        g                                        )                                        ⋅                                        Δ                                                       t                                           2                                                      ,                                                                                                                            R                                                       k                                           +                                           1                                                                                                                                     =                                                       R                                           k                                                      ⋅                                        exp                                        ⁡                                        (                                        (                                                       ω                                           imu                                                      −                                                       b                                           ω                                                      )                                        ⋅                                        Δ                                        t                                        )                                        .                                                                              \begin{aligned} \mathbf{v}_{k+1} &= \mathbf{v}_k + (\mathbf{R}_k \cdot (\mathbf{a}_{\text{imu}} - \mathbf{b}_a) + \mathbf{g}) \cdot \Delta t, \\ \mathbf{p}_{k+1} &= \mathbf{p}_k + \mathbf{v}_k \cdot \Delta t + \frac{1}{2} (\mathbf{R}_k \cdot (\mathbf{a}_{\text{imu}} - \mathbf{b}_a) + \mathbf{g}) \cdot \Delta t^2, \\ \mathbf{R}_{k+1} &= \mathbf{R}_k \cdot \exp((\boldsymbol{\omega}_{\text{imu}} - \mathbf{b}_\omega) \cdot \Delta t). \end{aligned}                     vk+1​pk+1​Rk+1​​=vk​+(Rk​⋅(aimu​−ba​)+g)⋅Δt,=pk​+vk​⋅Δt+21​(Rk​⋅(aimu​−ba​)+g)⋅Δt2,=Rk​⋅exp((ωimu​−bω​)⋅Δt).​
基于预积分丈量值构建:
                                       ImuFactor                            (                                       T                               k                                    ,                                       v                               k                                    ,                                       T                                           k                                  +                                  1                                                 ,                                       v                                           k                                  +                                  1                                                 ,                                       b                               k                                    ,                            PreintegratedIMU                            )                            .                                  \text{ImuFactor}(\mathbf{T}_{k}, \mathbf{v}_k, \mathbf{T}_{k+1}, \mathbf{v}_{k+1}, \mathbf{b}_k, \text{PreintegratedIMU}).                     ImuFactor(Tk​,vk​,Tk+1​,vk+1​,bk​,PreintegratedIMU).
    const gtsam::PreintegratedImuMeasurements& preint_imu = dynamic_cast<const gtsam::PreintegratedImuMeasurements&>(*imuIntegratorOpt_);
    gtsam::ImuFactor imu_factor(X(key - 1), V(key - 1), X(key), V(key), B(key - 1), preint_imu);
    graphFactors.add(imu_factor);
    // 添加IMU偏差之间的因子
    graphFactors.add(gtsam::BetweenFactor<gtsam::imuBias::ConstantBias>(B(key - 1), B(key), gtsam::imuBias::ConstantBias(),
                         gtsam::noiseModel::Diagonal::Sigmas(sqrt(imuIntegratorOpt_->deltaTij()) * noiseModelBetweenBias)));
4. 里程计因子添加与优化
位姿因子,激光里程计位姿转换为IMU位姿后,构造先验因子:
                                       PriorFactor                            (                                       T                                           k                                  +                                  1                                                 ,                                       T                               cur                                    ,                                       Q                               pose                                    )                            ,                                  \text{PriorFactor}(\mathbf{T}_{k+1}, \mathbf{T}_{\text{cur}}, \mathbf{Q}_{\text{pose}}),                     PriorFactor(Tk+1​,Tcur​,Qpose​),
此中                                              T                            cur                                       \mathbf{T}_{\text{cur}}                  Tcur​ 为当前里程计位姿。
    // 添加位姿因子
    gtsam::Pose3 curPose = lidarPose.compose(lidar2Imu);
    gtsam::PriorFactor<gtsam::Pose3> pose_factor(X(key), curPose, degenerate ? correctionNoise2 : correctionNoise);
    graphFactors.add(pose_factor);
优化求解,构建优化问题:
                                                    x                               ∗                                    =                            arg                            ⁡                                                   min                                  ⁡                                          x                                    ∑                            Factors                            .                                  \mathbf{x}^* = \arg\min_{\mathbf{x}} \sum \text{Factors}.                     x∗=argxmin​∑Factors.
调用优化器 optimizer.update 进行求解。
    // 优化
    optimizer.update(graphFactors, graphValues);
    optimizer.update();
    graphFactors.resize(0);
    graphValues.clear();
5. 优化后更新状态
优化完成后,从效果中提取最新状态:
                                                                                           T                                                       k                                           +                                           1                                                                                                                                     =                                        result                                        (                                                       X                                                         k                                              +                                              1                                                                     )                                        ,                                                                                                                            v                                                       k                                           +                                           1                                                                                                                                     =                                        result                                        (                                                       V                                                         k                                              +                                              1                                                                     )                                        ,                                                                                                                            b                                                       k                                           +                                           1                                                                                                                                     =                                        result                                        (                                                       B                                                         k                                              +                                              1                                                                     )                                        .                                                                              \begin{aligned} \mathbf{T}_{k+1} &= \text{result}(X_{k+1}), \\ \mathbf{v}_{k+1} &= \text{result}(V_{k+1}), \\ \mathbf{b}_{k+1} &= \text{result}(B_{k+1}). \end{aligned}                     Tk+1​vk+1​bk+1​​=result(Xk+1​),=result(Vk+1​),=result(Bk+1​).​
并重置IMU预积分器:
                                       imuIntegratorOpt                            −                            >                            resetIntegrationAndSetBias                            (                                       b                                           k                                  +                                  1                                                 )                            .                                  \text{imuIntegratorOpt}->\text{resetIntegrationAndSetBias}(\mathbf{b}_{k+1}).                     imuIntegratorOpt−>resetIntegrationAndSetBias(bk+1​).
    // 为下一步重置预积分
    gtsam::Values result = optimizer.calculateEstimate();
    prevPose_= result.at<gtsam::Pose3>(X(key));
    prevVel_   = result.at<gtsam::Vector3>(V(key));
    prevState_ = gtsam::NavState(prevPose_, prevVel_);
    prevBias_= result.at<gtsam::imuBias::ConstantBias>(B(key));
    // 重置优化预积分对象
    imuIntegratorOpt_->resetIntegrationAndSetBias(prevBias_);
    // 检查优化是否失败
6.重新传播
在重新传播之前,需要移除时间戳早于当前校正时间                                              t                            currentCorrectionTime                                  −                         Δ                         t                              t_{\text{currentCorrectionTime}} - \Delta t                  tcurrentCorrectionTime​−Δt 的IMU消息:
                                                    t                               imu                                    <                                       t                               currentCorrectionTime                                    −                            Δ                            t                            .                                  t_{\text{imu}} < t_{\text{currentCorrectionTime}} - \Delta t.                     timu​<tcurrentCorrectionTime​−Δt.
通过循环移除队列中满足上述条件的IMU消息,并记录最后一条被移除的IMU时间戳                                              t                            lastImuQT                                       t_{\text{lastImuQT}}                  tlastImuQT​:
                                                    t                               lastImuQT                                    =                                       t                               imu                                    .                                  t_{\text{lastImuQT}} = t_{\text{imu}}.                     tlastImuQT​=timu​.
      // 首先弹出比当前校正数据旧的IMU消息
      double lastImuQT = -1;
      while (!imuQueImu.empty() && ROS_TIME(&imuQueImu.front()) < currentCorrectionTime - delta_t)
      {
            lastImuQT = ROS_TIME(&imuQueImu.front());
            imuQueImu.pop_front();
      }
重新传播IMU
在IMU重新传播前,利用最新优化得到的偏置                                              b                            odom                                       \mathbf{b}_{\text{odom}}                  bodom​ 对IMU积分器重置:
// 使用新优化的偏差重置偏差
imuIntegratorImu_->resetIntegrationAndSetBias(prevBiasOdom);
对于队列中剩余的IMU消息,从                                              t                            lastImuQT                                       t_{\text{lastImuQT}}                  tlastImuQT​ 开始,逐条进行积分:
                                                                                           v                                                       k                                           +                                           1                                                                                                                                     =                                                       v                                           k                                                      +                                        (                                                       R                                           k                                                      ⋅                                        (                                                       a                                           imu                                                      −                                                       b                                           a                                                      )                                        +                                        g                                        )                                        ⋅                                        Δ                                        t                                        ,                                                                                                                            p                                                       k                                           +                                           1                                                                                                                                     =                                                       p                                           k                                                      +                                                       v                                           k                                                      ⋅                                        Δ                                        t                                        +                                                       1                                           2                                                      (                                                       R                                           k                                                      ⋅                                        (                                                       a                                           imu                                                      −                                                       b                                           a                                                      )                                        +                                        g                                        )                                        ⋅                                        Δ                                                       t                                           2                                                      ,                                                                                                                            R                                                       k                                           +                                           1                                                                                                                                     =                                                       R                                           k                                                      ⋅                                        exp                                        ⁡                                        (                                        (                                                       ω                                           imu                                                      −                                                       b                                           ω                                                      )                                        ⋅                                        Δ                                        t                                        )                                        .                                                                              \begin{aligned} \mathbf{v}_{k+1} &= \mathbf{v}_k + (\mathbf{R}_k \cdot (\mathbf{a}_{\text{imu}} - \mathbf{b}_a) + \mathbf{g}) \cdot \Delta t, \\ \mathbf{p}_{k+1} &= \mathbf{p}_k + \mathbf{v}_k \cdot \Delta t + \frac{1}{2} (\mathbf{R}_k \cdot (\mathbf{a}_{\text{imu}} - \mathbf{b}_a) + \mathbf{g}) \cdot \Delta t^2, \\ \mathbf{R}_{k+1} &= \mathbf{R}_k \cdot \exp((\boldsymbol{\omega}_{\text{imu}} - \mathbf{b}_\omega) \cdot \Delta t). \end{aligned}                     vk+1​pk+1​Rk+1​​=vk​+(Rk​⋅(aimu​−ba​)+g)⋅Δt,=pk​+vk​⋅Δt+21​(Rk​⋅(aimu​−ba​)+g)⋅Δt2,=Rk​⋅exp((ωimu​−bω​)⋅Δt).​
此中:


[*]                                                   v                               k                                          \mathbf{v}_k                     vk​ 和                                                    p                               k                                          \mathbf{p}_k                     pk​ 分别为速度和位置;
[*]                                                   R                               k                                          \mathbf{R}_k                     Rk​ 为姿态旋转矩阵;
[*]                                                   a                               imu                                          \mathbf{a}_{\text{imu}}                     aimu​ 和                                                    ω                               imu                                          \boldsymbol{\omega}_{\text{imu}}                     ωimu​ 分别为IMU的线加速度和角速度;
[*]                                                   b                               a                                          \mathbf{b}_a                     ba​ 和                                                    b                               ω                                          \mathbf{b}_\omega                     bω​ 分别为加速度和角速度的偏置;
[*]                                        Δ                            t                                  \Delta t                     Δt 为时间隔断:
                                              Δ                               t                               =                                           {                                                                                                                               1                                                    500                                                                  ,                                                                                                                                     若                                                                    t                                                    lastImuQT                                                                  <                                                 0                                                 ;                                                                                                                                                                               t                                                    imu                                                                  −                                                                   t                                                    lastImuQT                                                                  ,                                                                                                                                     否则                                                 .                                                                                                                     \Delta t = \begin{cases} \frac{1}{500}, & \text{若 } t_{\text{lastImuQT}} < 0; \\ t_{\text{imu}} - t_{\text{lastImuQT}}, & \text{否则}. \end{cases}                        Δt={5001​,timu​−tlastImuQT​,​若 tlastImuQT​<0;否则.​
// 从本次优化的开始处积分IMU消息
            for (int i = 0; i < (int)imuQueImu.size(); ++i)
            {
                sensor_msgs::Imu *thisImu = &imuQueImu;
                double imuTime = ROS_TIME(thisImu);
                double dt = (lastImuQT < 0) ? (1.0 / 500.0) : (imuTime - lastImuQT);

                imuIntegratorImu_->integrateMeasurement(gtsam::Vector3(thisImu->linear_acceleration.x, thisImu->linear_acceleration.y, thisImu->linear_acceleration.z),
                                                      gtsam::Vector3(thisImu->angular_velocity.x,    thisImu->angular_velocity.y,    thisImu->angular_velocity.z), dt);
                lastImuQT = imuTime;
            }

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: LIO-SAM代码解析:imuPreintegration.cpp(一)