[自学记录06|*Animation]四元数、死锁与方位插值

news2024/11/29 20:33:58

一、前言

还记得在很久以前不知道什么时候,看到过一个TA的面经,里面提到了四元数和万向锁,当时自己也查了一些资料,但是看的也是云里雾里,恰巧这两天学校的动画原理课讲到了这,打算整理一下做个小结。

二、方位的表达方式

方位的表达方式有很多种,它们各有优缺点,所以每种方式都不能算是很完美,包括四元数也是,但四元数的提出是为了解决方位的插值问题,所以只需要它有这个优点就够了。我们本篇主要探讨的问题也正是方位的插值问题。

以下是常用的方位表示形式

矩阵形式

Fixed Angle形式(参考世界坐标系)

Euler Angle形式(参考局部坐标系)

角度位移形式(Angle and Axis)

四元数形式

1.矩阵形式

熟悉图形变换的我们知道,用矩阵可以表示旋转,并且旋转矩阵一定是正交矩阵,所以旋转矩阵有一个很好的性质就是自身的逆等于自身的转置。那么矩阵自然也可以用在方位的表达中。但如果用矩阵的方位表达形式进行插值呢?下图举一个例子为绕Z轴的旋转矩阵,假设我们从θ=90°旋转到θ=-90°。

那么得到初始状态的方位矩阵和最终状态的方位矩阵如图所示,当进行中间插值时我们发现出现了问题。得到的插值结果明显不是一个旋转矩阵,也失去了旋转矩阵特有的正交性。所以对于关键帧的方位插值我们显然不能直接使用矩阵形式。

2.Fixed Angle形式(参考世界坐标系)

Fixed Angle其实就是以世界坐标为参考系下进行的方位表达,世界坐标系静止不动由此得到不同方位唯一的表示方法。Fixed Angle进行方位表达时按照固定顺序围绕世界坐标系的坐标轴旋转3次,最常用的为x,y,z顺序(θx,θy,θz)。在插值时需要对三个角度分别进行插值。当然,无论什么形式,我们最终都是要转换成矩阵形式在计算机中计算的,Fixed Angle当然也不例外。

接下来我们看一个例子,看看Fixed Angle能不能完美的实现方位的插值。

如上图关键帧1和关键帧2,我们选取关键帧1为初始状态,关键帧2为终止状态,那么我们的理想情况是进行插值之后,关键帧1可以平滑的过度到关键帧2的姿态。那么实际情况是不是这样呢?我们取中间帧看一下就知道了。

可以看到取中间帧时,物体在三个方向上的旋转角度分量分别是45°,67.5°,45°。也就是说在插值的过程中物体并不是仅仅由绕x轴旋转就从关键帧1过度到关键帧2的,它总会在中间 “” 一下。这种现象被称为“死锁”或“万向锁”。之所以被称为万向锁,是因为在万向节装置中,当两个旋转轴重合时,万向节会损失一个方向的自由度,如下图。

对于上面的例子,Fixed Angle解决死锁的方案是关键帧1(0, 90, 0)表示为(90, 90, 90),这样经过插值之后中间帧就是(90, 67.5, 90),但显然这样做起来很麻烦,并且无法保证方位表达的唯一性。

3.Euler Angle形式(参考局部坐标系)

Euler Angle,也就是欧拉角。本质上和Fixed Angle其实是一个东西,只不过Fixd Angle是以世界坐标为参考系,而欧拉角是以物体自身为参考系。

简单地说,就是将物体局部坐标系与世界坐标系重合;世界坐标系静止不动,局部坐标系与物体绑定,然后以局部坐标系为参考,对物体进行旋转(每次旋转时,局部坐标系随物体一起旋转)。

既然说了Fixed Angle和Euler Angle本质上是一样的只是参考系不同,那么我们就完全可以把它们之间互相转换,它们完全是逆向等价的。

4.角度位移形式(Angle and Axis)  

欧拉旋转定理

某个物体的两个空间朝向之间,存在唯一的、简单稳定的、绕某一空间轴的旋转变换。

