Vins-Fusion初始化位姿——3D-2D:PNP求解当前帧位姿

2023-05-16

继上一篇博文Vins-Fusion 外参camera-imu 标定,本文继续介绍Vins-Fusion初始化时,通过PNP求解当前帧位姿。

一、3D-2D:PNP

PnP是求解3D到2D点对运动的估计,描述的是知道n个3D空间的点及其投影位置,如何估计相机的位姿。因为其无需对极约束,故更少匹配点可获得较好的运动估计。特征点的3D位置可直接由三角化或者深度图确定,双目相机无需进行特定的初始化(如单目初始化时需使相机产生一定平移)。
PnP求解常用方法有,直接线性变换(DLT)和非线性优化方法。

1.优化迭代方法

2.P3P:可以使用任意4个特征点求解,不要求共面,特征点数量不为4时报错

参考论文《complete solution classification for perspective-n-point problem》

3.EPNP:只要特征点数量大于3就可求出正解

参考论文《EPnP: Efficient Perspective-n-Point Camera Pose Estimation》

源码中直接调用的cv solvePnP求解。

二、当前帧位姿3D-2D:PNP 求解流程

1.准备路标点位姿(3d坐标)及其在相机归一化平面的投影点

源码中对第一帧未作处理,因为此时路标点还未完成三角化,即无3d位置。
在关键帧中选择深度为正的关键帧,同时特征点从start_frame到当前帧frameCnt都能一直被观测到(一直被跟踪到)时,计算第一帧中特征点在世界坐标系下的位姿(先根据特征点在相机归一化平面的位置,通过外参camera-imu旋转到imu坐标系,再通过旋转矩阵Riw,得到世界坐标系下的位姿)。

vector<cv::Point2f> pts2D;
vector<cv::Point3f> pts3D;
// 遍历当前帧特征点
for (auto &it_per_id : feature)
{
	if (it_per_id.estimated_depth > 0)
	{
		int index = frameCnt - it_per_id.start_frame;
		// 特征点从start_frame图像帧到frameCnt对应的图像帧都能被观测到(一直被跟踪到了)
		if((int)it_per_id.feature_per_frame.size() >= index + 1)
		{
			// 在第一帧IMU下的坐标
			Vector3d ptsInCam = ric[0] * (it_per_id.feature_per_frame[0].point * it_per_id.estimated_depth) + tic[0];
			// 通过第一帧的位姿转到世界系 Twi
			Vector3d ptsInWorld = Rs[it_per_id.start_frame] * ptsInCam + Ps[it_per_id.start_frame];

			cv::Point3f point3d(ptsInWorld.x(), ptsInWorld.y(), ptsInWorld.z());
			cv::Point2f point2d(it_per_id.feature_per_frame[index].point.x(), it_per_id.feature_per_frame[index].point.y());
			// 世界坐标
			pts3D.push_back(point3d);
			// 像素坐标
			pts2D.push_back(point2d); 
		}
	}
}

2.根据第一帧求解到的在世界坐标系的位姿为当前帧PnP求解的世界坐标系位姿初始值,求解solvePoseByPnP(RCam, PCam, pts2D, pts3D)。

Eigen::Matrix3d RCam;
Eigen::Vector3d PCam;
// trans to w_T_cam以上一帧图像在世界坐标系下的pose作为当前帧PnP求解的初值
// 前一帧位姿 Twc = Twi * Tic
RCam = Rs[frameCnt - 1] * ric[0];
PCam = Rs[frameCnt - 1] * tic[0] + Ps[frameCnt - 1];

// 3d-2d求解当前帧位姿,Twc
if(solvePoseByPnP(RCam, PCam, pts2D, pts3D))
{
	// trans to w_T_imu
	// 转换到IMU系下
	Rs[frameCnt] = RCam * ric[0].transpose(); 
	Ps[frameCnt] = -RCam * ric[0].transpose() * tic[0] + PCam;

	Eigen::Quaterniond Q(Rs[frameCnt]);
}

3.solvePoseByPnP

