VINS 细节系列 - 光束法平差法(BA)Ceres 求解

2023-05-16

一、理论部分

学习过VINS的小伙伴应该知道,在SFM(structure from motion)的计算中 光束法平差法 - BA(Bundle Adjustment)

 的重要性!本人也是学习过一段时间后对其有了更加深刻的理解,那咱们就 先理论 后程序

 

1、 光束平差法

光束: 源于 bundle of light, 指的是三维空间中的点投影到像平面上的光束,而重投影误差正是利用这些光束来构建的,

因此强调光束也正是描述其优化模型的来源!

平差:感觉像测绘里面的内容!由于测量仪器的精度不完善和人为因素及外界条件的影响,测量误差总是不可避免的。

为此,观测值的个数往往要多于确定未知量所必须观测的个数。有了多余观测,势必在观测结果之间产生矛盾,测量平

差的目的就在于消除这些矛盾而求得观测量的最可靠结果并评定测量成果的精度,测量平差采用的原理就是“最小二乘法”

 

2、 BA模型到底是怎么来的?

 BA到底是干嘛的? 用一句话来描述BA那就是,BA的本质是一个优化模型,其目的是最小化重投影误差

本质是一个优化模型应该很容易理解,那么什么是重投影误差呢? 投影自然是个几何的问题,既然是几何问题那这个时候

来个图自然就是最棒了!

这些五颜六色的线就是我们讲的光束啦!那现在就该说下什么叫重投影误差了,重投影也就是指的第二次投影,那到底是怎么投影的呢?

第一次投影:指的就是相机在拍照的时候三维空间点投影到图像上,然后我们利用这些图像对一些特征点进行三角定位

                       (triangulation,显然是利用几何信息构建三角形来确定三维空间点的位置嘛 )

第二次投影:利用计算得到的三维点的坐标和我们计算得到的相机矩阵 进行第二次投影

现在我们知道什么是重投影了,那重投影误差到底是什么样的误差呢?

这个误差是指的真实三维空间点在图像平面上的投影(测量值)和重投影(预测值) 的差值,噪声等原因的存在,使得两者不会相等!

也就是这个差值不可能恰好为0,而优化的目的就是:找出最优的相机参数及三维空间点的坐标,使得将这些 差值的和 最小化!

 

数学模型如下:

BA是一个图优化模型,那首先肯定要构造一个图模型了 。既然是图模型那自然就有节点和边了,

这个图模型的节点由相机  Pi​  和三维空间点构成 Xj ​构成,如果点  Xj​ 投影到相机  Pi​ 的图像上则将这两个节点连接起来。

 

数学形式如下:

既然是优化模型,那自然就应该用各种优化算法来进行计算了!  BA现在基本都是利用LM(Levenberg-Marquardt)算法并在此基础上

利用BA模型的稀疏性质来进行计算的,LM算法是最速下降法(梯度下降法)和Gauss-Newton的结合体。

 

假设优化函数模型如下:

为什么用平方呢? 还不是因为不用计算平方根了嘛!

 

最速下降法

如果你对梯度比较熟悉的话,那你应该知道梯度方向是函数上升最快的方向,而此时我们需要解决的问题是让函数最小化。

 那就顺着梯度的负方向去迭代寻找使函数最小的变量值就好了嘛。梯度下降法就是用的这种思想,用数学表达如下:

其中  λ 为步长,最速下降法保证了每次迭代函数都是下降的,在初始点离最优点很远的时候刚开始下降的速度非常快,

但是最速下降法的迭代方向是折线形的导致了收敛非常非常的慢。

 

Newton型方法

 给定一个开口向上的一元二次函数,如何知道该函数何处最小?这个应该很容易就可以答上来了,对该函数求导,导数为 0 处就是函数最小处。

Newton型方法也就是这种思想,首先将函数利用泰勒展开到 二次项

