VINS中旋转外参初始化

VINS 中的旋转外参初始化

​ 为了使这个两个传感器融合,我们首先需要做的事情是将两个传感器的数据对齐,除了时间上的对齐,还有空间上的对齐。空间上的对齐通俗的讲就是将一个传感器获取的数据统一到另一个传感器的坐标系中,其关键在于确定这两个传感器之前的外参,本文将详细介绍 VINS_Monocamera-imu 的旋转外参标定算法原理并对其代码进行解读。

​ 相机与 IMU 之间的相对旋转如下图所示:

在这里插入图片描述

​ 上图表示相机和 IMU 集成的系统从到的运动,其中视觉可以通过特征匹配求得到时刻的旋转增量,同时 IMU 也可以通过积分得到到时刻的旋转增量。两个求得的旋转增量应当是相同的,因此分别将在自己坐标系下求得的增量转移到对方的坐标系下,即经过 q b c \mathbf{q}_{bc} qbc 变换后应当还是相同的。

​ 相邻两时刻 k k k , k + 1 k + 1 k+1 之间有: IMU 旋转积分 q b k b k + 1 \mathbf{q}_{b_{k} b_{k+1}} qbkbk+1 ,视觉测量 q c k c k + 1 \mathbf{q}_{c_{k} c_{k+1}} qckck+1。则有:
q b k b k + 1 ⊗ q b c = q b c ⊗ q c k c k + 1 \mathbf{q}_{b_{k} b_{k+1}} \otimes \mathbf{q}_{b c}=\mathbf{q}_{b c} \otimes \mathbf{q}_{c_{k} c_{k+1}} qbkbk+1qbc=qbcqckck+1
​ 上面的式子可以写成:
( [ q b k b k + 1 ] L − [ q c k c k + 1 ] R ) q b c = Q k + 1 k ⋅ q b c = 0 \left(\left[\mathbf{q}_{b_{k} b_{k+1}}\right]_{L}-\left[\mathbf{q}_{c_{k} c_{k+1}}\right]_{R}\right) \mathbf{q}_{b c}=\mathbf{Q}_{k+1}^{k} \cdot \mathbf{q}_{b c}=\mathbf{0} ([qbkbk+1]L[qckck+1]R)qbc=Qk+1kqbc=0
​ 其中 [     ˙ ] L , [     ˙ ] R \left[ \dot{\ \ \ } \right]_L, \left[ \dot{\ \ \ } \right]_R [   ˙]L,[   ˙]R 表示 left and right quaternion multiplication

​ 将多个时刻线性方程累计起来,并加上鲁棒核权重得到:
[ w 1 0 ⋅ Q 1 0 w 2 1 ⋅ Q 2 1 ⋮ w N N − 1 ⋅ Q N N − 1 ] q b c = Q N ⋅ q b c = 0 w k + 1 k = { 1 , r k + 1 k <  threshold   threshold  r k + 1 k ,  otherwise  \begin{array}{c} {\left[\begin{array}{c} w_{1}^{0} \cdot \mathbf{Q}_{1}^{0} \\ w_{2}^{1} \cdot \mathbf{Q}_{2}^{1} \\ \vdots \\ w_{N}^{N-1} \cdot \mathbf{Q}_{N}^{N-1} \end{array}\right] \mathbf{q}_{b c}=\mathbf{Q}_{N} \cdot \mathbf{q}_{b c}=\mathbf{0}} \\ w_{k+1}^{k}=\left\{\begin{array}{ll} 1, & r_{k+1}^{k}<\text { threshold } \\ \frac{\text { threshold }}{r_{k+1}^{k}}, & \text { otherwise } \end{array}\right. \end{array} w10Q10w21Q21wNN1QNN1 qbc=QNqbc=0wk+1k={1,rk+1k threshold ,rk+1k< threshold  otherwise 
该线性方程为超定方程,有最小二乘解。采用 SVD 进行求解。

  • 代码
bool InitialEXRotation::CalibrationExRotation(vector<pair<Vector3d, Vector3d>> corres, Quaterniond delta_q_imu, Matrix3d &calib_ric_result)
{
    frame_count++;
    Rc.push_back(solveRelativeR(corres));                               // 对极几何计算出的 R,t 约束
    Rimu.push_back(delta_q_imu.toRotationMatrix());     // IMU 预积分的得到的 R,t 约束
    Rc_g.push_back(ric.inverse() * delta_q_imu * ric);       // 将imu预积分转换到相机坐标系

    Eigen::MatrixXd A(frame_count * 4, 4);
    A.setZero();
    int sum_ok = 0;
    for (int i = 1; i <= frame_count; i++)
    {
        Quaterniond r1(Rc[i]);
        Quaterniond r2(Rc_g[i]);

        // A.angularDistance(B):是求两个旋转之间的角度差,用弧度表示
        double angular_distance = 180 / M_PI * r1.angularDistance(r2);
        ROS_DEBUG(
            "%d %f", i, angular_distance);

        double huber = angular_distance > 5.0 ? 5.0 / angular_distance : 1.0; // huber 核函数作加权
        ++sum_ok;
        // L R 分别为左乘和右乘矩阵
        Matrix4d L, R;

        double w = Quaterniond(Rc[i]).w();
        Vector3d q = Quaterniond(Rc[i]).vec();
        L.block<3, 3>(0, 0) = w * Matrix3d::Identity() + Utility::skewSymmetric(q);
        L.block<3, 1>(0, 3) = q;
        L.block<1, 3>(3, 0) = -q.transpose();
        L(3, 3) = w;

        Quaterniond R_ij(Rimu[i]);
        w = R_ij.w();
        q = R_ij.vec();
        R.block<3, 3>(0, 0) = w * Matrix3d::Identity() - Utility::skewSymmetric(q);
        R.block<3, 1>(0, 3) = q;
        R.block<1, 3>(3, 0) = -q.transpose();
        R(3, 3) = w;

        A.block<4, 4>((i - 1) * 4, 0) = huber * (L - R);
    }

    // svd 分解中最小奇异值对应的右奇异向量作为旋转四元数
    JacobiSVD<MatrixXd> svd(A, ComputeFullU | ComputeFullV);
    Matrix<double, 4, 1> x = svd.matrixV().col(3);
    Quaterniond estimated_R(x);
    // 所求的 x 是q^b_c,在最后需要转换成旋转矩阵并求逆。
    ric = estimated_R.toRotationMatrix().inverse();
    //cout << svd.singularValues().transpose() << endl;
    //cout << ric << endl;
    Vector3d ric_cov;
    ric_cov = svd.singularValues().tail<3>();
    // 至少迭代计算了WINDOW_SIZE次,且R的奇异值大于0.25才认为标定成功
    if (frame_count >= WINDOW_SIZE && ric_cov(1) > 0.25)
    {
        calib_ric_result = ric;
        return true;
    }
    else
        return false;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值