角度:θ , 旋转轴(单位向量):(Ax, Ay, Az)

这很好想,我们知道旋转肯定会产生一个圆环面,那么面就一定有一个法向量,也就是旋转轴对于的方向。 

Angle and Axis对方位的表示是使用一个旋转轴(单位向量)和一个角度值来表示物体的朝向,如(θ, Ax, Ay, Az)。插值方法则是对旋转轴和旋转角度分别进行插值计算

当然了,和其它方法一样,Angle and Axis仍然需要把插值后的结果转换成矩阵形式在计算机里表示。角度位移形式转换为矩阵的公式如下。

同样的,我们举一个例子,上图所示A1单位向量为初始状态,现在要通过变换把它变为A2单位向量的最终状态。根据欧拉旋转定理,我们可以求出唯一旋转轴B,只需要A1xA2也就是叉乘就可以了,知道了旋转角度,旋转轴,单位向量,我们自然可以对旋转的角度Φ(由arccos得到)进行插值。同时也就可以对单位向量自身的旋转θ进行插值,如上图所示。

显然Angle and Axis不会产生死锁问题。但有一个问题就是Angle and Axis不适合级联表示。比如由初始状态,首先旋转(θ1, Ax1, Ay1, Az1),然后旋转(θ2, Ax2, Ay2, Az2),我们很难知道它相当于由初始状态旋转了多少。

三、四元数

1.用复数表示二维旋转

学过线性代数的我们应该很容易就能写出这个旋转的方程表达式。可以很容易的看到在二维平面内逆时针旋转θ,x和y对应的系数关系。 

而如果将xy平面转为复数的二维平面,我们就可以把旋转表示成为两个复数的乘法,如上图所示。这时我们发现,复数乘法结果得到的实部就是旋转后的x坐标x',得到的虚部就是旋转后的y坐标y'。 于是我们发现,我们完全可以用复数表示二维平面内的旋转。

将旋转角度θ表示为复数形式:cosθ+sinθi

将二维平面上的点表示为复数形式:x+yi

二者相乘后的结果表示旋转后的点坐标。实部为x坐标,虚部为y坐标。

2.四元数基本概念

四元数顾名思义就是由一个实部和三个虚部构成的。

例如四元数 (a, b, c, d) = a + bi + cj + dk

(1)加减法

加减法遵循复数,对应实部,虚部相加减的规则。 

(2)乘法

乘法满足分配律,但不满足交换律。 上图右为i,j,k对应的乘积结果表。

(3)点乘

四元数的点乘可以直接当成四维向量的点乘,对应位相乘再加和即可。

(4)其它基本概念 

3.四元数表示三维空间旋转 

那么如何把四元数对应到三维空间的旋转呢

现在假设已知:

三维空间中一点v=(vx,vy,vz)绕单位轴向量u=(ux,uy,uz)旋转θ度。

我们需要先对点和旋转角度进行处理,把它们转化位四元数。

将点v转化为四元数:p=(0, vx,vy,vz),

将旋转参数转化为单位四元数q

那么计算公式:

最后提取旋转变换的结果:p的实部为0,p的虚部为旋转后的结果。

总结:

总的来说,单位四元数相当于四维空间中的一个单位球体。它上面的每一个点定义了三维空间中的一个旋转变换。

4.四元数和其他形式的互相转化

(1)四元数转为矩阵

(2)Fixed Angle转为四元数

(3)四元数转为Fixed Angle 

5.四元数的优点 

(1)结合律表示级联变换

先对p进行q1变换,再进行q2变换,等价于把q1q2合起来一起做变换如上图所示。 

(2)适合插值

对于三维空间中的两个方位,首先,将它们表示为四元数形式:

q1= (qx1 , qy1 , qz1 , qw1)

q2= (qx2 , qy2 , qz2 , qw2)

然后,对这两个四元数进行插值即可。

四、四元数插值需要考虑的问题

1.插值点选取

对于上图所示的情况,对单位向量θ,旋转(θAx,  Ay,  Az) 和 对单位向量-θ旋转l (-θ, -Ax, -Ay, -Az)表示的方位是相同的。并且,两个单位四元数q-q,它们也表示同一个旋转方位。