这一部分调用的是cv solvePnP进行求解的,所以很简单。结合源码说下几个需要注意,容易产生疑惑的地方。

bool FeatureManager::solvePoseByPnP(Eigen::Matrix3d &R, Eigen::Vector3d &P, 
                                      vector<cv::Point2f> &pts2D, vector<cv::Point3f> &pts3D)
{
    Eigen::Matrix3d R_initial;
    Eigen::Vector3d P_initial;

    // w_T_cam ---> cam_T_w 
    R_initial = R.inverse();
    P_initial = -(R_initial * P);

    //printf("pnp size %d \n",(int)pts2D.size() );
    // 特征点太少
    if (int(pts2D.size()) < 4)
    {
        printf("feature tracking not enough, please slowly move you device! \n");
        return false;
    }
    cv::Mat r, rvec, t, D, tmp_r;
    cv::eigen2cv(R_initial, tmp_r);
    cv::Rodrigues(tmp_r, rvec);
    cv::eigen2cv(P_initial, t);
    cv::Mat K = (cv::Mat_<double>(3, 3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);  
    bool pnp_succ;
    // 3d-2d Pnp 求解位姿
    pnp_succ = cv::solvePnP(pts3D, pts2D, K, D, rvec, t, 1);
    //pnp_succ = solvePnPRansac(pts3D, pts2D, K, D, rvec, t, true, 100, 8.0 / focalLength, 0.99, inliers);

    if(!pnp_succ)
    {
        printf("pnp failed ! \n");
        return false;
    }
    cv::Rodrigues(rvec, r);
    //cout << "r " << endl << r << endl;
    Eigen::MatrixXd R_pnp;
    cv::cv2eigen(r, R_pnp);
    Eigen::MatrixXd T_pnp;
    cv::cv2eigen(t, T_pnp);

    // cam_T_w ---> w_T_cam
    R = R_pnp.transpose();
    P = R * (-T_pnp);

    return true;
}
解释cv::solvePnP
void solvePnP(InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess=false, int flags = CV_ITERATIVE)
Parameters:
objectPoints - 世界坐标系下的控制点的坐标,vector的数据类型在这里可以使用
imagePoints - 在图像坐标系下对应的控制点的坐标。vector在这里可以使用
cameraMatrix - 相机的内参矩阵
distCoeffs - 相机的畸变系数
以上两个参数通过相机标定可以得到。
rvec - 输出的旋转向量。使坐标点从世界坐标系旋转到相机坐标系
tvec - 输出的平移向量。使坐标点从世界坐标系平移到相机坐标系
flags - 
1 SOLVEPNP_ITERATIVE:只能用四个共面的点来求解。使用列文伯格马夸尔特法迭代求解。(默认)
2 SOLVEPNP_P3P:可以使用任意4个特征点求解,不要求共面,特征点数量不为4时报错。
3 SOLVEPNP_EPNP:只要特征点数量大于3就可求出正解。

程序开始相当于求解solvePnP计算的位姿rvec、tvec的初值(cv::solvePnP输出的旋转矩阵为world-cam),因为使用列文伯格马夸尔特法迭代求解,故需提供初值,或者说提供准确的初值更有利于提高收敛速度。
solvePnP求解得到位姿rvec、tvec后,再将其转成cam-world,最终得到当前帧的位姿Rs[frameCnt],Ps[frameCnt]。
这里只是绕了一下,理解清楚就很简单了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vins-Fusion初始化位姿——3D-2D:PNP求解当前帧位姿 的相关文章

  • FreeRTOS系列|任务基础知识

    任务基础知识 1 多任务系统 1 1 前后台系统 单片机裸机开发时 xff0c 一般都是在main函数里面用while 1 做一个大循环来完成所有的处理 xff0c 循环中调用相应的函数完成所需的处理 有时也需要在中断中完成一些处理 相对于
  • 链表《5》使用链表实现学生成绩管理系统

    上次我使用动态数组结构体实现了学生成绩管理系统 xff1a http blog csdn net u010105970 article details 17752193 这次学习了链表对链表也有所了解 xff0c 我就想着用链表实现学生成绩
  • 得到一个数字中每一位的数字

    学习编程也有一段时间了 xff0c 随着学习的不断深入 xff0c 我越来越体会到了算法的重要性 xff0c 最近遇到了一些非常有意思的算法 xff0c 比如打印水仙花数 将数字逆置 xff0c 在这两个算法中会用到一个数字钟每一位的值 如
  • 使用C++实现学生管理系统

    我在前面的博客中分别使用C语言的动态数组和链表实现了学生成绩管理系统 xff0c 最近正好在学习C 43 43 xff0c 于是我便使用C 43 43 实现了学生成绩管理系统 xff0c 算法和前面的C语言的动态数组实现的学生成绩管理系统差
  • 制作一个简单的Android版的音乐播放器

    音乐播放器是一个非常常见的应用 xff0c 这篇博客就是介绍如何制作一个简单的音乐播放器 xff0c 这款音乐播放器具有以下的功能 xff1a 播放歌曲 暂停播放歌曲 显示歌曲的总时长 显示歌曲的当前播放时长 调节滑块可以将歌曲调节到任何时
  • 使用Less

    为什么要使用预处理CSS 在使用CSS过程中会遇到一个非常头疼的问题 xff0c 因为CSS中没有像java C 43 43 或者PHP等程序语言一样有有自己的变量 常量 条件语句以及一些编程语法 xff0c 只是一行行单纯的属性描述 xf
  • 使用Gulp

    为什么要使用Gulp 在前端开发中通常需要做 xff0c 预处理语言的编译 js文件的压缩 css文件的压缩 图片的压缩等一系列工作 xff0c 而使用Gulp可以自动化的完成这些工作 xff0c 从而提高网站的开发效率 xff0c 在我的
  • 欢迎使用CSDN-markdown编辑器

    欢迎使用Markdown编辑器写博客 本Markdown编辑器使用StackEdit修改而来 xff0c 用它写博客 xff0c 将会带来全新的体验哦 xff1a Markdown和扩展Markdown简洁的语法代码块高亮图片链接和图片上传
  • CMakeList的基本写法

    最近需要自己写CMakaList xff0c 所以简要写一下一些基本的操作 为图实用 xff0c 只写了常用的简单操作 1 确定cmake最低版本需求 span class hljs function span class hljs tit
  • SLAM的一点认识

    SLAM的一点认识 本人邮箱 xff1a sylvester0510 64 163 com xff0c 欢迎交流讨论 xff0c 欢迎转载 xff0c 转载请注明网址http blog csdn net u010128736 一 我与SLA
  • ORB-SLAM2详解(六)闭环检测

    ORB SLAM2详解 xff08 六 xff09 闭环检测 本人邮箱 xff1a sylvester0510 64 163 com xff0c 欢迎交流讨论 xff0c 欢迎转载 xff0c 转载请注明网址http blog csdn n
  • FreeRTOS系列|任务创建和删除

    任务创建和删除 1 任务创建和删除API函数 xTaskCreate 函数 xff1a 动态创建一个新的任务 xff0c 每个任务都需要RAM来保存任务状态 任务控制块 43 任务栈 xff0c 此接口采用动态分配内存资源 BaseType
  • 深度学习如何做特征工程?

    深度能自动获取特征 只是对某些领域而言的 实际上深度学习只是能自动对输入的低阶特征进行组合 变换 xff0c 得到高阶特征 对于图像处理之类的领域来说 xff0c 像素点就可以作为低阶特征输入 xff0c 组合 变换得到的高阶特征也有比较好
  • Git:《Git学习视频》学习笔记

    视频地址 xff1a 黑马程序员 Git学习视频 目录 xff1a 一Git介绍二Git与SVN的区别 速度结构其他 三Git基本命令的使用掌握 如何学习git指令常见命令单人开发配置帐号信息一般只需配置一次全局帐号即可查看日志起别名版本回
  • 海康云台摄像机 ISAPI 的签名机制与语音传输

    由于海康HikVision Hik 平台摄像机的SDK不支持Arm Linux平台 xff0c 为了跨平台的兼容性 xff0c 只能使用ISAPI作为控制或接收相机数据的方式 xff0c ISAPI是Hik的一套HTTP通信协议 xff0c
  • 无人机中的坐标系与相机姿态计算

    球坐标系 球坐标系是三维坐标系中的一种 xff0c 在无人机中一般使用球坐标系来表示相机姿态 xff0c 相机姿态的坐标是相对于无人机的 xff0c 而无人机的飞行姿态则是相对于大地坐标系的 这里我们使用的相机是2自由度的相机 xff0c
  • 【Ubuntu】安装中文输入法、终端不支持中文的解决方法

    一 中文输入法安装 1 安装汉语语言包 sudo apt install fcitx sudo apt install language pack zh hans 2 安装google拼音输入法 sudo apt install fcitx
  • 【Qt】QtCreator中配置clang-format

    1 安装clang format sudo apt install clang format 2 添加插件Beautifier 在QtCreator gt Help gt About Plugins 中添加插件Beautifer 添加后要重
  • 【TX2】TX2开发板系统默认串口有ttyS0(调试口)、ttyTHS1、ttyTHS2、ttyTHS3,通过修改设备树文件,可以新增三个串口

    1 简述 TX2开发板系统默认串口有ttyS0 调试口 ttyTHS1 ttyTHS2 ttyTHS3 通过修改设备树文件 可以新增三个串口 2 设备树 设备树中关于串口部分的描述 2 1 基础配置 注意 在这里状态都配置成禁止 statu
  • 【STM32】入门(六):I2C协议

    STM32 STM32单片机总目录 1 常见I2C设备 EEPROM 温湿度传感器 xff0c 例如 xff1a AHT10 电量计 xff0c 例如 xff1a TI的BQ34Z100 日历时钟 模数或数模转换器 2 I2C总线结构 I2

随机推荐

  • 【STM32】入门(九):HAL库学习

    STM32 STM32单片机总目录 1 简述 STD xff08 Standard Peripheral Libraries xff09 标准库 xff1a 面向过程 xff0c 仅仅是在寄存器上的一层封装操作 HAL xff08 Hard
  • 【STM32】入门(十一):初识uCOS-III

    STM32 STM32单片机总目录 1 轮询 中断 多任务对比 2 什么是任务 如果您学过linux xff0c 那么任务可以理解为线程 在代码中的体现就是线程函数 xff0c 一个函数中有个无限循环函数 xff0c 并且永不返回 例如 x
  • FreeRTOS系列|任务挂起和恢复

    任务挂起和恢复 1 任务挂起和恢复API函数 vTaskSuspend 函数 xff1a 将任务置于挂起状态 span class token keyword void span span class token function vTas
  • vscode 代码特效插件 让你的代码写出火花

    如果你经常觉得写代码是一件无趣的事情 xff0c 那么这里有一款插件推荐给你 xff0c 可以给你枯燥无味的写代码时添加一些趣味 这款插件名字叫做 power mode 现在我来教你如何下载它 xff0c 并且使用它 1 下载插件 打开vs
  • 【STM32】入门(十二):实时操作系统RTOS和通用操作系统GPOS的区别

    STM32 STM32单片机总目录 1 简述 实时操作系统 RTOS xff0c Real Time Operating System 通用操作系统 GPOS xff0c General Purpose Operating System 2
  • 【STM32】入门(十四):FreeRTOS-任务

    1 简述 FreeRTOS应用程序由一组独立的任务构成 在任何时间点 xff0c 应用程序中只能执行一个任务 xff0c FreeRTOS调度器负责决定所要执行的任务 每个任务在自己的上下文中执行 xff0c 不依赖于系统内的其他任务或 F
  • 【SBUS】一文看懂SBUS协议

    STM32 STM32单片机总目录 1 简介 S BUS是一个串行通信协议 xff0c S BUS是FUTABA提出的舵机控制总线 xff0c S bus使用RS232C串口的硬件协议作为自己的硬件运行基础 使用TTL电平 xff0c 即3
  • 【ubuntu】ubuntu14.04、16.04、18.04 LTS版本支持时间

    0 历史版本下载地址 http old releases ubuntu com releases http mirrors 163 com ubuntu releases 1 官网说明 https wiki ubuntu com Kerne
  • 树莓派,tx2硬件对比

    具体参考以下链接 http www exuehao com article detail 14
  • Gazebo中的平面运动 (urdf+控制器设置)及所遇见的问题

    这里有个视频 xff0c 介绍怎么让机器人在平面运动 xff08 在x和y方向上进行平移 xff09 xff1a https www youtube com watch v 61 mtSpqObg9X4 如果你们看不了视频也没关系 xff0
  • 2014年年终总结:写书成长,承载收获

    雪花纷飞 xff0c 任你飘落凝成魅力的雪域之城 美丽的守候 xff0c 望长城内外惟余莽莽 数着北国春夏秋冬的每一天 xff0c 2014 的日历天天换新装 xff0c 消瘦了你的时光 但丰盈了我的渴望 2014 年 xff0c 在你的身
  • 漫步数学分析三十五——乘法法则与梯度

    微分中另一个有名的法则是乘法法则或莱布尼兹法则 定 理 6 令 A R n 是开集 xff0c f A R m g A R 是可微函数 xff0c 那么 g f 是可微的并且对于 x A D g f x R n R m 为 D
  • CAN总线标准及协议分析

    目录 1 简介 2 CAN总线标准 2 1 物理层 2 1 1 CAN总线网络 2 1 2 CAN收发器 2 1 3 CAN信号表示 2 1 4 CAN信号传输 2 2 数据链路层 2 2 1 数据帧 2 2 1 1 帧起始与结束帧 2 2
  • Eclipse中Python开发环境搭建详细图文教程(Windows环境)

    转载请注明出处 Eclipse可便捷的集成开发Python xff0c 这里我们为了更好地使用Python进行机器学习 xff0c 首先进行Eclipse中Python开发环境的搭建 一 下载EclipseIDE 下载地址 xff1a ht
  • FreeRTOS系列|多任务调度

    多任务调度 1 多任务启动流程 多任务启动流程如下表所示 启动后以下各函数由上至下依次执行含义osKernelStart 启动内核vTaskStartScheduler 启动任务调度器xPortStartScheduler 启动调度器prv
  • Realsense d435i驱动安装、配置及校准

    写在前面 本文是在ubuntu20 04下安装 xff0c 其它版本大同小异 可能出现的问题 xff0c 主要由各自安装相关库版本不一致导致 xff0c 故问题不一 xff0c 但一般很好解决 xff0c 正常情况下不会出现 Intel R
  • Realsense d435i内参、外参标定

    使用工具code utils imu utils kalibr对Realsense d435i 内参 外参标定 本文介绍上述工具的安装 xff0c 及标定方法 一 code utils安装 1 建立工作空间 mkdir p calibrat
  • 从零完成slam实战,以Vins-Fusion为例

    写在前面 1 本文以vins fusion为例 xff0c 是因为其框架正统 简单清晰 xff0c 易于调试和后续改进 xff1b camera imu外参及同步时间td可实时估计 xff1b 已有融合gps方案且较为容易可添加融合其它传感
  • Vins-Fusion整体框架,数据流分析

    一 VINS Fusion VINS Fusion是一种基于优化的多传感器状态估计器 xff0c 可实现自主应用 xff08 无人机 汽车和AR VR xff09 的精确自我定位 VINS Fusion是VINS Mono的扩展 xff0c
  • Vins-Fusion初始化位姿——3D-2D:PNP求解当前帧位姿

    继上一篇博文Vins Fusion 外参camera imu 标定 xff0c 本文继续介绍Vins Fusion初始化时 xff0c 通过PNP求解当前帧位姿 一 3D 2D xff1a PNP PnP是求解3D到2D点对运动的估计 xf