旋转矩阵与欧拉角的相互转换

简介: 旋转矩阵与欧拉角的相互转换

旋转矩阵与欧拉角的相互转换

目录

1. 概述

欧拉角与旋转矩阵的相互转换,是图形计算中的常见问题。

2. 详论

2.1. 欧拉角的理解

表达旋转变换最简单的理解是三种旋转矩阵(绕X轴旋转矩阵,绕Y轴旋转矩阵以及绕Z轴旋转矩阵)级联。而欧拉角同样也有三种:航向角heading,俯仰角pitch和滚转角roll;其中,航向角heading有时也被称为偏航角yaw。三个欧拉角定义的矩阵级联也可以定义成旋转矩阵,这种旋转变换也叫做欧拉变换。

两者并没有绝对的对应的关系,但是绝大部分情况下,我们可以确定一个默认的视图方向:朝向负z轴,头部沿y轴定向,如下图所示:

想象一个飞机也位于上图的坐标系的默认视图,那么很显然可以看出一个对应关系:

  • 航向角heading为绕Y轴旋转
  • 俯仰角pitch为绕X轴旋转
  • 滚转角roll为绕Z轴旋转

2.2. 欧拉角转旋转矩阵

如上节所述,确定欧拉角到底是绕哪一个轴旋转的关键是确定默认的视图方向。另一个需要确定的因素就是旋转的顺序。由于矩阵的乘法不满足交换律,那么矩阵级联的顺序不同,得到的旋转矩阵也不同。一种比较常用的旋转顺序是:

E(h,p,r)=Rz(r)Rx(p)Ry(h)E(ℎ,�,�)=R�(�)R�(�)R�(ℎ)

我们使用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的实现是正确的,一般的图形矩阵计算库应该都有类似的接口。

分类: OpenGL

标签: OpenGL , 三维图形 , 旋转矩阵 , 欧拉角


相关文章
|
存储 数据采集 数据可视化
Open3d系列 | 1. Open3d实现点云数据读写、点云配准、点云法向量计算
Open3d系列 | 1. Open3d实现点云数据读写、点云配准、点云法向量计算
17877 1
Open3d系列 | 1. Open3d实现点云数据读写、点云配准、点云法向量计算
|
机器学习/深度学习 存储 编解码
Open3d系列 | 3. Open3d实现点云上采样、点云聚类、点云分割以及点云重建
Open3d系列 | 3. Open3d实现点云上采样、点云聚类、点云分割以及点云重建
15051 1
Open3d系列 | 3. Open3d实现点云上采样、点云聚类、点云分割以及点云重建
|
机器学习/深度学习 文字识别 数据挖掘
Visionpro从小白到大佬,第一章了解工具名称和用途
Visionpro从小白到大佬,第一章了解工具名称和用途
3680 0
Visionpro从小白到大佬,第一章了解工具名称和用途
|
算法 机器人 Linux
开源项目推荐:3D点云处理软件CloudCompare,基于Qt和OpenGL
开源项目推荐:3D点云处理软件CloudCompare,基于Qt和OpenGL
6872 0
开源项目推荐:3D点云处理软件CloudCompare,基于Qt和OpenGL
|
算法框架/工具 C++ Python
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
1643 0
|
8月前
|
算法 机器人 Python
机器人逆运动学进阶:李代数、矩阵指数与旋转流形计算
本文深入讲解机器人逆运动学中旋转计算的核心数学工具,包括矩阵指数与对数、SO(3)李群与李代数、流形和切空间等概念,帮助理解三维旋转误差计算原理,并提供基于矩阵指数的精确旋转更新方法及代码实现。
494 1
机器人逆运动学进阶:李代数、矩阵指数与旋转流形计算
|
IDE Unix 编译器
Windows下配置CMake(入门级教程,适合新人收藏学习)
Windows下配置CMake(入门级教程,适合新人收藏学习)
6476 1
|
传感器 机器人 测试技术
ROS相机内参标定详细步骤指南
本文是关于ROS相机内参标定的详细步骤指南,包括了标定的目的、原理、所需材料、具体操作流程以及标定结果的分析。文章以Ubuntu20.04和ROS1 Noetic为测试环境,适用于单目RGB相机的内参标定,使用ros-noetic-camera-calibration工具包进行操作,并提供了标定过程中的注意事项和建议。
2680 1
ROS相机内参标定详细步骤指南
|
传感器 自动驾驶 机器人
大疆Livox Mid360 使用指南
本文是大疆Livox Mid-360激光雷达的使用指南,包括Livox Viewer 2的安装与使用、Livox SDK2的安装与演示、Livox ROS的配置与启动,以及一些使用时的注意事项。文章还提供了关于Livox Mid-360的详细特点、接线信息、尺寸信息、主控端IP设置、修改Livox Mid 360的IP方法、坐标系定义和IMU内参的介绍。此外,还提供了官方资料和软件下载的链接。
10952 2