证明如下:

2.线性插值问题 

对于下图插值公式

表示旋转的四元数必须是单位长度的: |q|=1 

其次,插值后的四元数不是单位长度的,需要对插值结果进行归一化。如下图所示

3.球面线性插值 

但仍然有问题,我们线性插值得到的结果经过归一化映射到球面上之后我们会发现,角度的变化其实并不是均匀的,显然我们不能对最终的值直接进行线性插值,而是要对角度进行球面线性插值,经过推导,我们可以得到如下图的球面线性插值公式。

 球面线性插值的特性

4.Bezier球面线性插值

对于多个四元数方位的过渡动画,球面线性插值存在一阶不连续问题。也就是方位过度形成的曲线并不连续,或者说并不平滑。这个问题我们显然很熟悉了,我们完全可以用Bezier曲线去进行平滑的过度。

我们需要根据给定的一系列四元数,在四维球面上构建分段三次Bezier样条线,沿着样条线进行四元数插值即可。


五、结语 

本文从比较High Level的层面上总结了一下各种表达方位的方式,涉及介绍较多,公式推导较少,关于一些详细的公式推导可以参考其它文章,有很多大佬写了很多非常好的推导过程可以参考,有兴趣的朋友可以自行学习。

三维旋转:欧拉角、四元数、旋转矩阵、轴角之间的转换 - 知乎 (zhihu.com)【Unity编程】欧拉角与万向节死锁(图文版)-CSDN博客


在学习GAMES101的时候,我曾记得闫令琪老师说过的一句话,我们学东西分为Why,What,How这么几个步骤,How这个步骤往往是花费时间最多的,但是往往其实是最不重要的。我同样觉得,我们着重学习的应该是这些提出这些想法的创意和解决问题的思路,而不单单是公式的推导,当然并不是说推导不重要,而是我常常在想,如果把学完的知识全部忘掉,我应该剩下什么,我觉得那就是最重要的东西,对我而言,那就是解决问题思考问题的能力和对未知的好奇心。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1095998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux学习笔记】 - 项目自动化工具make/Makefile的使用

一、背景知识 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中。makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需…

芯片学习记录SN74AHC1G14DBV

SN74AHC1G14DBV 芯片介绍 SN74AHC1G14器件是单个逆变器门。该器件执行布尔函数Y /A.The器件作为独立的逆变器门发挥作用,但由于施密特作用,门可能对正(VT)和负(VT−)信号具有不同的输入阈值电平。 引脚信…

07测试Maven中依赖的范围,依赖的传递原则,依赖排除的配置

依赖的特性 scope标签在dependencies/dependency标签内,可选值有compile(默认值),test,provided,system,runtime,import compile:在项目实际运行时真正要用到的jar包都是以compile的范围进行依赖 ,比如第三方框架SSM所需的jar包test:测试过程中使用的j…

大数据基础技能入门指南

本文介绍了数据工作中数据基础和复杂数据查询两个基础技能。 背景 当下,不管是业务升级迭代项目,还是体验优化项目,对于数据的需求都越来越大。数据需求主要集中在以下几个方面: 项目数据看板搭建:特别是一些AB实验的看…

【算法练习Day20】修剪二叉搜索树将有序数组转换为二叉搜索树把二叉搜索树转换为累加树

​📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:练题 🎯长路漫漫浩浩,万事皆有期待 文章目录 修剪二叉搜索树将有序数组转…

Grade 5 Math

数形结合 5 2 3 https://download.csdn.net/download/spencer_tseng/88431286

深入理解 Java 中的 synchronized 关键字

引入多线程的重要性和挑战 可以参考另一篇文章 https://blog.csdn.net/qq_41956309/article/details/133717408 JMM(Java Memory Model,Java 内存模型) 什么是JMM JMM(Java Memory Model,Java 内存模型&#xff09…

怎么在抖音上引流?分享五个抖音引流推广必备的几个方法

