解读《视觉SLAM十四讲》,带你一步一步入门视觉SLAM—— 第 3 讲 三维刚体运动 (下)

2024-06-05 17:38

本文主要是介绍解读《视觉SLAM十四讲》,带你一步一步入门视觉SLAM—— 第 3 讲 三维刚体运动 (下),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

陪女朋友为期五天的农村调研终于结束,终于可以回到大魔都享受城市生活了。在高铁上闲来无事再写点吧!(由于我肩部肌肉劳损,太疼了,所以本篇博客是我口述,女朋友代写的,感谢她的鼎力相助)
  
  在上一篇博客中我们介绍了三维刚体运动的旋转矩阵和变换矩阵,下面我要带你解读这一讲的下半部分内容:

  • 旋转向量、欧拉角、四元数;

解读

这一讲中的很多概念都比较抽象,我尽量给大家总结的通俗一些,但是大家还是要自己仔细去理解和体会这些几何变换的意义,有些东西如果实在难以理解,你也别着急,咱们先学会用,慢慢的就理解了。
  
  前面我们介绍了旋转矩阵和变换矩阵,它们的矩阵描述分别为:
R = [ a 11 a 12 a 13 a 21 a 22 a 23 a 31 a 32 a 33 ] (0) R = \left[\begin{matrix}a_{11}&a_{12}&a_{13}\\ a_{21}&a_{22}&a_{23}\\a_{31}&a_{32}&a_{33} \end{matrix}\right] \tag0 R=a11a21a31a12a22a32a13a23a33(0)

T = [ R 3 ∗ 3 t 3 ∗ 1 0 T 1 ] (1) T = \left[\begin{matrix}R_{3*3}&t_{3*1}\\ 0^T&1\end{matrix}\right] \tag1 T=[R330Tt311](1)
  我们观察(0)式可以发现,在旋转矩阵中一共有9个变量,也就是说旋转矩阵有9个自由度,而实际上我们空间当中的一次旋转变换只需要3个自由度,也就是3个变量,所以我们使用旋转矩阵表示旋转变换时,额外引入了6个变量,就会造成表达的冗余。
  
  我们再观察(1)式,在变换矩阵中一共有16个量,实际上一次変换只有6个自由度,也就只需要6个变量,那么变换矩阵实际也是冗余的。
  
  另外一方面,旋转矩阵和变换矩阵都是正交矩阵,并且行列式的值为1,这在运算和优化中就会引入额外的限制,因为我们的优化结果必须要满足旋转矩阵和变换矩阵的形式。
  
  于是我们就想能不能有更好的表达方法去表达旋转和变换,能够一方面变量很紧凑,另一方面不会引入额外的约束。那么我们就要探索下面的一些方法。

旋转向量

因为前面所述的问题,所以作者在书中提出了旋转向量。旋转向量实际上并不难理解的,一个旋转轴 n ⃗ = [ a 1 , a 2 , a 3 ] \vec n=[a_1,a_2,a_3] n =[a1,a2,a3]加上一个旋转角度 θ \theta θ就可以达到旋转的效果。关于旋转向量,它和旋转矩阵一样也表示一种旋转变换,那么它们之间一定可以相互转换,转换可以使用罗德里格斯公式:
R = c o s θ I ⃗ + ( 1 − c o s θ ) n ⃗ n ⃗ T + s i n θ [ 0 − a 3 a 2 a 3 0 − a 1 − a 2 a 1 0 ] R = cos\theta \vec I +(1-cos\theta)\vec n \vec n^T+sin\theta \left[\begin{matrix}0&-a_3&a_{2}\\ a_{3}&0&-a_{1}\\-a_{2}&a_{1}&0 \end{matrix}\right] R=cosθI +(1cosθ)n n T+sinθ0a3a2a30a1a2a10
同样,旋转矩阵也可以转换为旋转向量,转换公式大家可以参考书中的公式。
  
  尽管旋转向量已经比旋转矩阵直观了很多,但是还是不够直观,于是又提出了欧拉角。

欧拉角

我们可以想象一下:对于一个三维坐标系,变换它的姿态,我们可以分为三步,第一步,我们先选择任意一个轴,以它为旋转轴进行旋转,第二步,在剩下的两个轴中选择一个轴作为旋转轴,然后旋转一定的角度,第三步,再以最后一根轴为旋转轴进行旋转,这样的过程就可以把一个坐标系旋转为另外的姿态。
  
  欧拉角虽然很直观,但是有很大的局限性,它常常会发生万向锁问题,也称为奇异性问题。当我们选择XYZ轴不同顺序进行依次旋转时常常发生万向锁问题,所以在SLAM中欧拉角的应用并不多,这里不再细说,大家看书就可以。关于万向锁问题大家可以参考这个视频了解一下《“欧拉角旋转”产生“万向锁”的来源,以及如何避免万向锁》
  
  我们不妨总结一下前面说的几种表示旋转的方法:欧拉角虽然直观,但是会导致万向锁问题,它很可能就不可用了,所以它在SLAM问题中很少使用;旋转矩阵参数冗余而且还会引入额外的约束,虽然使用会带来一些麻烦,但是至少不会失效;旋转向量使用旋转轴加上旋转角,好像还挺好的,没有带来什么不便和问题。那么还有更好的表示旋转的方法吗?答案是有的!