H 为Hessian矩阵,是二次偏导矩阵。也就是说Newton型方法将函数 局部近似 成一个二次函数进行迭代,然后令 x 在  δx方向上迭代直至收敛,

接下来自然就对这个函数求导了:

 

Gauss-Newton方法

既然Newton型方法计算Hessian矩阵太困难了,那有没有什么方法可以不计算Hessian矩阵呢?在范数符号内将 e 一阶泰勒展开,我们可以得到

其中  J 为Jacobi矩阵,函数 e 对 x 求一次偏导而来,梯度也是对向量函数求一次偏导而来。将标量考虑为 1×1的矩阵,将向量考虑为   n×1的矩阵,

其实这些求导都是求Jacobi矩阵。此时不需要计算Hessian矩阵。同样,二次函数导数为0时取极值,则有

由此  x  在  δx  方向上迭代直至  ||e|| 最小,同时我们可以发现一个等式,会在下面的LM方法中用到

 

LM方法

LM方法就是在以上方法基础上的改进,通过参数的调整使得优化能在最速下降法 和 Gauss-Newton法之间自由的切换,

在保证下降的同时也能保证快速收敛。Gauss-Newton最后需要求解的方程为

LM算法在此基础上做了更改,变成了

通过参数 λ 的调节在最速下降法和Gauss-Newton法之间切换。做个不很数学的直观分析吧,当  λ 很小时,

显然和Gauss-Newton法是一样的;当 λ很大时,就变成了这样:

然后再看看前面的最速下降法?

其实LM算法的具体形式就笔者看到的就有很多种,但是本质都是通过参数 λ 在最速下降法和Gauss-Newton法之间切换。

这里选用的是维基百科上的形式,LM算法就由此保证了每次迭代都是下降的,并且可以快速收敛。

 

解方程

稠密矩阵的最小二乘解

对于形如  Ax=b 的 超定 参数方程而言,有很多求解方式,伪逆、QR分解、SVD 等等 。这些方式都有一个共同的特点,

