在vins初始化中的陀螺仪偏置标定原理与代码部分

对于窗口中连续两帧图像 b k b_{k} bk b k + 1 b_{k+1} bk+1,之前已经通过视觉 sfm 得到了两帧相对于滑窗第一帧的旋转 q c 0 b k 和 q c 0 b k + 1 \mathbf{q}_{c_{0} b_{k}}和\mathbf{q}_{c_{0} b_{k+1}} qc0bkqc0bk+1,此时之前通过 IMU 预积分得到这两帧旋转的预积分 γ ^ b k b k + 1 \hat{\gamma}_{b_k b_{k+1}} γ^bkbk+1(先前不带 bias 的预积分)。

此时,我们可以建立约束方程,最小化代价函数,如下:

a r g m i n δ b g ∑ k i n B ∣ 2 ⌊ q c 0 b k + 1 − 1 ⨂ q c 0 b k ⨂ γ b k b k + 1 ⌋ x y z ∣ 2 argmin_{\delta \mathbf{b}^{g}} \sum_{k in B} \left|2 \left \lfloor \mathbf{q}_{c_{0} b_{k+1}}^{-1} \bigotimes \mathbf{q}_{c_{0} b_{k}} \bigotimes {\gamma}_{b_k b_{k+1}}\right \rfloor_{x y z} \right|^{2} argminδbgkinB2qc0bk+11qc0bkγbkbk+1xyz2
其中 γ b k b k + 1 {\gamma}_{b_k b_{k+1}} γbkbk+1表示的是算上陀螺仪 bias 的预积分值。
γ b k b k + 1 ≈ γ ^ b k b k + 1 ⨂ [ 1 1 2 J b g γ δ b g ] \gamma_{b_k b_{k+1}} \approx \hat{\gamma}_{b_k b_{k+1}} \bigotimes \left[\begin{array}{c}{1} \\ {\frac{1}{2} J_{b_{g}}^{\gamma} \delta b_{g}}\end{array}\right] γbkbk+1γ^bkbk+1[121Jbgγδbg]
具体方法
在上述问题的求解时,最理想的情况如下(其中等式右边的四元数代表的是旋转不变的四元数):

q c 0 b k + 1 − 1 ⨂ q c 0 b k ⨂ γ b k b k + 1 = [ 1 0 0 0 ] \mathbf{q}_{c_{0} b_{k+1}}^{-1} \bigotimes \mathbf{q}_{c_{0} b_{k}} \bigotimes {\gamma}_{b_k b_{k+1}} = \left[\begin{array}{l}{1} \\ {0}\\ {0}\\ {0}\end{array}\right] qc0bk+11qc0bkγbkbk+1=1000
对上式进行变换可以得到

γ b k b k + 1 = q c 0 b k − 1 ⨂ q c 0 b k + 1 ⨂ [ 1 0 0 0 ] {\gamma}_{b_k b_{k+1}} = \mathbf{q}_{c_{0} b_{k}}^{-1} \bigotimes \mathbf{q}_{c_{0} b_{k+1}} \bigotimes \left[\begin{array}{l}{1} \\ {0}\\ {0}\\ {0}\end{array}\right] γbkbk+1=qc0bk1qc0bk+11000
δ b g \delta b_{g} δbg带入上式可以得到

γ ^ b k b k + 1 ⨂ [ 1 1 2 J b g γ δ b g ] = q c 0 b k − 1 ⨂ q c 0 b k + 1 ⨂ [ 1 0 ] \hat{\gamma}_{b_k b_{k+1}} \bigotimes\left[\begin{array}{c}{1} \\ {\frac{1}{2} J_{b_{g}}^{\gamma} \delta b_{g}}\end{array}\right] = \mathbf{q}_{c_{0} b_{k}}^{-1} \bigotimes \mathbf{q}_{c_{0} b_{k+1}} \bigotimes \left[\begin{array}{l}{1} \\ {0}\end{array}\right] γ^bkbk+1[121Jbgγδbg]=qc0bk1qc0bk+1[10]
只考虑上式虚部,我们可以得到 (其中 v e c vec vec 代表取虚部)

