旋转矩阵与欧拉角之间如何准确实现相互转换?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1296个文字,预计阅读时间需要6分钟。
详细论述了通过GLM库实现旋转矩阵与欧拉角的旋转过程。
目录
1.概述
2.详细论述
1.概述
欧拉角与旋转矩阵是描述三维空间中物体旋转的两种常用方式。本文将详细介绍通过GLM库实现这两种方式之间的转换过程。2. 详细论述
2.1 欧拉角的解释
欧拉角是一种表示三维空间中旋转的方法,通常包括三个角度:俯仰角(Pitch)、横滚角(Roll)和偏航角(Yaw)。这三个角度分别对应于绕x轴、y轴和z轴的旋转。2.2 欧拉角旋转旋转矩阵将欧拉角转换为旋转矩阵的过程涉及计算三个旋转矩阵,并将它们依次相乘。这个过程可以通过GLM库中的函数实现。
2.3 旋转矩阵转欧拉角将旋转矩阵转换为欧拉角的过程需要求解三个角度的值。这可以通过数学上的逆过程完成,同样可以利用GLM库中的函数来实现。
1. 概述欧拉角与旋转矩阵之间的相互转换是三维空间计算中常见的需求。通过GLM库,可以方便地实现这两种表示方式之间的转换。
详细论述了通过GLM库实现旋转矩阵与欧拉角的旋转过程。 目录- 1. 概述
- 2. 详论
- 2.1. 欧拉角的理解
- 2.2. 欧拉角转旋转矩阵
- 2.3. 旋转矩阵转欧拉角
欧拉角与旋转矩阵的相互转换,是图形计算中的常见问题。
2. 详论 2.1. 欧拉角的理解表达旋转变换最简单的理解是三种旋转矩阵(绕X轴旋转矩阵,绕Y轴旋转矩阵以及绕Z轴旋转矩阵)级联。而欧拉角同样也有三种:航向角heading,俯仰角pitch和滚转角roll;其中,航向角heading有时也被称为偏航角yaw。三个欧拉角定义的矩阵级联也可以定义成旋转矩阵,这种旋转变换也叫做欧拉变换。
两者并没有绝对的对应的关系,但是绝大部分情况下,我们可以确定一个默认的视图方向:朝向负z轴,头部沿y轴定向,如下图所示:
想象一个飞机也位于上图的坐标系的默认视图,那么很显然可以看出一个对应关系:
- 航向角heading为绕Y轴旋转
- 俯仰角pitch为绕X轴旋转
- 滚转角roll为绕Z轴旋转
如上节所述,确定欧拉角到底是绕哪一个轴旋转的关键是确定默认的视图方向。另一个需要确定的因素就是旋转的顺序。由于矩阵的乘法不满足交换律,那么矩阵级联的顺序不同,得到的旋转矩阵也不同。一种比较常用的旋转顺序是:
\[{\textbf{E}}(h,p,r) = {\textbf{R}}_z(r){\textbf{R}}_x (p){\textbf{R}}_y(h) \]我们使用GLM(OpenGL Mathematics)库进行验证一下:
#include <iostream>
#include <glm/gtx/euler_angles.hpp>
using namespace std;
static void PrintMat(const glm::mat4& m)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%.9lf\t", m[i][j]);
}
printf("\n");
}
}
int main()
{
glm::mat4 rotY = glm::eulerAngleY(glm::radians(24.0f));
glm::mat4 rotX = glm::eulerAngleX(glm::radians(65.0f));
glm::mat4 rotZ = glm::eulerAngleZ(glm::radians(42.0f));
glm::mat4 rotYXZ = rotY * rotX * rotZ;
PrintMat(rotYXZ);
cout << endl;
glm::mat4 rotYXZ1 = glm::eulerAngleYXZ(glm::radians(24.0f), glm::radians(65.0f), glm::radians(42.0f));
PrintMat(rotYXZ1);
cout << endl;
glm::mat4 rotYXZ2 = glm::yawPitchRoll(glm::radians(24.0f), glm::radians(65.0f), glm::radians(42.0f));
PrintMat(rotYXZ2);
}
运行结果如下:
直接使用欧拉角旋转矩阵相乘,与eulerAngleYXZ()函数,以及yawPitchRoll()函数三者的矩阵结果是一致的。说明在GLM中欧拉角的定义以及旋转顺序,与本文论述的一致。
2.3. 旋转矩阵转欧拉角已知绕X轴、Y轴以及Z轴旋转矩阵的公式以及它们的旋转顺序,可以很容易倒推旋转矩阵表达的欧拉角。当然也没有那么容易,因为有一些特殊情况必须处理。那么还是通过GLM进行实现:
#include <iostream>
#include <glm/gtx/euler_angles.hpp>
using namespace std;
static void PrintMat(const glm::mat4& m)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%.9lf\t", m[i][j]);
}
printf("\n");
}
}
int main()
{
glm::mat4 rotY = glm::eulerAngleY(glm::radians(24.0f));
glm::mat4 rotX = glm::eulerAngleX(glm::radians(65.0f));
glm::mat4 rotZ = glm::eulerAngleZ(glm::radians(42.0f));
glm::mat4 rotYXZ1 = glm::eulerAngleYXZ(glm::radians(24.0f), glm::radians(65.0f), glm::radians(42.0f));
PrintMat(rotYXZ1);
cout << endl;
float y = 0, x = 0, z = 0;
glm::extractEulerAngleYXZ(rotYXZ1, y, x, z);
cout << glm::degrees(y) << '\t' << glm::degrees(x) << '\t' << glm::degrees(z);
}
运行结果如下:
由欧拉角参数生成的eulerAngleYXZ()与extractEulerAngleYXZ()提取的欧拉角一致。说明GLM的实现是正确的,一般的图形矩阵计算库应该都有类似的接口。
本文共计1296个文字,预计阅读时间需要6分钟。
详细论述了通过GLM库实现旋转矩阵与欧拉角的旋转过程。
目录
1.概述
2.详细论述
1.概述
欧拉角与旋转矩阵是描述三维空间中物体旋转的两种常用方式。本文将详细介绍通过GLM库实现这两种方式之间的转换过程。2. 详细论述
2.1 欧拉角的解释
欧拉角是一种表示三维空间中旋转的方法,通常包括三个角度:俯仰角(Pitch)、横滚角(Roll)和偏航角(Yaw)。这三个角度分别对应于绕x轴、y轴和z轴的旋转。2.2 欧拉角旋转旋转矩阵将欧拉角转换为旋转矩阵的过程涉及计算三个旋转矩阵,并将它们依次相乘。这个过程可以通过GLM库中的函数实现。
2.3 旋转矩阵转欧拉角将旋转矩阵转换为欧拉角的过程需要求解三个角度的值。这可以通过数学上的逆过程完成,同样可以利用GLM库中的函数来实现。
1. 概述欧拉角与旋转矩阵之间的相互转换是三维空间计算中常见的需求。通过GLM库,可以方便地实现这两种表示方式之间的转换。
详细论述了通过GLM库实现旋转矩阵与欧拉角的旋转过程。 目录- 1. 概述
- 2. 详论
- 2.1. 欧拉角的理解
- 2.2. 欧拉角转旋转矩阵
- 2.3. 旋转矩阵转欧拉角
欧拉角与旋转矩阵的相互转换,是图形计算中的常见问题。
2. 详论 2.1. 欧拉角的理解表达旋转变换最简单的理解是三种旋转矩阵(绕X轴旋转矩阵,绕Y轴旋转矩阵以及绕Z轴旋转矩阵)级联。而欧拉角同样也有三种:航向角heading,俯仰角pitch和滚转角roll;其中,航向角heading有时也被称为偏航角yaw。三个欧拉角定义的矩阵级联也可以定义成旋转矩阵,这种旋转变换也叫做欧拉变换。
两者并没有绝对的对应的关系,但是绝大部分情况下,我们可以确定一个默认的视图方向:朝向负z轴,头部沿y轴定向,如下图所示:
想象一个飞机也位于上图的坐标系的默认视图,那么很显然可以看出一个对应关系:
- 航向角heading为绕Y轴旋转
- 俯仰角pitch为绕X轴旋转
- 滚转角roll为绕Z轴旋转
如上节所述,确定欧拉角到底是绕哪一个轴旋转的关键是确定默认的视图方向。另一个需要确定的因素就是旋转的顺序。由于矩阵的乘法不满足交换律,那么矩阵级联的顺序不同,得到的旋转矩阵也不同。一种比较常用的旋转顺序是:
\[{\textbf{E}}(h,p,r) = {\textbf{R}}_z(r){\textbf{R}}_x (p){\textbf{R}}_y(h) \]我们使用GLM(OpenGL Mathematics)库进行验证一下:
#include <iostream>
#include <glm/gtx/euler_angles.hpp>
using namespace std;
static void PrintMat(const glm::mat4& m)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%.9lf\t", m[i][j]);
}
printf("\n");
}
}
int main()
{
glm::mat4 rotY = glm::eulerAngleY(glm::radians(24.0f));
glm::mat4 rotX = glm::eulerAngleX(glm::radians(65.0f));
glm::mat4 rotZ = glm::eulerAngleZ(glm::radians(42.0f));
glm::mat4 rotYXZ = rotY * rotX * rotZ;
PrintMat(rotYXZ);
cout << endl;
glm::mat4 rotYXZ1 = glm::eulerAngleYXZ(glm::radians(24.0f), glm::radians(65.0f), glm::radians(42.0f));
PrintMat(rotYXZ1);
cout << endl;
glm::mat4 rotYXZ2 = glm::yawPitchRoll(glm::radians(24.0f), glm::radians(65.0f), glm::radians(42.0f));
PrintMat(rotYXZ2);
}
运行结果如下:
直接使用欧拉角旋转矩阵相乘,与eulerAngleYXZ()函数,以及yawPitchRoll()函数三者的矩阵结果是一致的。说明在GLM中欧拉角的定义以及旋转顺序,与本文论述的一致。
2.3. 旋转矩阵转欧拉角已知绕X轴、Y轴以及Z轴旋转矩阵的公式以及它们的旋转顺序,可以很容易倒推旋转矩阵表达的欧拉角。当然也没有那么容易,因为有一些特殊情况必须处理。那么还是通过GLM进行实现:
#include <iostream>
#include <glm/gtx/euler_angles.hpp>
using namespace std;
static void PrintMat(const glm::mat4& m)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%.9lf\t", m[i][j]);
}
printf("\n");
}
}
int main()
{
glm::mat4 rotY = glm::eulerAngleY(glm::radians(24.0f));
glm::mat4 rotX = glm::eulerAngleX(glm::radians(65.0f));
glm::mat4 rotZ = glm::eulerAngleZ(glm::radians(42.0f));
glm::mat4 rotYXZ1 = glm::eulerAngleYXZ(glm::radians(24.0f), glm::radians(65.0f), glm::radians(42.0f));
PrintMat(rotYXZ1);
cout << endl;
float y = 0, x = 0, z = 0;
glm::extractEulerAngleYXZ(rotYXZ1, y, x, z);
cout << glm::degrees(y) << '\t' << glm::degrees(x) << '\t' << glm::degrees(z);
}
运行结果如下:
由欧拉角参数生成的eulerAngleYXZ()与extractEulerAngleYXZ()提取的欧拉角一致。说明GLM的实现是正确的,一般的图形矩阵计算库应该都有类似的接口。