都是将 A  看作一般的稠密矩阵,主要得到的解自然非常鲁棒,但是计算量却是和维数的三次方成正比( O ( n 3 )  。

面对BA这种超大规模的优化似乎有点不太实用。

稀疏矩阵的Cholesky分解

稠密矩阵计算起来那么复杂,如果是稀疏矩阵的话利用其稀疏的性质可以大幅减少计算量, 对于稀疏矩阵的 Cholesky分解 就是这样。

其分解形式为一个上 三角矩阵 的转置乘上自身

为什么说我们的矩阵是稀疏的?

考虑相机位置(图像数量)和空间点都非常多的情况,不难想象Jacobi矩阵不光是一个稀疏矩阵而且还可以写成形如 [A∣B] 的分块矩阵。

接下来就该利用这些性质正式进入计算了!

开始计算吧

现在再回到 Gauss-Newton 最后的超定参数方程吧。既然Jacobi 矩阵可以分块那我们就先分块,分块可以有效降低需要计算的矩阵的维度并以此减少计算量。

 

注意:李群及李代数

不知道有没有人注意到,在优化迭代的过程中,我们求的值为   δx,然后利用  x+δx 来更新 x 的值。这里就应该出现一个问题了,

对于空间点的坐标和平移向量这么处理自然没有什么问题,但是对于旋转矩阵呢?难道用 R + δ R 来更新 R 的值吗?好像不太对吧。

对于旋转矩阵 R  而言是不存在加法的,按理讲应该用 RδR来更新 R  的值,但是优化算法的迭代过程又不能是乘法,这就出现了矛盾。

这里 旋转矩阵及相关运算属于李群,此时将旋转矩阵变换到其对应的李代数上进行计算,然后再变回李群。

 

协方差矩阵

在我们的推导中是求解方程

但常常加入信息矩阵(协方差矩阵的逆),令求解方程变为

其中  Σ x  为协方差矩阵,令其为分块对角阵表示所有观测向量都不相关

 

 

二、程序部分  (Ceres Solver)

Ceres 对 BA 的介绍如下:
给定一系列测得的图像,包含特征点位置和对应关系。BA的目标就是,通过最小化重投影误差,确定三维空间点的位置和相机参数

这个优化问题通常被描述为非线性最小二乘法问题,要最小化的目标函数 即为测得图像中特征点位置 和 相机成像平面上的对应的投影

之间的差的平方。Ceres例程使用了BAL数据集 。

第一步依然使定义一个模板functor来计算残差,在这个问题中也就是的重投影误差。每个残差值依赖于 空间点的位置(3个参数)

和相机参数(9个参数)。九个相机参数包含用 Rodriques’ axis-angle表示的 旋转向量 R(3个参数),平移参数 T(3个参数),

以及焦距 f 和两个径向畸变参数 k1, k2。相机模型的详细描述也可以在BAL的主页找到;  

理解:

不知道你们有没有理解上面这个图的意思?上面的 X1是实际环境中的点,相机观察到特征点 X1 后,会在相机平面上得到 像素点x1,

这个 x1 就是 此时 P1相机得到的观测值! 那可能会问,X1' 是什么?X1'P1 相机 前面的相机 用三角法估计出来的三维点,但是这个

估计出来的三维点位置和真正环境中的X1是不重和的!因为噪声等误差的存在嘛!现在我们知道了这个虚拟的三维点 X1' ,然后投影到

P1 相机上,得到了 像素点 x1' ;  得到了 P1 相机下 像素点 x1和 x1', 那我们就 进行优化,不断调整 R,T等参数 是 他俩的误差最小!

 

 

/---------------------------------------------------  程序  ------------------------------------------------------------/

BA.h

struct SnavelyReprojectionError {
	SnavelyReprojectionError(double observed_x, double observed_y)
		: observed_x(observed_x), observed_y(observed_y) {}
 
	template <typename T>
	bool operator()(const T* const camera,
		const T* const point,
		T* residuals) const {

		// camera[0,1,2] 是三个方向上的旋转
		T p[3];

                //根据旋转,预测空间特征点在 相机的坐标
		ceres::AngleAxisRotatePoint(camera, point, p);
 
		// camera[3,4,5] 是XYZ三个方向上的平移
		p[0] += camera[3];
		p[1] += camera[4];
		p[2] += camera[5];
 
                //归一化坐标
		T xp = -p[0] / p[2];
		T yp = -p[1] / p[2];
 
		// 下面的程序是为了得到 经过修正后的 坐标 
		const T& l1 = camera[7];
		const T& l2 = camera[8];
		T r2 = xp*xp + yp*yp;
		T distortion = 1.0 + r2  * (l1 + l2  * r2);
 
		const T& focal = camera[6];
		T predicted_x = focal * distortion * xp;
		T predicted_y = focal * distortion * yp;
 
 
		// 计算两个归一化 坐标的差:预测值 和 实际的测量值
		residuals[0] = predicted_x - observed_x;
		residuals[1] = predicted_y - observed_y;
 
		return true;
	}
 
	 
	static ceres::CostFunction* Create(const double observed_x,
		const double observed_y) {
		return (new ceres::AutoDiffCostFunction<SnavelyReprojectionError, 2, 9,  3>(new SnavelyReprojectionError(observed_x, observed_y)));
	}
 
	double observed_x;
	double observed_y;
};

以上部分定义了反向投影误差是怎么计算的,即residuals的计算,以及损失函数是怎么定义的,损失函数中的几个参数,

第一个为代价函数的类型,第二个为代价的维度,第三个为每张像片外方位元素和相机内参,demo使用的相机内参为一

个焦距加两个畸变参数,再加上3个旋转矩阵参数3个平移矩阵参数,正好9个,第四个为每一个空间三维点的坐标为3维。

 

main.cpp

if (!bal_problem.LoadFile("C:\\Users\\sggzg\\Desktop\\problem-49-7776-pre.txt")) {
		std::cerr << "ERROR: unable to open file " << "C:\\Users\\sggzg\\Desktop\\problem - 49 - 7776 - pre.txt" << "\n";
	}
const double* observations = bal_problem.observations();
 
 
 
ceres::Problem problem;
 
for (int i = 0; i < bal_problem.num_observations(); ++i)
 {
ceres::CostFunction* cost_function =SnavelyReprojectionError::Create(observations[2 * i + 0],observations[2 * i + 1]);
problem.AddResidualBlock(cost_function,NULL  ,bal_problem.mutable_camera_for_observation(i),bal_problem.mutable_point_for_observation(i));}
 
 
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_SCHUR;
options.max_num_iterations = 3;
options.minimizer_progress_to_stdout = true;
 
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
std::cout << summary.FullReport() << "\n";

 

这一部分中for循环主要就是添加每一个前面所说的光束法平差单元,AddResidualBlock函数即添加每一个平差单元的需要优化的参数,

Create函数通过具体的像点观测值实例化前面定义的损失函数。平差的一些选项设置,平差报告的打印。

 

结合自己的实验数据进行调整:

主要是对反向投影误差计算的修改,根据自己的误差定义修改计算residuals的过程,以及根据相机的不同重新定义损失函数,如下:

ceres::CostFunction* cost_function = new ceres::AutoDiffCostFunction<
				BundleAdjustment_CostFunction, 2, 4, 3, 3, 3>(
					new BundleAdjustment_CostFunction(point2D.X(), point2D.Y()));
 
problem.AddResidualBlock(cost_function, loss_function, psfmreconstruction->ImageDatas[img_idx].image.Qvec().data(),
				psfmreconstruction->ImageDatas[img_idx].image.Tvec().data(), psfmreconstruction->params_.data(), 
				psfmreconstruction->points3Ds_[point2D.Point3DId()].XYZ().data());

这时可以看出损失函数中的几个参数,第一个为代价函数的类型,第二个为代价的维度,第三个为每张像片外方位元素和相机内参,

我使用的相机内参为一个焦距加两个像主点参数,再加上4元数表示的qvec4个参数以及平移向量3个参数,第四个为每一个空间三维点的坐标为3维。

实验数据

原始代码针对的数据集下载地址:http://grail.cs.washington.edu/projects/bal/

 

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

VINS 细节系列 - 光束法平差法(BA)Ceres 求解 的相关文章

  • Windows 环境下安装Redis 5.0.x 服务图文教程

    Windows 环境下安装Redis 5 0 x 服务图文教程 Redis官网并没有提供windows的安装包 xff0c github有第三方制作的windows安装包 下载地址 xff1a https github com tporad
  • Python 爬虫+可视化,手把手教你使用 Python 爬取 JD 网站并且可视化展示

    当你看到别人使用 Python 网络爬虫做出一些高大上的项目你是否也有那么一点点的心动 xff1f 羡慕别人用几行简单的代码就能获取到自己想要的数据 xff1f 羡慕别人用几行代码就能做出优美的可视化图案 xff1f 我将使用最新 Pyth
  • 推荐系统实践:基于数据集MovieLens构造简单推荐系统

    摘要 本文基于 MovieLens 数据集构造了用户 电影项目评价矩阵 xff0c 并基于评价矩阵计算两用户间的相似度 xff0c 取出相似度最高的 N 个用户作为候选用户序列 接着筛选出这 N 个候选用户的高分电影项目且当前用户尚未观看
  • Flask 入门教程:Jinja2模板用法

    Jinja2模板引擎简介 模板 在前面的示例中 xff0c 视图函数的主要作用是生成请求的响应 xff0c 这是最简单的请求 实际上 xff0c 视图函数有两个作用 xff1a 处理业务逻辑和返回响应内容 在大型应用中 xff0c 把业务逻
  • VINS-mono中坐标系定义以及通过VINS-mono求解无人机位姿

    因为在科研中需要使用VINS mono算法来为无人机提供位姿估计信息 因此需要搞清楚VINS mono相应坐标系以及无人机坐标系之间的关系 目录 1 坐标系关系 1 1 VINS mono坐标系定义 1 2 无人机坐标系 2 通过VINS
  • Github Copilot 开始收费了, 帮你列出些替代的插件

    今天打开 VSCode xff0c 弹出了Github Copilot 开始收费的通知 可以免费用到 8 月 22 日 xff0c 每月 70 元还是有些小贵 这里给大家推荐一些替代品 xff1a Kite https www kite c
  • 如何在 Ubuntu上使用 Nginx 设置密码验证

    介绍 设置 Web 服务器时 xff0c 您通常希望限制访问网站的某些部分 Web 应用程序通常提供自己的身份验证和授权方法 xff0c 但如果这些方法不充分或不可用 xff0c 则可以使用 Web 服务器本身来限制访问 在本指南中 xff
  • 使用Argo CD和GitOps持续部署到Kubernetes

    引言 使用Kubernetes部署你的应用程序可以提供显著的基础设施优势 xff0c 例如灵活的伸缩 分布式组件的管理以及对应用程序不同版本的控制 然而 xff0c 随着控制的增加 xff0c 复杂性也随之增加 持续集成和持续部署 CI C
  • GitHub Codespaces 的配置

    CPU xff1a 4x Xeon 64 2 60 GHz 轻度开发够用 xff0c 要是编译什么稍微复杂一点的项目 估计会CPU跑满 内存 xff1a 8G xff0c 勉强够用 自用的Mac 16G都感觉不太够 硬盘 xff1a 32G
  • 使用Zoundry在CSDN发布Blog

    安装一个Zoundry吧 xff0c 用这个来离线写Blog xff0c 再也不怕突然断线和丢失文章了 Zoundry是用Python实现的一个离线撰写Blog工具 支持Community Servedr blogger com Wordp
  • Python中Array的常用操作(二)数组基本操作

    1 数组操作 x代表数组中的元素 xff0c i代表位置 a append x 把元素x添加到数组的尾部 b insert i x 把元素x 插入到位置i c remove x 删除第一个元素x d pop i 删除第i个元素 xff0c
  • Python中Array的常用操作(三)数组高级操作

    1 抽取数组中不重复的数据 gt gt gt a 61 x 2 for x in range 1 5 2 gt gt gt uniq 61 list set a 8 2 4 6 gt gt gt uniq 61 sorted set a 2
  • 2011年,移动互联网加速蔓延 – 来自2011移动开发者大会

    2011移动开发者大会 xff0c 这是第二届移动开发者大会了 xff0c 这一年来移动互联网各个领域蔓延开来 xff0c 蔓延这个词是开复老师演讲的主题 从事塞班开发的请举手 xff0c 举手者寥寥 记得在去年移动开发者大会上 xff0c
  • main函数之前做了什么?

    main函数之前 真正的函数执行入口或开始 一种解释 实际上 xff0c 在可执行文件被加载之后 xff0c 控制权立即交给由编译器插入的Start函数 xff0c 它将对后面这些全局变量进行准备 xff1a osver 操作系统的构件编号
  • detecron2中的注册机制

    文章目录 一 为什么使用注册类二 注册类的实现 传送门 Detectron2 01 注册机制 Registry 实现 一 为什么使用注册类 以下转自知乎 https zhuanlan zhihu com p 93835858 对于detec
  • 单目视觉SLAM在无人机上的应用

    目录 写在前面 本文说明 论文链接和实验视频 源代码链接 一 实验环境 硬件 软件 算法 二 实验环境搭建过程 1 Intel NUC安装Ubuntu 16 04 2 安装ROS D435i驱动以及ORB SLAM2算法 3 ORB SLA
  • TypeError: Expected cv::UMat for argument ‘img‘

    研究Detectron2中的在线数据增强的源码 并显示数据增强后的图像时 xff0c 遇到 TypeError Expected cv UMat for argument 39 img 的问题 显然 xff0c 问题要求是输入一个uint8
  • Linux 桌面终于迎来了 Docker Desktop

    Docker 桌面是容器化应用程序的最简单方法 无需考虑在你选择的系统上设置环境即可开始使用 只需要安装 Docker 桌面 xff0c 就可以开始了 Docker 桌面应用程序附带容器工具 xff0c 如 Kubernetes Docke
  • Dockerfile制作镜像和常用Shell脚本语法记录

    一 常规命令和使用记录 1 定义变量 判断匹配 赋值等 定义变量 addr 61 a namespace 61 b 判断匹配自定义的 包括参数化构建设置的变量 环境变量 xff0c 并赋值 case 34 Env 34 in dev nam
  • [Holo_wo]-vscode常用配置项说明

    vscode 配置文件核心 settings json xff1a 整个vscode的配置 xff0c 是本地vscode的配置 xff0c 如果有ssh远程 xff0c 那么会在远程主机的 vscode server目录下有setting

随机推荐

  • 基于jQuery的ajax跨域请求,PHP作为服务器端代码

    ajax实现跨域请求有两种方式 xff1a 方法一 xff1a jsonp的方式 jsonp方式的关键点在客户请求以jsonp作为数据类型 xff0c 服务器端接收jsonp的回调函数 xff0c 并通过回调函数进行数据的传输 具体代码如下
  • 无人机位置信息计算无人机的瞬时速度的matlab仿真

    目录 1 算法描述 2 仿真效果预览 3 MATLAB核心程序 4 完整MATLAB 1 算法描述 无人机最早在20世纪20年代出现 xff0c 1914年第一次世界大战正进行得如火如荼 xff0c 英国的卡德尔和皮切尔两位将军 xff0c
  • 基于simulink的无人机姿态飞行控制仿真

    目录 1 算法描述 2 仿真效果预览 3 MATLAB核心程序 4 完整MATLAB 1 算法描述 无人机是无人驾驶飞机的简称 xff08 Unmanned Aerial Vehicle xff09 xff0c 是利用无线电遥控设备和自备的
  • 基于ADRC自抗扰控制器的simulink仿真,ESO和TD等模块使用S函数开发

    目录 1 算法仿真效果 2 MATLAB核心程序 3 算法涉及理论知识概要 4 完整MATLAB 1 算法仿真效果 matlab2022a仿真结果如下 xff1a 2 MATLAB核心程序 function sys x0 str ts 61
  • m基于模糊控制与遗传优化的自适应ADRC双闭环控制策略matlab仿真

    目录 1 算法仿真效果 2 MATLAB核心程序 3 算法涉及理论知识概要 4 完整MATLAB 1 算法仿真效果 matlab2013b仿真结果如下 xff1a 遗传优化的优化迭代过程仿真图 xff1a 这个是我们采用的优化算法的有过过程
  • VINS-mono在Ubuntu20.04上从零开始安装运行和环境配置(尝试)

    最近尝试在Ubuntu 20 04上安装运行港科大的VINS mono算法 详细记录一下安装过程以及遇到的问题 先记录一下结果 ROS opencv Eigen Ceres以及VINS mono都编译并安装成功了 但是用euroc数据集跑V
  • 数据结构-C++实现

    之前的2周一直在学数据结构 xff0c 头都大了 我是之前对数据结构一点认识都没有 xff0c 我是直接看书怼的 xff0c 我看的是 大话数据结构 xff0c 前面的讲解还不错 xff0c 到了树 图后 xff0c 就有点看不懂了 xff
  • 几款好看的css表格

    表格一 xff1a 代码 xff1a html代码段 xff1a 是用vs写的 表头 lt th gt 那是从数据库读取的数据段 lt td gt 那是我为测试效果加的代码 xff0c 大家可以自行更改 lt h1 gt 待处理订单 lt
  • 非线性优化 (曲线拟合) 问题:高斯牛顿、g2o 方法总结

    其实还有一个Ceres库可以进行优化 xff0c 但是之前的博客已经具体分析了 xff0c 所以这里就对其余两个进行了介绍 xff0c 相关的内容是SLAM14讲里面的知识 一 理论部分 我们先用一个简单的例子来说明如何求解最小二乘问题 x
  • VINS-Fusion : EUROC、TUM、KITTI测试成功 + 程序进程详细梳理

    完成以下任务的前提是系统安装了必备的库 xff0c 比如cere Eigen3 3等 提前下载好了数据集EUROC xff0c KITTI等 一 相关论文 T Qin J Pan S Cao and S Shen A General Opt
  • ROS 简单理解

    https download csdn net download qq 30022867 11120759 utm medium 61 distribute pc relevant download none task download b
  • ROS系列:七、熟练使用rviz

    7 熟练使用rviz xff08 1 xff09 rviz整体界面 rviz是ROS自带的图形化工具 xff0c 可以很方便的让用户通过图形界面开发调试ROS 操作界面也十分简洁 xff0c 如图29 xff0c 界面主要分为上侧菜单区 左
  • ROS系列:八、图像消息和OpenCV图像之间进行转换-cv_bridge

    cv bridge是在ROS图像消息和OpenCV图像之间进行转换的一个功能包 一 xff09 在ROS图像和OpenCV图像之间转换 xff08 C 43 43 xff09 xff11 xff0e Concepts xff08 概念 xf
  • ROS系列:九、rosbag使用

    文章目录 解析rosbag中的 bag文件 xff0c 得到 jpg图片数据和 pcd点云数据 https blog csdn net weixin 40000540 article details 83859694 1 rosbag写入文
  • 三、松灵课堂 | SCOUT的仿真使用

    仿真环境的介绍 Gazebo Gazebo是一款3D动态模拟器 xff0c 能够在复杂的室内和室外环境中准确有效地模拟机器人群 与游戏引擎提供高保真度的视觉模拟类似 xff0c Gazebo提供高保真度的物理模拟 xff0c 其提供一整套传
  • 1PPS:秒脉冲 相关概念理解

    时钟模块上的GPS接收机负责接收GPS天线传输的射频信号 xff0c 然后进行变频解调等信号处理 xff0c 向基站提供1pps信号 xff0c 进行同步 GPS使用原子钟 xff08 原子钟 xff0c 是一种计时装置 xff0c 精度可
  • opencv GStreamer-CRITICAL

    使用openvino中的opencv跑之前的代码 碰到个问题 span class token punctuation span myProg span class token operator span span class token
  • 激光雷达 LOAM 论文 解析

    注意 xff1a 本人实验室买的是Velodyne VLP 16激光雷和 LOAM 论文中作者用的不一样 xff0c 在介绍论文之前先介绍一下激光雷达的工作原路 xff0c 这样更容易理解激光雷达的工作过程 xff0c 其实物图如下图1所示
  • VINS 细节系列 - 坐标转换关系

    前言 在学习VINS Mono过程中 xff0c 对初始化代码中的坐标转换关系做出了一些推导 xff0c 特意写了博客记录一下 xff0c 主要记录大体的变量转换关系 相机和IMU的外参 若需要VINS标定旋转外参 xff0c 则进入以下代
  • VINS 细节系列 - 光束法平差法(BA)Ceres 求解

    一 理论部分 学习过VINS的小伙伴应该知道 xff0c 在SFM xff08 structure from motion xff09 的计算中 光束法平差法 BA xff08 Bundle Adjustment xff09 的重要性 xf