J b g γ δ b g = 2 ( γ ^ b k b k + 1 − 1 ⨂ q c 0 b k − 1 ⨂ q c 0 b k + 1 ) v e c J_{b_{g}}^{\gamma} \delta b_{g}=2\left({\hat{\gamma}_{b_k b_{k+1}}}^{-1} \bigotimes \mathbf{q}_{c_{0} b_{k}}^{-1} \bigotimes \mathbf{q}_{c_{0} b_{k+1}}\right)_{v e c} Jbgγδbg=2(γ^bkbk+11qc0bk1qc0bk+1)vec
对于上式,我们想要做的是求解出 δ b g \delta b_{g} δbg的大小,此时我们可以使用如下办法:

等式两侧同时乘以 J b g γ T J_{b_{g}}^{\gamma T} JbgγT(在使用 cholesky 分解求解矩阵,获取使目标函数达到最小的解时,需要将系数矩阵变为正定),即得到
J b g γ T J b g γ δ b g = 2 J b g γ T ( γ ^ b k b k + 1 − 1 ⨂ q c 0 b k − 1 ⨂ q c 0 b k + 1 ) v e c J_{b_{g}}^{\gamma T} J_{b_{g}}^{\gamma} \delta b_{g}=2 J_{b_{g}}^{\gamma T} \left({\hat{\gamma}_{b_k b_{k+1}}}^{-1} \bigotimes \mathbf{q}_{c_{0} b_{k}}^{-1} \bigotimes \mathbf{q}_{c_{0} b_{k+1}}\right)_{v e c} JbgγTJbgγδbg=2JbgγT(γ^bkbk+11qc0bk1qc0bk+1)vec
使用 LDLT 分解即可求得 δ b g \delta b_{g} δbg注意这个地方得到的只是 Bias 的变化量,需要在滑窗内累加得到Bias 的准确值。


/**
 * @brief   陀螺仪偏置校正
 * @optional    根据视觉SFM的结果来校正陀螺仪Bias -> Paper V-B-1
 *              主要是将相邻帧之间SFM求解出来的旋转矩阵与IMU预积分的旋转量对齐
 *              注意得到了新的Bias后对应的预积分需要repropagate
 * @param[in]   all_image_frame所有图像帧构成的map,图像帧保存了位姿、预积分量和关于角点的信息
 * @param[out]  Bgs 陀螺仪偏置
 * @return      void
*/
void solveGyroscopeBias(map<double, ImageFrame> &all_image_frame, Vector3d* Bgs)
{
    Matrix3d A;
    Vector3d b;
    Vector3d delta_bg;
    A.setZero();
    b.setZero();
    map<double, ImageFrame>::iterator frame_i;
    map<double, ImageFrame>::iterator frame_j;
    //遍历所有图像帧
    for (frame_i = all_image_frame.begin(); next(frame_i) != all_image_frame.end(); frame_i++)
    {
        //下一帧
        frame_j = next(frame_i);
        MatrixXd tmp_A(3, 3);
        tmp_A.setZero();
        VectorXd tmp_b(3);
        tmp_b.setZero();

        //两帧之间的旋转变换 
        //R_ij = (R^c0_bk)^-1 * (R^c0_bk+1) 转换为四元数 q_ij = (q^c0_bk)^-1 * (q^c0_bk+1)
        Eigen::Quaterniond q_ij(frame_i->second.R.transpose() * frame_j->second.R);
        //tmp_A = J_j_bw 雅可比 ,之前的预积分是没有算上陀螺仪bias的
        tmp_A = frame_j->second.pre_integration->jacobian.template block<3, 3>(O_R, O_BG);
        //tmp_b = 2 * (r^bk_bk+1)^-1 * (q^c0_bk)^-1 * (q^c0_bk+1)
        //      = 2 * (r^bk_bk+1)^-1 * q_ij
        tmp_b = 2 * (frame_j->second.pre_integration->delta_q.inverse() * q_ij).vec();
        //tmp_A * delta_bg = tmp_b
        A += tmp_A.transpose() * tmp_A;
        b += tmp_A.transpose() * tmp_b;

    }
    //LDLT方法
    delta_bg = A.ldlt().solve(b);
    ROS_WARN_STREAM("gyroscope bias initial calibration " << delta_bg.transpose());

    //假设窗口中bgs值都相同
    for (int i = 0; i <= WINDOW_SIZE; i++)
        Bgs[i] += delta_bg;

    //标定成功bias后需要重新进行预积分
    for (frame_i = all_image_frame.begin(); next(frame_i) != all_image_frame.end( ); frame_i++)
    {
        frame_j = next(frame_i);
        frame_j->second.pre_integration->repropagate(Vector3d::Zero(), Bgs[0]);
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值