四元数怎么实现旋转

2021-04-29 18:59发布

4条回答
tiu
2楼 · 2021-04-30 15:19

四元数又是什么呢?简单来说,四元数本质上是一种高阶复数(听不懂了吧。。。),是一个四维空间,相对于复数的二维空间。我们高中的时候应该都学过复数,一个复数由实部和虚部组成,即x = a + bi,i是虚数单位,如果你还记得的话应该知道i^2 = -1。而四元数其实和我们学到的这种是类似的,不同的是,它的虚部包含了三个虚数单位,i、j、k,即一个四元数可以表示为x = a + bi + cj + dk。那么,它和旋转为什么会有关系呢?

 

在Unity里,tranform组件有一个变量名为rotation,它的类型就是四元数。很多初学者会直接取rotation的x、y、z,认为它们分别对应了Transform面板里R的各个分量。当然很快我们就会发现这是完全不对的。实际上,四元数的x、y、z和R的那三个值从直观上来讲没什么关系,当然会存在一个表达式可以转换,在后面会讲。

 

大家应该和我一样都有很多疑问,既然已经存在了这两种旋转表示方式,为什么还要使用四元数这种听起来很难懂的东西呢?我们先要了解这三种旋转方式的优缺点:

 

  • 矩阵旋转

    • 优点:

      • 旋转轴可以是任意向量;

    • 缺点:

      • 旋转其实只需要知道一个向量+一个角度,一共4个值的信息,但矩阵法却使用了16个元素;

      • 而且在做乘法操作时也会增加计算量,造成了空间和时间上的一些浪费;

  • 欧拉旋转

    • 优点:

      • 很容易理解,形象直观;

      • 表示更方便,只需要3个值(分别对应x、y、z轴的旋转角度);但按我的理解,它还是转换到了3个3*3的矩阵做变换,效率不如四元数;

    • 缺点:

      • 之前提到过这种方法是要按照一个固定的坐标轴的顺序旋转的,因此不同的顺序会造成不同的结果;

      • 会造成万向节锁(Gimbal Lock)的现象。这种现象的发生就是由于上述固定坐标轴旋转顺序造成的。理论上,欧拉旋转可以靠这种顺序让一个物体指到任何一个想要的方向,但如果在旋转中不幸让某些坐标轴重合了就会发生万向节锁,这时就会丢失一个方向上的旋转能力,也就是说在这种状态下我们无论怎么旋转(当然还是要原先的顺序)都不可能得到某些想要的旋转效果,除非我们打破原先的旋转顺序或者同时旋转3个坐标轴。这里有个视频可以直观的理解下;

      • 由于万向节锁的存在,欧拉旋转无法实现球面平滑插值;

  • 四元数旋转

    • 优点:

      • 可以避免万向节锁现象;

      • 只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高;

      • 可以提供平滑插值;

    • 缺点:

      • 比欧拉旋转稍微复杂了一点点,因为多了一个维度;

      • 理解更困难,不直观;


首先,单位四元数才能表示旋转,比如一个单位四元数可以写为



表示将一个向量绕(x,y,z)轴旋转 theta/2 度。

只要将一个向量看成四元数,然后乘以这个四元数即可。比如一个向量(w,x,y,z)为(0,1,2,3),
那么利用四元数的乘法,用(0,1,2,3)*q即可

722
4楼 · 2021-05-10 14:13

哈密尔顿

为了纪念四元数的发明者哈密尔顿,爱尔兰于1943年11月15日发行了下面这张邮票: 

哈密尔顿简直是个天才,哈密尔顿从小到进入大学之前没有进过学校读书,他的教育是靠叔父传授以及自学。他找到了法国数学家克莱罗(Clairaut)写的《代数基础》一书,很快就学会了代数,然后看牛顿写的《数理原理》。在16岁时就读法国著名数学家和天文学家拉普拉斯(Laplace)五册的《天体力学》,他发现拉普拉斯关于力的平行四边形法则的证明的错误. 

四元数的概念是由爱尔兰数学家Sir William Rowan Hamilton发明的(1843年,都柏林)。Hamilton当时正和他的妻子前往爱尔兰皇家研究院,当他从Brougham桥通过皇家运河时,他领悟到了一个激动人心的东西,并立刻把它刻在桥的一个石头上:

i2=j2=k2=ijk=−1

i2=j2=k2=ijk=−1


 