大家好,我是 小刘今天为大家分享的是抖音引流知识分享,今天咱们聊一些干货知识,绝对会让你们有一个重新的认知。抖音的流量大,是毋庸置疑的,抖音也是最早一批短视频平台。抖音于2017年上线,一开始主要是通过…

Golang学习记录:基础知识篇(一)

Golang学习:基础知识篇(一) 前言什么是Golang?Go语言的基础语法语言结构基础语法数据类型基础使用 前言 很久之前就想学Go语言了,但是一直有其他东西要学,因为我学的是Java嘛,所以后面学的东西…

配置VScode开发环境-CUDA编程

如果觉得本篇文章对您的学习起到帮助作用,请 点赞 关注 评论 ,留下您的足迹💪💪💪 本文主要介绍VScode下的CUDA编程配置,因此记录以备日后查看,同时,如果能够帮助到更多人&#xf…

操作系统导论-第四章作业(待更)

一、进程 进程就是运行中的程序,程序本身是没有生命周期的,它只是存储在磁盘上的一些指令(或者一些静态数据),操作系统将这些指令和数据加载到内存中,使其运行起来。 1.1 虚拟化CPU技术 根据我们平时使用…

基于Java的共享充电宝管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

AI时代助力程序员与项目经理的双翼飞翔:从开发到成长的秘诀

❤️作者主页:小虚竹 ❤️作者简介:大家好,我是小虚竹。2022年度博客之星评选TOP 10🏆,Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作…

企业网盘中支持在线编辑的有哪些选项?

企业网盘作为现代企业不可或缺的工具之一,为企业提供了便捷的文件存储和共享功能。而其中支持在线编辑的解决方案更是减少了对额外软件的依赖,使团队成员可以直接在浏览器中进行实时协作。 什么是在线编辑? 在线编辑是指用户无需下载文件&a…

3D 生成重建008-zero123让扩散模型了解空间信息zero-shot 单图生3d

3D 生成重建008-zero123让扩散模型了解空间信息zero-shot 单图生3d 文章目录 00 论文工作1 论文方法1.1 条件生成微调1.2 维护3d表示 2 效果 0 0 论文工作 之前分享的工作主要尝试是从一个pre-trained 文生图的diffusion模型中去蒸馏知识,从而去维护一个3d的表示…

数据结构上机实验——栈和队列的实现、栈和队列的应用、进制转换、约瑟夫环问题

文章目录 栈和队列上机实验1.要求2.栈的实现(以顺序栈为例)3.队列的实现(以顺序队列为例)4.利用栈实现进制转换5.利用队列解决约瑟夫环问题6.全部源码Stack.hQueue.htest.cpp 栈和队列上机实验 1.要求 1.利用栈的基本操作实现将任…

docker-compose部署elk(8.9.0)并开启ssl认证

docker部署elk并开启ssl认证 docker-compose部署elk部署所需yml文件 —— docker-compose-elk.yml部署配置elasticsearch和kibana并开启ssl配置基础数据认证配置elasticsearch和kibana开启https访问 配置logstash创建springboot项目进行测试kibana创建视图,查询日志…

李宏毅生成式AI课程笔记(持续更新

01 ChatGPT在做的事情 02 预训练(Pre-train) ChatGPT G-Generative P-Pre-trained T-Transformer GPT3 ----> InstructGPT(经过预训练的GPT3) 生成式学习的两种策略 我们在使用ChatGPT的时候会注意到,网站上…

2023/10/15

文章目录 1.uniapp之Vue2升Vue3值得注意的几点1.1 页面生命周期的使用1.2 引入资源的方式 2. 浏览器本地存储之Cookie和webStorage3. CSS变量 var()的用法4. CSS之实现线性渐变背景5. 图片无法和文字对齐的正确解决方案6. 使用正则处理接口返回的富文本内的图片7. transition实…

Java练习题-获取数组元素最大值

✅作者简介:CSDN内容合伙人、阿里云专家博主、51CTO专家博主、新星计划第三季python赛道Top1🏆 📃个人主页:hacker707的csdn博客 🔥系列专栏:Java练习题 💬个人格言:不断的翻越一座又…