四元数学习之四元数和矩阵的转换

本文探讨四元数作为替代矩阵和欧拉角的数学工具,解释四元数不满足交换率的原因,并讨论其在计算机图形学中的优势。通过公式推导,展示了如何将四元数转换为旋转矩阵,并通过OpenGL进行验证。最后,提供了实现四元数运算的简单类及其使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

四元数学习之四元数和矩阵的转换

         四元数是一种可以替代矩阵和欧拉角的数学工具。他最初是由William Rowan Hamilton发现的(参考维基百科),它的最大的特点是不满足交换率。也谈一下自己对这一点的体会。在离散数学中有讲到半群、群、环和域的概念,其中环的定义是具有交换率和分配率(详情参考环的数学定义),而域的概念则是在环的基础上加上了交换率。所以说四元数无法满足域的定义,它是除法环的一种。何为除法环?其实很简单,被除数和除数都满足结合律和分配律,但是如果要满足交换律,即被除数和除数交换位置,那么它的结果是不同的(准确地说,如果它们不为0的话,那么结果呈倒数关系)。又由于要在四维解空间上解得i3=-1,所以只能在不满足交换率的条件下得出i、j、k。

    四元数在计算机图形学的优势在于运算量小和利于插值,且旋转没有缺陷。可是普通的一个四元数定义又比较难懂,而且OpenGL的API中又没有带四元数的参数的函数,所以需要我们根据公式做一做小小的转换。

    原创文章,反对未声明的引用。原博客地址

### 四元数转换矩阵的关系 四元数是一种用于表示三维空间旋的有效工具,而转换矩阵则可以用来描述更广泛的几何变换,包括平移、缩放。当仅考虑纯旋时,四元数可以通过特定的数学公式化为对应的旋矩阵[^1]。 #### 四元数到旋矩阵转换 给定一个单位四元数 \( q = w + xi + yj + zk \),其分量分别为 \( w, x, y, z \) 并满足约束条件 \( w^2 + x^2 + y^2 + z^2 = 1 \)。该四元数可被映射至如下形式的旋矩阵: \[ R = \begin{bmatrix} 1 - 2y^2 - 2z^2 & 2xy - 2wz & 2xz + 2wy \\ 2xy + 2wz & 1 - 2x^2 - 2z^2 & 2yz - 2wx \\ 2xz - 2wy & 2yz + 2wx & 1 - 2x^2 - 2y^2 \end{bmatrix} \] 上述公式的推导基于四元数乘法定义及其与向量叉积运算之间的联系[^2]。 以下是实现这一过程的一个 Python 函数示例: ```python import numpy as np def quaternion_to_rotation_matrix(quaternion): """ 将四元数为旋矩阵 :param quaternion: 单位四元数 (w, x, y, z) :return: 对应的3×3旋矩阵 """ w, x, y, z = quaternion / np.linalg.norm(quaternion) R = np.array([ [1 - 2*y**2 - 2*z**2, 2*x*y - 2*w*z, 2*x*z + 2*w*y], [ 2*x*y + 2*w*z, 1 - 2*x**2 - 2*z**2, 2*y*z - 2*w*x], [ 2*x*z - 2*w*y, 2*y*z + 2*w*x, 1 - 2*x**2 - 2*y**2] ]) return R ``` #### 旋矩阵四元数转换 对于任意有效的正交旋矩阵 \( R \in SO(3) \),存在唯一一组对应于它的单位四元数(相差全局负号)。具体计算方式取决于矩阵元素的最大值位置来优化数值稳定性[^3]。 下面提供了一个从旋矩阵恢复四元数的方法: ```python def rotation_matrix_to_quaternion(matrix): """ 将旋矩阵四元数 :param matrix: 输入的3×3旋矩阵 :return: 对应的单位四元数(w,x,y,z) """ trace = matrix.trace() if trace > 0: S = ((trace + 1.0)**0.5)*2 qw = 0.25 * S qx = (matrix[2][1]-matrix[1][2])/S qy = (matrix[0][2]-matrix[2][0])/S qz = (matrix[1][0]-matrix[0][1])/S elif (matrix[0][0]>max(matrix[1][1],matrix[2][2])): S=(((1.0+matrix[0][0]-matrix[1][1]-matrix[2][2])**0.5))*2; qw=(matrix[2][1]-matrix[1][2])/S ; qx=0.25*S; qy=(matrix[0][1]+matrix[1][0])/S; qz=(matrix[0][2]+matrix[2][0])/S; elif (matrix[1][1]>matrix[2][2]): S=((1.0-matrix[0][0]+matrix[1][1]-matrix[2][2]))**(0.5)*2; qw=(matrix[0][2]-matrix[2][0])/S; qx=(matrix[0][1]+matrix[1][0])/S; qy=0.25*S; qz=(matrix[1][2]+matrix[2][1])/S; else : S=((1.0-matrix[0][0]-matrix[1][1]+matrix[2][2])**(0.5))*2; qw=(matrix[1][0]-matrix[0][1])/S; qx=(matrix[0][2]+matrix[2][0])/S; qy=(matrix[1][2]+matrix[2][1])/S; qz=0.25*S; return np.array([qw,qx,qy,qz]) ``` 以上函数实现了两种数据结构间的双向化操作,并保持了较高的精度需求下的鲁棒性处理[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值