关于哈密尔顿的介绍可以看这篇博客: 邮票上的数学家(10)哈密尔顿(爱尔兰)

四元数旋转推导过程

1.基本概念

(1) 四元数的一般形式如下:q=q0+q1i+q2j+q3kq=q0+q1i+q2j+q3k 

(2) 单位四元数:满足四元数的模为1,即q02+q12+q22+q32=1q02+q12+q22+q32=1 

(3) 四元数的三角形式:q=cosθ2+u⃗ sinθ2q=cosθ2+u→sinθ2 

(4)共轭四元数:q∗=q0−q1i−q2j−q3kq∗=q0−q1i−q2j−q3k 

(5) 纯四元数:q=q1i+q2j+q3kq=q1i+q2j+q3k 

(6)四元数与空间旋转:

Rq(p)=qpq−1

Rq(p)=qpq−1


其中: 

qq:单位四元数 

q−1q−1:四元数的逆,对于单位四元数, q∗=q−1q∗=q−1 

pp:纯四元数 

Rq(p):也是一个纯四元数Rq(p):也是一个纯四元数

2. 欧拉角的万向锁问题

先看一个简单的欧拉旋转,如下图所示:欧拉旋转需要先确定旋转顺序,我们可以定义X-Y-Z的顺序(总共有12种旋转顺序),那么什么是万向锁呢,我们可以用手机在桌子上进行旋转,以手机的正面为xy平面,以手机的厚度的方向作为z轴,我们先绕x转一个角度,然后再绕y轴旋转90度,我们会发现一个问题,当我们再绕z轴旋转一个角度,效果等同于我开始绕x轴旋转另外一个角度,再绕y轴旋转90度就行了. 

 

我们的欧拉旋转只能表示二维空间了,这是解我们的微分方程会出现退化现象,造成我们的微分方程无法解的情况。这样说似乎还是比较模糊,那么我们举一个例子: 



如图所示:XwYwZwXwYwZw是世界坐标系,XiYiZiXiYiZi是机体坐标系,我们先绕XiXi轴旋转30∘30∘,再绕YiYi旋转90∘90∘,如下图所示: 

 

此时我们的XwXw和ZiZi在同一直线上,最后我们再绕ZiZi旋转40∘40∘,如下图所示: 

 

我们会发现一个问题,无论我们怎么旋转,我们的坐标都是(30,90,z),也就是绕z轴的旋转角度我们无法衡量的,这也就是我们的万向锁问题。


3. 四元数推导

复数旋转

首先我们看一个复数p=a+bip=a+bi在复平面的表示: 

现在我们将它旋转角度θθ,先定义另外一个复数q=cosθ+isinθq=cosθ+isinθ,我们发现,复数的乘法表示了一种旋转: 

qp=(acosθ−bsinθ)+i(asinθ+bcosθ)

qp=(acosθ−bsinθ)+i(asinθ+bcosθ)


这个复数恰好就是 pp旋转θθ角度后的值: 


三维复数旋转

我们看到了二维复数乘法可以表示旋转,那么三维空间呢。按照举一反三的思想,我们会想到再增加一个虚数作为第三个维度,这个就要涉及到我们的向量的叉乘,如下图所示: 

 

向量叉乘的结果是两个向量构成平面的垂直向量,那么我们定义两个个三维的复数: 

z1=a1+b1i+c1jz2=a2+b2i+c2j

z1=a1+b1i+c1jz2=a2+b2i+c2j


其中 i2=j2=−1i2=j2=−1,我们类似的进行复数的乘法,得到: 

z1z2=(a1a2−b1b2−c1c2)+(a1b2+a2b1)i+(a1c2+a2c1)j+b1c2ij+b2c1ji

z1z2=(a1a2−b1b2−c1c2)+(a1b2+a2b1)i+(a1c2+a2c1)j+b1c2ij+b2c1ji


我们会发现,如果没有 ij和jiij和ji这两项,我们三维的复数旋转也就没问题,那该如何处理呢?

四元数旋转

哈密尔顿引入四维的四元数:q=q0+q1i+q2j+q3k,其中i2=j2=k2=−1q=q0+q1i+q2j+q3k,其中i2=j2=k2=−1,根据向量的叉乘可以定义下列一些关系: 

 

 

 

 

可以得到下列关系: 

