3D数学基础--3D中的方位与角位移(2)

2024-05-09 07:32

本文主要是介绍3D数学基础--3D中的方位与角位移(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:3D中讨论的四元数都是单位四元数

四元数记法

上一章节讲了用三个数表达3D方位一定会有万向锁这样的问题,它涉及到一些非常高级的数学概念,如“簇”。而四元数通过使用四个数来表达方位,从而可以避免这些问题,下面先来看看它的记法:
这里写图片描述
注:w:类似复数实部,v:虚数。

四元数的数学渊源

四元数其实是由数学里的复数引申而来的,首先来简单说下什么是复数?复数=实数+虚数,它扩展了如对一个负数开平方根的问题。下面来看看复数的定义:
这里写图片描述
复数集存在于一个2D平面上,这个平面有两个轴:实轴(x)和虚轴(y)。这样,就能将复数(x,y)解释为一个2D向量,好的,现在我们可以这样通俗的理解,复数=向量。下面再来看看用复数怎么表达平面中的旋转:
这里写图片描述
从上面可以看出引入复数q和用2×2旋转矩阵达到的效果是一样的,目前为止,我们已经将复数和前面学习的知识联系起来了,而现在我们讲的只是2D平面,那么怎么把复数扩展到3D中呢?它又怎么和四元数联系起来呢?下面我们来看下书上关于它的一个典故:
这里写图片描述
四元数扩展复数系统,它使用了三个虚部i, j, k。它们关系如下:
这里写图片描述

四元数几何意义

欧拉证明了一个旋转序列等价于单个旋转,因此,3D中的任意角位移都能表示为绕单一轴的单一旋转。我们记角度为θ,旋转轴为n(向量),那么绕n轴旋转θ角度,可用复数形式表示为(θ,n),那么其对应的四元数表示为:
这里写图片描述
注释:我们可以近似把一个四元数理解为一个旋转矩阵或角位移。

四元数的一般数学运算

  • 负四元数:
    这里写图片描述
    q和-q代表的角位移是相同的,其实就是相当于将θ加上360°的倍数,对方位没影响。所以负四元数只是在数学上把它的四个分量都变负了,但几何上它们是等效的。即3D中任意角位移都有两种不同的四元数表示方法,它们互相为负。

  • 没有角位移的单位四元数:
    这里写图片描述
    注:代入上面四元数的四个值公式即可得出。

  • 四元数的模:
    这里写图片描述
    而我们3D数学里只使用模为1的四元数(单位四元数),即前面列出的四元数的四个值公式的四元数。

  • 四元数的共轭和逆:
    数学定义我就直接拿书上讲的,如下:
    这里写图片描述
    由于我们只使用单位四元数,所以四元数的逆和共轭是相等的。那么,它们有什么几何意义呢?共轭其实就是把四元数的向量部分变负,所以一个四元数的共轭就是代表一个相反的角位移。
    注释:其实我们还可以保持四元数向量部分不变,而让角度部分变负,同样能代表一个相反的角位移。但为了和复数的共轭概念一致,所以四元数的共轭用上面那种形式定义。

  • 四元数的叉乘:
    四元数的叉乘不用乘号,而且行与列的形式也没什么区别,下面是四元数乘法的标准定义:
    这里写图片描述
    但我们实际不用这种形式,具体原因这里不打算详细讲解,大体是因为这个形式会导致多个变换连接成一个后,变换顺序会颠倒。以后会把这些数学计算封装成一个四元数的类,对于里面的数据我们不再需要管。之所以用叉乘就是执行旋转变换时需要用到它。

  • 四元数“差”:
    四元数的差是指一个方位到另一个方位的角位移。我们用四元数表示是:从a旋转到b的角位移d等于:这里写图片描述

  • 四元数点乘:
    四元数的点乘和向量的点乘很类似,几何原理也类似,a·b的绝对值越大,a和b代表的角位移越“相似”。公式如下:
    这里写图片描述

四元数的高级数学运算

  • 四元数的对数,指数和标量乘运算:
    虽然这些运算我们很少直接使用它们,但它们是某些重要四元数运算的基础,下面来分别看看它们的定义:
    这里写图片描述

    这里写图片描述

    这里写图片描述

  • 四元数求幂:
    注意它与上面指数运算的区别,指数运算底数是e,而这里是四元数做底数。所以,指数运算只要一个参数–四元数,而四元数求幂要两个参数–四元数和指数。公式如下:
    这里写图片描述
    再来说说它能做什么用?假设,四元数q代表一个角位移,现在想要得到代表1/3这个角位移的四元数,其实就是等于这个四元数的1/3次幂。即四元数求幂它可以从角位移中抽取一部分。

    四元数求幂代码实例:

//四元数输入和输出float w, x, y, z;//指数float exponent;//检查单位四元数,避免除零if(fabs(w) < 0.9999f){//提取半角float alpha = acos(w);//计算新的alpha值float newAlpha = alpha * exponent;//计算新的w值w = cos(newAlpha);//计算新的x, y, z 值float mult = sin(newAlpha) / sin(alpha);x *= mult;y *= mult;z *= mult;}
  • 四元数插值(slerp):
    当今3D数学中四元数之所以存在的理由就是利用它可以在两个四元数间平滑的插值。它避免了欧拉角插值的所有问题。具体的推导过程就不详细解释了,有兴趣的可以自己查阅相关资料(3D数学基础图形与游戏开发),下面直接贴出公式:
    这里写图片描述

    slerp代码实例:

//两个输入四元数float w0, x0, y0, z0;float w1, x1, y1, z1;//插值变量float t;//输出四元数float w, x, y, z;//用点乘计算两四元数夹角的cos值float cosOmega = w0 * w1 + x0 * x1 + y0 * y1 + z0 * z1;//如果点乘为负,则反转一个四元数以取得短的4D弧if(cosOmega < 0.0f){w1 = -w1;x1 = -x1;y1 = -y1;z1 = -z1;cosOmega = -cosOmega;}//检查插值的起点和终点是否过于接近以避免除零float k0, k1;if(cosOmega > 0.9999f){//非常接近,直接用线性插值k0 = 1.0 - t;k1 = t;}else{//用三角公式sin^2(cosOmega) + cos^2(cosOmega) = 1计算出sinwfloat sinOmega = sqrt(1.0f - cosOmega * cosOmega);//通过sinw 和 cosw计算w夹角float omega = atan2(sinOmega, cosOmega);//计算分母的倒数,这样只需要一次除法float oneOverSinOmega = 1.0f / sinOmega;//计算插值变量k0 = sin((1.0f - t) * omega) * oneOverSinOmega;k1 = sin(t * omega) * oneOverSinOmega;}//得到插值w = w0 * k0 + w1 * k1;x = x0 * k0 + x1 * k1;y = y0 * k0 + y1 * k1;z = z0 * k0 + z1 * k1;
  • 四元数样条(squad):
    slerp(球面线性插值)只提供了两个方位间的插值,但对于超过两个的方位序列,我们要进行插值就得用到squad。对于其具体数学原理推导这里也不打算讲了。

四元数的优点和缺点

  • 四元数的一些其他角位移表示方法所没有的优点:
    1,平滑插值
    2,快速连接和角位移求逆,同样的操作,它要比矩阵快且容易些。
    3,能快速转换成矩阵形式。
    4,仅用四个数表示。

  • 缺点:
    1,比欧拉角稍微大一些。
    2,四元数可能不合法。因为我们讨论的有意义的四元数必须是单位大小,而输入坏数据或浮点数舍入误差累积都可能使四元数不合法(当然我们可以通过四元数标准化来解决这个问题)。
    3,难于使用,在所有三种形式中,四元数是最难直接使用的。

这篇关于3D数学基础--3D中的方位与角位移(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

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

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

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

uva 10014 Simple calculations(数学推导)

直接按照题意来推导最后的结果就行了。 开始的时候只做到了第一个推导,第二次没有继续下去。 代码: #include<stdio.h>int main(){int T, n, i;double a, aa, sum, temp, ans;scanf("%d", &T);while(T--){scanf("%d", &n);scanf("%lf", &first);scanf

uva 10025 The ? 1 ? 2 ? ... ? n = k problem(数学)

题意是    ?  1  ?  2  ?  ...  ?  n = k 式子中给k,? 处可以填 + 也可以填 - ,问最小满足条件的n。 e.g k = 12  - 1 + 2 + 3 + 4 + 5 + 6 - 7 = 12 with n = 7。 先给证明,令 S(n) = 1 + 2 + 3 + 4 + 5 + .... + n 暴搜n,搜出当 S(n) >=

uva 11044 Searching for Nessy(小学数学)

题意是给出一个n*m的格子,求出里面有多少个不重合的九宫格。 (rows / 3) * (columns / 3) K.o 代码: #include <stdio.h>int main(){int ncase;scanf("%d", &ncase);while (ncase--){int rows, columns;scanf("%d%d", &rows, &col

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX