转自:https://www.cnblogs.com/psklf/p/5656938.html

严正声明:
作者:psklf
出处: https://www.cnblogs.com/psklf/p/5656938.html
欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任!

[TOC]

结论

我直接抛出结论:
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轴就指向同一个方向(它们相当于同一个轴了)。

看得懂吗?我是看不太懂~

我的理解

我们先来考虑一下,旋转到底是怎么个旋转法。

静态的情况很好理解,怎么旋转都不会有问题,万向节的问题是不会出现在静态的旋转过程中的。但是你想像一下动态的旋转,动态的旋转,这里会有两个坐标系,看清楚了,两个坐标系!

  1. 世界坐标系
  2. 物体坐标系

那么这两者是什么关系呢?

一开始,这两个坐标系是重合的,但是旋转开始以后,世界坐标系不会变化,物体坐标系随着旋转就发生变化了。

亲爱的读者,你们先想想,这两个坐标系的关系,你们觉得物体旋转是绕着那个坐标系旋转的?
你会说:

你刚刚不是说了嘛!是绕着物体的坐标系旋转的!

对,没有错,那么在物体旋转的时候,物体的坐标系是不是一直在变化呢?是的!那么我們在给他旋转的参数的时候考虑到这个问题了吗?没有!

就是说我给他的旋转的参数是基于一种假设:每一次旋转都是以物体的坐标系为参考来进行的。就是说我是希望它每一次旋转前,都能够将旋转参数在物体坐标系上进行计算。很简单,一架飞机,作为机长,每次旋转以后他跟着飞机旋转了,后面的旋转操作自然是基于新的物体坐标系来的。

但是实际上,程序解析我给的数据的时候,只是简单地将三个轴的旋转一个个的相乘,也就是说,总的来说还是在最开始的那个坐标系(也就是一直不动的世界坐标系)下面计算的。而且需要注意的是: 每一次进行计算的顺序是确定不变的! 这也是为什么有人会说万向节问题是因为旋转顺序导致的樂。
看一下在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 * zTransmultiMatrix(xTrans, yTrans, tempMatrix);multiMatrix(tempMatrix, zTrans, rotateTrans);

看懂了吗,物体最终在哪个位置是简单粗暴地将绕xyz三个旋转的矩阵连续相乘得到的,计算的顺序是x->y->z,那么比如用户先输入绕y轴转90度,再输入绕x轴转90度。其实程序执行的时候,还是会先将x轴的数据进行计算,再计算y轴的数据。但是如果用户先输入绕y轴转90度,再输入绕z轴转90度,程序还是按照x-y-z的顺序来,只是正好用户也是这样输入。

现在我們明确了两点:

  1. 物体的旋转是以世界坐标系为参考的。
  2. 物体旋转的顺序是确定的,和用户输入的旋转的顺序无关。

那么还是刚刚那两种情况:

操作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)的理解相关推荐

  1. 使用四元数解决万向节锁(Gimbal Lock)问题

    使用四元数解决万向节锁(Gimbal Lock)问题 参考文章: (1)使用四元数解决万向节锁(Gimbal Lock)问题 (2)https://www.cnblogs.com/psklf/p/56 ...

  2. 关于万向锁(Gimbal lock)问题的理解及解决

    1. Gimbal lock的理解 万向锁(Gimbal lock): 一旦选择±90°作为pitch角,就会导致第一次旋转和第三次旋转等价,整个旋转表示系统被限制在只能绕竖直轴旋转,丢失了一个表示维 ...

  3. 万向锁(Gimbal lock)问题的理解及解决

    万向锁(Gimbal lock)问题的理解及解决 万向锁(Gimbal lock): 一旦选择±90°作为pitch角,就会导致第一次旋转和第三次旋转等价,整个旋转表示系统被限制在只能绕竖直轴旋转,丢 ...

  4. 万向节死锁 gimbal lock

    万向节死锁 gimbal lock ,如下图一,把灰色箭头想象成是一架飞机,红,绿蓝三个圈看作是三个外围控制器,外圈带动所有里圈运动,里圈的运动不影响外圈. 1,首先,绕Y轴旋转(旋转绿圈),来确定前 ...

  5. 万向节死锁_万向节死锁 gimbal lock

    ,如下图一,把灰色箭头想象成是一架飞机,红,绿蓝三个圈看作是三个外围控制器,外圈带动所有里圈运动,里圈的运动不影响外圈. 1,首先,绕Y轴旋转(旋转绿圈),来确定前进的方向.这时红圈与蓝圈都跟着旋转. ...

  6. 如何快速解决Unity中万向节死锁(gimbal lock)的问题

    如何快速解决Unity中万向节死锁(gimbal lock)的问题 转载连接:https://www.jianshu.com/p/59acdd1c9db8 万向节死锁的根本问题是欧拉角(EulerAn ...

  7. 欧拉角表示旋转会出现的问题——万向锁(Gimbal Lock)

    本文用来总结万向锁问题.尽量写得非常简单,方便自己复习和后人理解,水平有限若有错误请指教. 一.旋转的表示 本文中矩阵计算的结果是在世界坐标系(称之为North East Down Frame NED ...

  8. 八分钟诠释什么是万向节死锁(Gimbal Lock)

  9. Unity中旋转方式的探究与对万向节死锁(Gimbal Lock)的理解

    Gimbal Lock Gimbal Lock的原理网上已经有很多资料,详细可以看介绍视频.视频讲到Gimbal Lock的时候提到x,y,z三个坐标轴是有从属关系(hierarchical syst ...

最新文章

  1. phpMyAdmin 数据库添加int类型的值时默认设为唯一主键的问题解决
  2. list mybatis批量保存_mybatis 批量将list数据插入到数据库的实现
  3. python树状节点 可拖拽_Python 的 heapq 模块源码分析
  4. LruCache:从网络加载图片缓存实例
  5. excel2010冻结行列
  6. [js] 举例说明js中什么是尾调用优化
  7. ssh 登录时,有的服务器很容易频繁断开连接,有的却几乎不会断开。
  8. 有了中文版MSDN2,何必又东奔西走去找资料
  9. 广东理工学院计算机考试大纲,广东理工学院2020年专插本《电工电子技术》考试大纲...
  10. ArcGIS入门 (一)
  11. 错误码 0x8007007b 解决
  12. RabbitMQ(一)
  13. Python之身份证号码的校验
  14. Mac系统常用软件总结
  15. NHibernate 联合查询,解决方法-通过自动转换成DataTable
  16. 【开源方案】PPT/PPTX转image图片
  17. 在浏览器中嵌入播放器
  18. KuPlay:社区运营会是下一个风口吗?
  19. 计蒜客T1005输出字符三角形
  20. android 启动图片 大小,ios 和安卓常用图标、启动图 尺寸

热门文章

  1. 他想做摩洛哥COC证书
  2. 「Java工具类」发现一个身份证地址解析出省市区的工具类
  3. 零拷贝( Zero-copy )
  4. UI自动化测试(二)浏览器操作及对元素的定位方法(xpath定位和css定位详解)...
  5. php排行榜代码,优化排行榜
  6. css 解决投影仪投影不清晰,投影仪不清晰要如何解决?
  7. C++随机数之线性同余发生器
  8. PTA 十进制转换二进制
  9. 电脑用电,电脑一天24小时多少度电 电脑一天用电量计算【图文】
  10. 玩游戏时计算机ram,计算机的32G RAM是否必要? 8G,16G,32G内存游戏,生产率测量比较...