ij=−ji=kjk=−kj=iki=−ik=ji2=j2=k2=ijk=−1

ij=−ji=kjk=−kj=iki=−ik=ji2=j2=k2=ijk=−1


为了方便理解,我们将四元数写成向量的形式: q=[s,v⃗ ]q=[s,v→],我们可以理解为 ss为实部,向量v⃗ v→表示的就是三维空间,下面我们看一下四元数的乘法: 

qa=[sa,a⃗ ]qb=[sb,b⃗ ]qaqb=[sasb−a⃗ ⋅b⃗ ,sab⃗ +sba⃗ +a⃗ ×b⃗ ]

qa=[sa,a→]qb=[sb,b→]qaqb=[sasb−a→⋅b→,sab→+sba→+a→×b→]


由于我们研究的是三维空间,因此我们可以令 qaqa为一个纯四元数,即 qa=[0,a⃗ ]qa=[0,a→].则可以得到:

qaqb=[−a⃗ ⋅b⃗ ,sba⃗ +a⃗ ×b⃗ ]

qaqb=[−a→⋅b→,sba→+a→×b→]


从上面可以看到,一个普通的四元数是无法将三维空间映射到三维空间的,我们令向量点乘的部分为零,此时,一个纯四元数就可以旋转为另一个纯四元数.为了表现出旋转,这里我们用四元数的三角表示方式: qb=[cosθ,sinθb⃗ ]qb=[cosθ,sinθb→],令 a⃗ ⋅b⃗ =0a→⋅b→=0,则有: 

qaqb=[0,a⃗ cosθ+a⃗ ×b⃗ sinθ]

qaqb=[0,a→cosθ+a→×b→sinθ]


我们没有对向量 b⃗ b→做任何限制,下面来用一个例子说明应当对向量 b⃗ b→做什么限制. 

令 p=[0,2i],q=[2√2,2√2b⃗ ]p=[0,2i],q=[22,22b→],考虑到 a⃗ ⋅b⃗ =0a→⋅b→=0,令 b⃗ =|b⃗ |kb→=|b→|k,则将 pp旋转45∘45∘后得到: 

p′=qp=[0,2–√|b⃗ |i+2–√|b⃗ |j]

p′=qp=[0,2|b→|i+2|b→|j]


旋转之前,纯四元数 pp的模长为|p|=2|p|=2,旋转过后,纯四元数 p′p′的模长 |p′|=2|b⃗ ||p′|=2|b→|,所以我们要给旋转四元数又加上一个约束:四元数 qq的模长为1,即qq是一个单位四元数.

但是上面的旋转是有缺点的,因为其限制了我们的旋转轴和需要被旋转的四元数必须是垂直的(a⃗ ⋅b⃗ =0a→⋅b→=0),而不能达到任意的旋转.这时,聪明的哈密尔顿发现,一个四元数会把一个纯四元数拉到四维空间,但它的共轭又会把这个四维的空间拉回到三维空间.我们以一个简单的例子来说明这个问题: 

p=[0,2i],q=[fracsqrt22,fracsqrt66(i+j+k)],则q∗=[fracsqrt22,−fracsqrt66(i+j+k)]

p=[0,2i],q=[fracsqrt22,fracsqrt66(i+j+k)],则q∗=[fracsqrt22,−fracsqrt66(i+j+k)]


旋转之后的四元数 Rq(p)Rq(p): 

Rq(p)=[0,2j]

Rq(p)=[0,2j]


这里需要注意的一点是,因为经过两次的旋转,所以旋转的角度是 2θ2θ,这就是为什么我们常常看到的旋转四元数是一下形式: 

q=cosθ2+u⃗ sinθ2,其中|u⃗ |=1

q=cosθ2+u→sinθ2,其中|u→|=1

Quaternions – Ken Shoemake




彭彭彭
5楼 · 2021-05-13 17:21

对于一个轴已经固定的轮子来说,只要一元数字来表示旋转,就是旋转的角度;
对于空间的物体,用三元(维)数字(就是三维立体坐标,或者向量)可以描述他旋转的轴(或方向),一元(维)数可以表示旋转的角度

