IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> VINS 外参在线标定 -> 正文阅读

[人工智能]VINS 外参在线标定

在VINS中相机的外参 R i c R_{ic} Ric?是可以在线动态标定的,实现函数为:

/**
 * @brief 外参在线标定
 * 
 * @param corres 两帧图像之间的共视特征点
 * @param delta_q_imu 两帧图像之间的IMU预积分量
 * @param calib_ric_result 标定结果存放
 * @return true 
 * @return false 
 */
bool InitialEXRotation::CalibrationExRotation(vector<pair<Vector3d, Vector3d>> corres, Quaterniond delta_q_imu, Matrix3d &calib_ric_result)

基本原理

R c b R b k b k + 1 R c b T = R c k c k + 1 ? R c b R b k b k + 1 = R c k c k + 1 R c b ? q c b ? q b k b k + 1 = q c k c k + 1 ? q c b ? [ q b k b k + 1 ] R q c b = [ q c k c k + 1 ] L q c b ? { [ q c k c k + 1 ] L ? [ q b k b k + 1 ] R } q c b = 0 \begin{aligned} &R_{c b} R_{b_{k} b_{k+1}} R_{c b}^{T}=R_{c_{k} c_{k+1}} \\ &\Rightarrow R_{c b} R_{b_{k} b_{k+1}}=R_{c_{k} c_{k+1}} R_{c b} \\ &\Rightarrow q_{c b} \otimes q_{b_{k} b_{k+1}}=q_{c_{k} c_{k+1}} \otimes q_{c b} \\ &\Rightarrow\left[q_{b_{k} b_{k+1}}\right]_{R} q_{c b}=\left[q_{c_{k} c_{k+1}}\right]_{L} q_{c b} \\ &\Rightarrow\left\{\left[q_{c_{k} c_{k+1}}\right]_{L}-\left[q_{b_{k} b_{k+1}}\right]_{R}\right\} q_{c b}=0 \end{aligned} ?Rcb?Rbk?bk+1??RcbT?=Rck?ck+1???Rcb?Rbk?bk+1??=Rck?ck+1??Rcb??qcb??qbk?bk+1??=qck?ck+1???qcb??[qbk?bk+1??]R?qcb?=[qck?ck+1??]L?qcb??{[qck?ck+1??]L??[qbk?bk+1??]R?}qcb?=0?

其中涉及到四元数的左乘和右乘矩阵:
q = [ x y z w ] T = [ q v q w ] , [ q ] L = q w I + [ [ q v ] × q v ? q v T 0 ] , [ q ] R = q w I + [ ? [ q v ] × q v ? q v T 0 ] q=[x y z w]^{T}=\left[\begin{array}{c} q_{v} \\ q_{w} \end{array}\right], \quad[q]_{L}=q_{w} I+\left[\begin{array}{cc} {\left[q_{v}\right]_{\times}} & q_{v} \\ -q_{v}^{T} & 0 \end{array}\right], \quad[q]_{R}=q_{w} I+\left[\begin{array}{cc} -\left[q_{v}\right]_{\times} & q_{v} \\ -q_{v}^{T} & 0 \end{array}\right] q=[xyzw]T=[qv?qw??],[q]L?=qw?I+[[qv?]×??qvT??qv?0?],[q]R?=qw?I+[?[qv?]×??qvT??qv?0?]

当有多对这样的组合后就可以构建超定方程即公式
A = { [ q c k c k + 1 1 ] L ? [ q b k b k + 1 1 ] R [ q c k c k + 1 2 ] L ? [ q b k b k + 1 2 ] R ? [ q c k c k + 1 n ] L ? [ q b k b k + 1 n ] R } , A ? q c b = 0 A=\left\{\begin{array}{c} {\left[q_{c_{k} c_{k+1}}^{1}\right]_{L}-\left[q_{b_{k} b_{k+1}}^{1}\right]_{R}} \\ {\left[q_{c_{k} c_{k+1}}^{2}\right]_{L}-\left[q_{b_{k} b_{k+1}}^{2}\right]_{R}} \\ \cdots \\ {\left[q_{c_{k} c_{k+1}}^{n}\right]_{L}-\left[q_{b_{k} b_{k+1}}^{n}\right]_{R}} \end{array}\right\}, \quad A \cdot q_{c b}=0 A=??????????????[qck?ck+1?1?]L??[qbk?bk+1?1?]R?[qck?ck+1?2?]L??[qbk?bk+1?2?]R??[qck?ck+1?n?]L??[qbk?bk+1?n?]R????????????????,A?qcb?=0

通过SVD分解就可以得到 q c b q_{cb} qcb?,然后再取逆即可得到外参 q b c = i n v ( q c b ) q_{b c}=i n v\left(q_{c b}\right) qbc?=inv(qcb?)

代码实现

bool InitialEXRotation::CalibrationExRotation(vector<pair<Vector3d, Vector3d>> corres, Quaterniond delta_q_imu, Matrix3d &calib_ric_result)
{
    this->frame_count++; // 记录进入该函数的次数,用于定义A矩阵的规模的

    Rc.push_back(solveRelativeR(corres));// 求取帧间变换阵R,(第k+1帧变换到第k帧的)R_c(k+1)^ck

    Rimu.push_back(delta_q_imu.toRotationMatrix()); // 两帧之间的陀螺仪预积分值中的旋转变化量 R

    Rc_g.push_back(ric.inverse() * delta_q_imu * ric);  // 图像k帧到k+1帧的旋转

    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]);
        // 两个线性变换转过的角度
        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;
        ++sum_ok;
        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);
    // 这里得到的是R_ci,取逆可得 R_ic
    ric = estimated_R.toRotationMatrix().inverse();
    Vector3d ric_cov;
    ric_cov = svd.singularValues().tail<3>();

    // 用0.25来限定倒数第二小的奇异值,如果全部奇异值都非常小接近0,则说明相机没有进行充分的旋转,无法进行初始化
    // 至少会迭代windowSize次
    if (frame_count >= windowSize && ric_cov(1) > 0.25)
    {
        calib_ric_result = ric;
        return true;
    }
    else
        return false;
}
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:39:40  更:2022-05-09 12:40:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:20:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码