万向节锁(Gimbal Lock)的理解
结论
我直接抛出结论:
Gimbal Lock 产生的原因不是欧拉角也不是旋转顺序,而是我們的思维方式和程序的执行逻辑没有对应,也就是说是我们的观念导致这个情况的发生。
他人解释
首先我们看一下欧拉角的定义:
用一句话说,欧拉角就是物体绕坐标系三个坐标轴(x,y,z轴)的旋转角度。
在这里,坐标系可以是世界坐标系,也可以是物体坐标系,旋转顺序也是任意的,可以是xyz,xzy,yxz,zxy,yzx,zyx中的任何一种,甚至可以是xyx,xyy,xzz,zxz等等等等。。。。。。所以说欧拉角多种多样。欧拉角可分为两种情况:
1,静态:即绕世界坐标系三个轴的旋转,由于物体旋转过程中坐标轴保持静止,所以称为静态。
2,动态:即绕物体坐标系三个轴的旋转,由于物体旋转过程中坐标轴随着物体做相同的转动,所以称为动态。
网上的文章,一般都是这样解释的:
是指物体的两个旋转轴指向同一个方向。实际上,当两个旋转轴平行时,我们就说万向节锁现象发生了,换句话说,绕一个轴旋转可能会覆盖住另一个轴的旋转,从而失去一维自由度
通常说来,万向节锁发生在使用Eular Angles(欧拉角)的旋转操作中,原因是Eular Angles按照一定的顺序依次独立地绕轴旋转。让我们想象一个具体的旋转场景,首先物体先绕转X轴旋转,然后再绕Y轴,最后绕Z轴选择,从而完成一个旋转操作(飘飘白云译注:实际是想绕某一个轴旋转,然而Eular Angle将这个旋转分成三个独立的步骤进行),当你绕Y轴旋转90度之后万向节锁的问题就出现了,因为X轴已经被求值了,它不再随同其他两个轴旋转,这样X轴与Z轴就指向同一个方向(它们相当于同一个轴了)。
看得懂吗?我是看不太懂~
我的理解
我们先来考虑一下,旋转到底是怎么个旋转法。
静态的情况很好理解,怎么旋转都不会有问题,万向节的问题是不会出现在静态的旋转过程中的。但是你想像一下动态的旋转,动态的旋转,这里会有两个坐标系,看清楚了,两个坐标系!
- 世界坐标系
- 物体坐标系
那么这两者是什么关系呢?
一开始,这两个坐标系是重合的,但是旋转开始以后,世界坐标系不会变化,物体坐标系随着旋转就发生变化了。
亲爱的读者,你们先想想,这两个坐标系的关系,你们觉得物体旋转是绕着那个坐标系旋转的?
你会说:
你刚刚不是说了嘛!是绕着物体的坐标系旋转的!
对,没有错,那么在物体旋转的时候,物体的坐标系是不是一直在变化呢?是的!那么我們在给他旋转的参数的时候考虑到这个问题了吗?没有!
就是说我给他的旋转的参数是基于一种假设:每一次旋转都是以物体的坐标系为参考来进行的。就是说我是希望它每一次旋转前,都能够将旋转参数在物体坐标系上进行计算。很简单,一架飞机,作为机长,每次旋转以后他跟着飞机旋转了,后面的旋转操作自然是基于新的物体坐标系来的。
但是实际上,程序解析我给的数据的时候,只是简单地将三个轴的旋转一个个的相乘,也就是说,总的来说还是在最开始的那个坐标系(也就是一直不动的世界坐标系)下面计算的。而且需要注意的是: 每一次进行计算的顺序是确定不变的! 这也是为什么有人会说万向节问题是因为旋转顺序导致的樂。
看一下在OpenGL 实现旋转的代码:
void configRotateTrans(GLfloat radX, GLfloat radY, GLfloat radZ) {
GLfloat xTrans[4][4] = {0};
GLfloat yTrans[4][4] = {0};
GLfloat zTrans[4][4] = {0};
GLfloat tempMatrix[4][4] = {0};
xTrans[3][3] = 1;
xTrans[0][0] = 1;
xTrans[1][1] = cosf(radX);
xTrans[1][2] = -sinf(radX);
xTrans[2][2] = cosf(radX);
xTrans[2][1] = sinf(radX);
yTrans[3][3] = 1;
yTrans[0][0] = cosf(radY);
yTrans[0][2] = sinf(radY);
yTrans[2][2] = cosf(radY);
yTrans[2][0] = -sinf(radY);
yTrans[1][1] = 1;
zTrans[3][3] = 1;
zTrans[2][2] = 1;
zTrans[0][0] = cosf(radZ);
zTrans[0][1] = -sinf(radZ);
zTrans[1][0] = sinf(radZ);
zTrans[1][1] = cosf(radZ);
// Multiply the 3 matrix
// rotateTrans = xTrans * yTrans * zTrans
multiMatrix(xTrans, yTrans, tempMatrix);
multiMatrix(tempMatrix, zTrans, rotateTrans);
看懂了吗,物体最终在哪个位置是简单粗暴地将绕xyz三个旋转的矩阵连续相乘得到的,计算的顺序是x->y->z,那么比如用户先输入绕y轴转90度,再输入绕x轴转90度。其实程序执行的时候,还是会先将x轴的数据进行计算,再计算y轴的数据。但是如果用户先输入绕y轴转90度,再输入绕z轴转90度,程序还是按照x-y-z的顺序来,只是正好用户也是这样输入。
现在我們明确了两点:
- 物体的旋转是以世界坐标系为参考的。
- 物体旋转的顺序是确定的,和用户输入的旋转的顺序无关。
那么还是刚刚那两种情况:
操作A:
用户第一次输入: 绕Y轴转90度,第二次输入:绕X轴转90度。
实际程序运行:先繞X轴转90度,再绕Y轴转90度。
操作B:
用户第一次输入: 绕Y轴转90度,第二次输入:绕Z轴转90度。
实际程序运行:先繞Y轴转90度,再绕Z轴转90度。
现在发挥一下想象力,当物体绕Y轴转动90度以后,物体坐标系的X轴和世界坐标系的Z轴是不是变成了同一个轴?好的,那么这个时候,用户无论输入的是绕X轴转还是绕Z轴转,最终物体转动是不是都是绕着这个轴(世界Z轴/物体X轴)。上面的操作A和操作B的结果是一样的!
这就是Gimbal Lock,这并不是什么缺陷,陷阱,而是我們的思维方式是错误的,所以导致这个问题的出现。
参考资料:GimbalLock万向节锁与四元数旋转
万向节锁(Gimbal Lock)的理解的更多相关文章
- 使用四元数解决万向节锁(Gimbal Lock)问题
问题 使用四元数可以解决万向节锁的问题,但是我在实际使用中出现问题:我设计了一个程序,显示一个三维物体,用户可以输入绕zyx三个轴进行旋转的指令,物体进行相应的转动. 由于用户输入的是绕三个轴旋转的角 ...
- 万向节死锁 gimbal lock
,如下图一,把灰色箭头想象成是一架飞机,红,绿蓝三个圈看作是三个外围控制器,外圈带动所有里圈运动,里圈的运动不影响外圈. 1,首先,绕Y轴旋转(旋转绿圈),来确定前进的方向.这时红圈与蓝圈都跟着旋转. ...
- Gimbal Lock欧拉角死锁问题
技术背景 在前面几篇跟SETTLE约束算法相关的文章(1, 2, 3)中,都涉及到了大量的向量旋转的问题--通过一个旋转矩阵,给定三个空间上的欧拉角\(\alpha, \beta, \gamma\), ...
- Gimbal Lock
[Gimbal Lock] 万向锁源于欧拉角的是有序处理的.U3D中的序列为: y->x->z.当旋转y时,local坐标系与世界坐标系重合,所以y等于永远按惯性坐标旋转.当x旋转+/-9 ...
- 【转】锁(lock)知识及锁应用
sql server锁(lock)知识及锁应用转自:http://blog.csdn.net/huwei2003/article/details/4047191 关键词:锁提示,锁应用 提示:这里所摘 ...
- volatile和synchronized与lock的理解
volatile 特征: a:可见性:一个线程修改了某个共享变量的值,其他线程能够立马得知这个修改. b:禁止特定的处理器重排序. volatile的内存语义: 1.当写一个volatile变量的时候 ...
- Python3学习之路~9.3 GIL、线程锁之Lock\Rlock\信号量、Event
一 Python GIL(Global Interpreter Lock) 全局解释器锁 如果一个主机是单核,此时同时启动10个线程,由于CPU执行了上下文的切换,让我们宏观上看上去它们是并行的,但实 ...
- java里的锁总结(synchronized隐式锁、Lock显式锁、volatile、CAS)
一.介绍 首先, java 的锁分为两类: 第一类是 synchronized 同步关键字,这个关键字属于隐式的锁,是 jvm 层面实现,使用的时候看不见: 第二类是在 jdk5 后增加的 Lock ...
- java面试-公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解
一.公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解 公平锁:多个线程按照申请的顺序来获取锁. 非公平锁:多个线程获取锁的先后顺序与申请锁的顺序无关.[ReentrantLock 默认非公平.s ...
随机推荐
- SQLServer执行命令出现“目录无效的提示”
异常处理汇总-数据库系列 http://www.cnblogs.com/dunitian/p/4522990.html 一般都是清理垃圾清理过头了,把不该删的目录删了 网上说法: 问题描述: 1.s ...
- AI人工智能系列随笔
初探 AI人工智能系列随笔:syntaxnet 初探(1)
- ASP.NET Core 中文文档 第四章 MVC(4.2)控制器操作的路由
原文:Routing to Controller Actions 作者:Ryan Nowak.Rick Anderson 翻译:娄宇(Lyrics) 校对:何镇汐.姚阿勇(Dr.Yao) ASP.NE ...
- scala练习题1 基础知识
1, 在scala REPL中输入3. 然后按下tab键,有哪些方法可以被调用? 24个方法可以被调用, 8个基本类型: 基本的操作符, 等: 2,在scala REPL中,计算3的平方根,然 ...
- 无法访问org.springframework.core.NestedRuntimeException 找不到org.springframework.core.NestedRuntimeException的类文件
在学习springAOP时,出现如下异常: 无法访问org.springframework.core.NestedRuntimeException 找不到org.springframework.cor ...
- 编写一个通用的Makefile文件
1.1在这之前,我们需要了解程序的编译过程 a.预处理:检查语法错误,展开宏,包含头文件等 b.编译:*.c-->*.S c.汇编:*.S-->*.o d.链接:.o +库文件=*.exe ...
- mysql 大表拆分成csv导出
最近公司有一个几千万行的大表需要按照城市的id字段拆分成不同的csv文件. 写了一个自动化的shell脚本 在/home/hdh 下面 linux-xud0:/home/hdh # lltotal 1 ...
- 从myeclipse导入eclipse,不能识别为web项目(java项目转为web项目)
1.进入项目目录,找到.project文件,打开. 2.找到<natures>...</natures>代码段. 3.在第2步的代码段中加入如下标签内容并保存: ...
- fedora上部署ASP.NET——(卡带式电脑跑.NET WEB服务器)
andrew,20130601,guilin 本文记录在树莓派(fedora)上部署ASP.NET MVC2 的过程. 本文共分为六部分,分别是前置条件,Apache的安装,Mysql的安装,安装mo ...
- VS2012+EF6+Mysql配置心路历程
为了学习ORM,选择了EntityFramework,经历了三天两夜的煎熬,N多次错误,在群里高手的帮助下,终于成功,现在将我的心路历程记录下来,一是让自己有个记录,另外就是让其它人少走些弯路. 我的 ...