相关问题推荐

  • 回答 5

    第一种方法:通过点击场景文件打开Unity游戏工程找到Unity游戏工程所在的目录,我这里的工程放在在E盘根路径的Unity_workspace文件夹中。注意:unity软件不支持中文路径,所以不要把工程放在中文文件夹下。我们在这里就打开New Unity Project 4工程,进入到Ne...

  • 回答 13
    已采纳

    如果是学习研究的话,当然是体验官方的最新版本。要是项目开发的话,还是要选择长期稳定版本,也就是大版本的LTS。比如2017.4或者是2018.4都是LTS版本,至于后面的小版本可以去看下更新的内容来做选择吧!...

  • 回答 9

    unity3D是实时3D互动内容创作和运营平台。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助Unity将创意变成现实。Unity平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC...

  • 回答 11

    1、Unity3D:如果你需要开发大型游戏,或需要开发3D游戏的,请选这个。2、Cocos2D-x:如果你开发的是中小型游戏,对安装包大小比较在意的,请选这个。3、Andengine、Cocos2D-iPhone:如果你只为开发单平台游戏,又非常在意速度和安装包大小,请选这个。最后。...

  • 回答 11

    首先在场景中调整好你要观看的视角选择摄像机,按下Ctrl+Shift+F或者菜单栏->GameObject->Align with view在不行的话,可以调整摄像机的Position 和 Rotation

  • 回答 5

    将MeshRender组件移除即可:

  • 回答 9

    1.在Asset store里选择一个skybox。 2.从素材库中选择一个人物角色,也可以自己建模或者在其他软件中做好再导进来。 3.想好角色如何运动,然后用自己比较熟悉的语言编写来作展示,这段代码可以实现当你按下键盘上的A/D/S/W的按键时,角色会向前后左右四个方向的...

  • 回答 17

    还是要学好编程基础呀如果你觉得编程很苦难 不一定要从c#开始学  学学js flash as等等  有个梯度就好多了如果要用好unity  不会编程那是不行的  学习的过程中都有个头疼的过程  记住  头越痛  代表你要接受的东西越多  坚持 你的大脑在和知识兼容中:D...

  • 回答 4

    xcel 表的操作少不了要引入第三方库,首先我们需要引入 Excel.dll 和 ICSharpCode.SharpZipLib.dll,这两个类库在网上都能找到;然后我们还需要引入 System.Data.dll,这个类库在 Unity3D 的安装路径下的 Editor\Data\Mono\lib\mono\unity 文件夹下能找到...

  • 回答 1

    需要添加如下引用: System.Configuration System.Data System.EnterpriseServices System.Security System.XML using UnityEngine; using System.Collections; using System;  using  System.Data;  using System.Data...

  • 物理引擎问题2021-06-15 17:35
    回答 4

    物理引擎则使用动量、扭矩等用高等数学手段来模拟真实物体,这将得到更真实的效果且使我们的编码更加容易。

  • 回答 1

    不能这样表述,三维通常是立体的空间,二维则是平面的。数学中通常是Oxyz表示空间直角坐标系,Oxy表示表示的是平面直角坐标系,你可以说空间直角坐标系中去掉Z轴可以转换为二维,因为去掉X或Y轴都能转换为二维。...

  • 回答 2

    GameObject.renderer.enabled//是控制一个物体是否在屏幕上渲染或显示 而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的GameObject.Destroy()//表示移除物体或物体上的组件 代表销毁该物体 实际上该物体的内存并没有立即释放,而是等到这...

  • Canvas三种渲染模式2021-04-29 19:50
    回答 10

    一:Overlay—覆盖模式类似于手机贴膜,所有UI都会显示在场景中2D,3D物体的上层在同一个Canvas下可以调整Canvas子物体的先后顺序,层级面板中越靠上则先被渲染多个Canvas下可以调整Canvas组件的Sort Order属性调整渲染顺序,数值越小的画布越先被渲染:Camer...

  • Unity引擎2021-04-29 19:47
    回答 4

    不得不说,Unity3d是个解放生产力的游戏引擎,自带了各种编辑器,可以进行一系列的可视化操作。需要注意的是,unity3d适合FPS游戏,物理游戏等中小型的游戏,并不太适合MMO开发。unity3d难学吗?如何学习unity3d呢?在学习之前又应该了解哪些内容呢?代码写不...

  • 回答 3

    不是人工检查的,如果你的问题里面有敏感关键字,是发不出去的,现在国内所有的网站在发布文章时都要进行检查的,所以你在发之前先检查一下看问题里面是否有违禁词语。

没有解决我的问题,去提问