四元数

我是在学习SLAM的时候,才第一次接触到四元数,当时第一次接触也是一头雾水,尽管现在也没有完全理解,但是算是会用了。
  
  前面我们说到的一些表示旋转的方法,或多或少都存在一些问题,所以为了解决这些问题,就有人想到了四元数。这个东西我确实没有深入的去了解,所以靠我现在的理解,还是很难讲清楚,大家还是以《十四讲》为主要去理解四元数。
  
  我有一些认识在这里和大家分享一下:我们在学习一些几何的时候总是想直观的去理解一些定理或概念,多数情况下这样是行得通的,但是在四元数上若想直观的理解它的旋转还是有些困难的,如果你实在不能理解四元数,那就暂且将它放一边,就把它当做一个工具使用就行,记住它的一些性质和用法,对于它的理解你就边用边深入。关于四元数我推荐一个英文教程你可以阅读一下《四元数数学基础》提取码:q2x3

最后,无论是四元数、旋转矩阵还还是旋转向量,它们都可以用来描述同一个旋转。我们应该在实际中选择最为方便的形式,而不必拘泥于某种特定的形式。《视觉SLAM十四讲 从理论到实践》

扩展阅读:关于的旋转矩阵、旋转向量(轴角)、欧拉角、四元数的优缺点,可以看一下这篇博客:《矩阵、欧拉角、轴-角对、四元数随笔》

实践

我建议你按照书中的代码把实践部分内容多打几遍,不要嫌麻烦,一开始写代码都是这样先重复,再模仿,最后就能自己写了。

代码部分有两个地方还是值得你去注意的:

  • 注意四元数在Eigen中的表示顺序,在书本理论部分四元数的实部在前,形式是(w, x, y, z),而在Eigen库中形式是(x, y, z, w)。你要注意一下。我在公司实习的时候,有一个工程师就因为这个顺序搞反了,导致一个BUG找了一星期。
  • 有一行代码v_rotated = q*v;,这个是用四元数计算旋转,而书上理论部分使用的计算公式是: p ′ = q p q − 1 p'=qpq^{-1} p=qpq1,但是在代码中直接用q*v,因为Eigen库重载了*号,所以你以后使用的时候,直接用*就能表示四元数的旋转了。

无论你犯了多少错,或者进步得有多慢,你都走在了那些不曾尝试的人的前面。

这篇关于解读《视觉SLAM十四讲》,带你一步一步入门视觉SLAM—— 第 3 讲 三维刚体运动 (下)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1033729

相关文章

MySQL中时区参数time_zone解读

《MySQL中时区参数time_zone解读》MySQL时区参数time_zone用于控制系统函数和字段的DEFAULTCURRENT_TIMESTAMP属性,修改时区可能会影响timestamp类型... 目录前言1.时区参数影响2.如何设置3.字段类型选择总结前言mysql 时区参数 time_zon

MySQL中的锁和MVCC机制解读

《MySQL中的锁和MVCC机制解读》MySQL事务、锁和MVCC机制是确保数据库操作原子性、一致性和隔离性的关键,事务必须遵循ACID原则,锁的类型包括表级锁、行级锁和意向锁,MVCC通过非锁定读和... 目录mysql的锁和MVCC机制事务的概念与ACID特性锁的类型及其工作机制锁的粒度与性能影响多版本

Redis过期键删除策略解读

《Redis过期键删除策略解读》Redis通过惰性删除策略和定期删除策略来管理过期键,惰性删除策略在键被访问时检查是否过期并删除,节省CPU开销但可能导致过期键滞留,定期删除策略定期扫描并删除过期键,... 目录1.Redis使用两种不同的策略来删除过期键,分别是惰性删除策略和定期删除策略1.1惰性删除策略

Redis与缓存解读

《Redis与缓存解读》文章介绍了Redis作为缓存层的优势和缺点,并分析了六种缓存更新策略,包括超时剔除、先删缓存再更新数据库、旁路缓存、先更新数据库再删缓存、先更新数据库再更新缓存、读写穿透和异步... 目录缓存缓存优缺点缓存更新策略超时剔除先删缓存再更新数据库旁路缓存(先更新数据库,再删缓存)先更新数

C#反射编程之GetConstructor()方法解读

《C#反射编程之GetConstructor()方法解读》C#中Type类的GetConstructor()方法用于获取指定类型的构造函数,该方法有多个重载版本,可以根据不同的参数获取不同特性的构造函... 目录C# GetConstructor()方法有4个重载以GetConstructor(Type[]

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题: