四元数学习之四元数和矩阵的转换
四元数是一种可以替代矩阵和欧拉角的数学工具。他最初是由William Rowan Hamilton发现的(参考维基百科),它的最大的特点是不满足交换率。也谈一下自己对这一点的体会。在离散数学中有讲到半群、群、环和域的概念,其中环的定义是具有交换率和分配率(详情参考环的数学定义),而域的概念则是在环的基础上加上了交换率。所以说四元数无法满足域的定义,它是除法环的一种。何为除法环?其实很简单,被除数和除数都满足结合律和分配律,但是如果要满足交换律,即被除数和除数交换位置,那么它的结果是不同的(准确地说,如果它们不为0的话,那么结果呈倒数关系)。又由于要在四维解空间上解得i3=-1,所以只能在不满足交换率的条件下得出i、j、k。
四元数在计算机图形学的优势在于运算量小和利于插值,且旋转没有缺陷。可是普通的一个四元数定义又比较难懂,而且OpenGL的API中又没有带四元数的参数的函数,所以需要我们根据公式做一做小小的转换。
原创文章,反对未声明的引用。原博客地址:http://blog.csdn.net/gamesdev/article/details/10036105
设四元数Q(x, y, z, w)表示向量a(xa,ya, za)经过α角旋转后的结果,则x、y、z和w分别为:
x= sin(α/2)·xa
y= sin(α/2)·ya
z= sin(α/2)·za
w= cos(α/2)
在上一篇博客中讲到了如何用一个矩阵表示坐标系沿向量的旋转,这里我直接给出公式:
将这两个公式结合起来。再结合高中所学的半角公式:
sinα = 2sin(α/2)·cos(α/2)
cosα = cos2(α/2) - sin2(α/2)
cos2(α/2) = (1 +cosα)/2
sin2(α/2) = (1 -cosα)/2
可以解出用四元数表示旋转矩阵为:
该来验证一下公式的正确性,同样地,采用OpenGL托管的矩阵来测试,看看使用自带的glRotatef()函数和我们写的公式相比,究竟有没有差距。
首先写了一个简单的Quaternion类,它的定义如下:
#ifndef QUATERNION_H
#define QUATERNION_H
#include <QtGlobal>
#include <math.h>
class Quaternion
{
public:
Quaternion( float _x,
float _y,
float _z,
float _w )
{
x = _x;
y = _y;
z = _z;
w = _w;
}
void ToMatrix( float matrix[] )
{
Q_ASSERT( matrix != Q_NULLPTR );
#ifndef MATRIX
#define MATRIX( row, col ) matrix[row * 4 + col]
#endif
MATRIX( 0, 0 ) = 2 * ( x * x + w * w ) - 1;
MATRIX( 0, 1 ) = 2 * ( x * y + z * w );
MATRIX( 0, 2 ) = 2 * ( x * z - y * w );
MATRIX( 0, 3 ) = 0.0f;
MATRIX( 1, 0 ) = 2 * ( x * y - z * w );
MATRIX( 1, 1 ) = 2 * ( y * y + w * w ) - 1;
MATRIX( 1, 2 ) = 2 * ( y * z + x * w );
MATRIX( 1, 3 ) = 0.0f;
MATRIX( 2, 0 ) = 2 * ( x * z + y * w );
MATRIX( 2, 1 ) = 2 * ( y * z - x * w );
MATRIX( 2, 2 ) = 2 * ( z * z + w * w ) - 1;
MATRIX( 2, 3 ) = 0.0f;
MATRIX( 3, 0 ) = 0.0f;
MATRIX( 3, 1 ) = 0.0f;
MATRIX( 3, 2 ) = 0.0f;
MATRIX( 3, 3 ) = 1.0f;
#undef MATRIX
}
static Quaternion FromRotation( float _x,
float _y,
float _z,
float angleInDegree )
{
// 向量的单位化
float length = sqrt( _x * _x + _y * _y + _z * _z );
Q_ASSERT( !qFuzzyCompare( length, 0.0f ) );// 希望length不为0
_x /= length;
_y /= length;
_z /= length;
float alpha = angleInDegree / 180 * 3.1415926;// 已转换弧度制
return Quaternion(
sin( alpha / 2 ) * _x,
sin( alpha / 2 ) * _y,
sin( alpha / 2 ) * _z,
cos( alpha / 2 ) );
}
private:
float x, y, z, w;
};
#endif // QUATERNION_H
下面展示了如何调用这个类。
#include <assert.h>
#include <stdio.h>
#include "GLWidget.h"
#include "Quaternion.h"
void PrintMatrix( float matrix[16] )
{
Q_ASSERT( matrix != 0 );
printf( "%8.2f%8.2f%8.2f%8.2f\n"
"%8.2f%8.2f%8.2f%8.2f\n"
"%8.2f%8.2f%8.2f%8.2f\n"
"%8.2f%8.2f%8.2f%8.2f\n",
matrix[0], matrix[1], matrix[2], matrix[3],
matrix[4], matrix[5], matrix[6], matrix[7],
matrix[8], matrix[9], matrix[10], matrix[11],
matrix[12], matrix[13], matrix[14], matrix[15] );
}
GLWidget::GLWidget( QWidget* pParent ):
QGLWidget( pParent )
{
setWindowTitle( "Test OpenGL Quaternion and matrix" );
}
void GLWidget::initializeGL( void )
{
float angle = 30.0f;
float x = 12.0f;
float y = 8.0f;
float z = 3.0f;
float matrix1[16], matrix2[16];
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glGetFloatv( GL_MODELVIEW_MATRIX, matrix1 );
glGetFloatv( GL_MODELVIEW_MATRIX, matrix2 );
printf( "The initial identity matrix is:\n" );
PrintMatrix( matrix2 );
printf( "Now perform OpenGL glRotate function.\n" );
glRotatef( angle, x, y, z );
glGetFloatv( GL_MODELVIEW_MATRIX, matrix1 );
PrintMatrix( matrix1 );
printf( "Now using quaternion to perform rotation.\n" );
Quaternion::FromRotation( x, y, z, angle ).ToMatrix( matrix2 );
PrintMatrix( matrix2 );
}
void GLWidget::paintGL( void )
{
}
以下是运行结果。
这说明上述运算是正确的。
分享到:
相关推荐
讲述四元数和旋转矩阵之间相互转化的学术论文:首先介绍了四元数和旋转矩阵在实现向量旋转中的应用,在此基础上,根据游戏开发的实际需要,讨论了四元数和旋转矩阵之间的相互转化关系。最后,重点分析了由旋转矩阵到...
四元数矩阵右特征值的计算可转化为它的复表示矩阵的特征值的计算问题,本文利用复表示矩阵的特殊结构给出了一种减少计算其特征值计算量的方法。 四元数矩阵计算中有一些新的问题是复矩阵计算中没有的内容。例如...
欧拉角/四元数转化为机器手坐标系描述矩阵,有两个matlab程序,分别是欧拉角模式和四元数模式转化为描述矩阵的代码
这是矩阵欧拉角四元数两两之间的转换软件,只要输入其中一个,就可以转换其他两个,而且欧拉角还分弧度和度的形式,同时还有娱乐快捷键,学习娱乐两不误
旋转矩阵R通常是3x3的形式,具有inv(R)=trans(R)的性质,即R的逆就是R的转置。 描述旋转还可有另外一组实数来表示,就是四元素。...本例子给出了四元数与欧拉角以及与旋转矩阵互换的代码。希望对各位有用。
四元数与欧拉角以及矩阵之间的转换,把欧拉角转换成旋转矩阵,方便计算顶点变换。
本文提出了一种四元数和对偶四元数矩阵形式的新算法。 它在旋转平面的特殊情况下应用四元数,将旋转角度的正弦和余弦转换为矩阵形式,然后以两个矩阵形式导出平坦的四元数基。 它以四元数矩阵的形式建立了一系列6R...
四元数转化为旋转矩阵的matlab函数
包含四元数的基本运算,矩阵的基本运算,四元数、欧拉角、旋转矩阵之间的相互转换
共有六个函数。作用分别是,姿态矩阵转换为欧拉角;欧拉角转换为姿态矩阵;欧拉角转换为四元数;四元数转换为姿态矩阵‘四元数转换为欧拉角。’
欧拉角,四元数和方向余弦矩阵三者之间相互转换的代码,采用北-东-地坐标系
旋转矩阵和四元数以及欧拉角之间的转换,相应公式推导过程
代码!!!!重要!!!! 学习中关于机器人领域中四元数、欧拉角、旋转矩阵、旋转向量的相互转换关系总结,整理加深记忆。 每一个都有相互转换关系,并注释
文档描述了,在东北天下的欧拉角,旋转矩阵,四元数,之间的转换关系,以及加速度计,磁力计的转换关系,有助于姿态解算时的推导。
# 写上用四元数表示的orientation和xyz表示的position orientation = {'y': -0.6971278819736084, 'x': -0.716556549511624, 'z': -0.010016582945017661, 'w': 0.02142651612120239} position = {'y': -0....
从旋转矩阵计算得到四元数,代码简单,内附word说明文档。如有不当之处还请多多指正。
openGL相关的四元数类。包括与欧拉角的转换和矩阵类的转换。
这个是OpenGL相关的矩阵类,其中实现了包括了平移矩阵、旋转矩阵、缩放矩阵等各种矩阵变换的实现以及欧拉角和四元数的相关转换。
我上个四元数的文档里面有错误,所以我修改了一下。...里面主要修改了旋转矩阵和四元数之间相互转换的矩阵对应关系,之前一个是左乘,一个是右乘,我没有注意到。需要把其中一个矩阵转置之后才能对应上。
对于旋转矩阵、欧拉角、四元数的转换过程的一个解释。你们说的话我不敢苟同,我个人认为这个意大利面应该拌42号混凝土,因为这个螺丝钉的长度很容易会直接影响到挖掘机的扭矩,你往里砸的时候,一瞬间它就会产生大量...