一、理论基础

1. 旋转矩阵

旋转矩阵通常是一个3x3矩阵,表示物体的旋转变换。一个标准的旋转矩阵 ( R ) 如下:

R=(r11r12r13r21r22r23r31r32r33)R = \begin{pmatrix} r_{11} & r_{12} & r_{13} \\ r_{21} & r_{22} & r_{23} \\ r_{31} & r_{32} & r_{33} \end{pmatrix}R= r11r21r31r12r22r32r13r23r33

2. 四元数的定义

四元数的形式为 ( q = (w, x, y, z) ),其中:

  • ( w ) 是实部,
  • ( x, y, z ) 是虚部。

四元数 ( q ) 和旋转矩阵 ( R ) 之间的关系可以通过以下公式进行转换。

3. 姿态矩阵转四元数公式

根据旋转矩阵 ( R ) 的迹(trace),可以选择不同的公式来计算四元数。

(1) 如果矩阵的迹 trace(R)>0\text{trace}(R) > 0trace(R)>0

矩阵的迹是对角线元素之和:

trace(R)=r11+r22+r33\text{trace}(R) = r_{11} + r_{22} + r_{33}trace(R)=r11+r22+r33

在这种情况下,四元数可以通过以下公式计算:

S=2×trace(R)+1 S = 2 \times \sqrt{\text{trace}(R) + 1} S=2×trace(R)+1

w=0.25×S w = 0.25 \times S w=0.25×S
x=r32−r23S x = \frac{r_{32} - r_{23}}{S} x=Sr32r23
y=r13−r31S y = \frac{r_{13} - r_{31}}{S} y=Sr13r31
z=r21−r12S z = \frac{r_{21} - r_{12}}{S} z=Sr21r12

(2) 如果矩阵的迹 trace(R)≤0\text{trace}(R) \leq 0trace(R)0

需要根据不同的矩阵元素选择最大对角线元素,选择不同的公式进行计算。

  • 如果 r11r_{11}r11 是最大值:
    S=2×1+r11−r22−r33 S = 2 \times \sqrt{1 + r_{11} - r_{22} - r_{33}} S=2×1+r11r22r33
    w=r32−r23S w = \frac{r_{32} - r_{23}}{S} w=Sr32r23
    x=0.25×S x = 0.25 \times S x=0.25×S
    y=r12+r21S y = \frac{r_{12} + r_{21}}{S} y=Sr12+r21
    z=r13+r31S z = \frac{r_{13} + r_{31}}{S} z=Sr13+r31

  • 如果 r22r_{22}r22是最大值:
    S=2×1+r22−r11−r33 S = 2 \times \sqrt{1 + r_{22} - r_{11} - r_{33}} S=2×1+r22r11r33
    w=r13−r31S w = \frac{r_{13} - r_{31}}{S} w=Sr13r31
    x=r12+r21S x = \frac{r_{12} + r_{21}}{S} x=Sr12+r21
    y=0.25×S y = 0.25 \times S y=0.25×S
    z=r23+r32S z = \frac{r_{23} + r_{32}}{S} z=Sr23+r32

  • 如果(r33( r_{33}(r33是最大值:
    S=2×1+r33−r11−r22 S = 2 \times \sqrt{1 + r_{33} - r_{11} - r_{22}} S=2×1+r33r11r22
    w=r21−r12S w = \frac{r_{21} - r_{12}}{S} w=Sr21r12
    x=r13+r31S x = \frac{r_{13} + r_{31}}{S} x=Sr13+r31
    y=r23+r32S y = \frac{r_{23} + r_{32}}{S} y=Sr23+r32
    z=0.25×S z = 0.25 \times S z=0.25×S



二、C++程序实现

根据第一部分理论基础的介绍,很容易可以写出对应的C++程序,我写的一个示例如下所示,其中matrixToQuaternion函数接收一个3x3旋转矩阵,利用上面介绍的四元数和旋转矩阵之间的数学公式,计算并返回对应的四元数。 printQuaternion函数用于将四元数的值输出到终端。

#include <iostream>
#include <cmath>

struct Quaternion {
    double w, x, y, z;
};

// 旋转矩阵转换为四元数的函数
Quaternion matrixToQuaternion(double R[3][3]) {
    Quaternion q;
    double trace = R[0][0] + R[1][1] + R[2][2]; // 矩阵的迹

    if (trace > 0.0) {
        double s = 0.5 / sqrt(trace + 1.0);
        q.w = 0.25 / s;
        q.x = (R[2][1] - R[1][2]) * s;
        q.y = (R[0][2] - R[2][0]) * s;
        q.z = (R[1][0] - R[0][1]) * s;
    } else {
        if (R[0][0] > R[1][1] && R[0][0] > R[2][2]) {
            double s = 2.0 * sqrt(1.0 + R[0][0] - R[1][1] - R[2][2]);
            q.w = (R[2][1] - R[1][2]) / s;
            q.x = 0.25 * s;
            q.y = (R[0][1] + R[1][0]) / s;
            q.z = (R[0][2] + R[2][0]) / s;
        } else if (R[1][1] > R[2][2]) {
            double s = 2.0 * sqrt(1.0 + R[1][1] - R[0][0] - R[2][2]);
            q.w = (R[0][2] - R[2][0]) / s;
            q.x = (R[0][1] + R[1][0]) / s;
            q.y = 0.25 * s;
            q.z = (R[1][2] + R[2][1]) / s;
        } else {
            double s = 2.0 * sqrt(1.0 + R[2][2] - R[0][0] - R[1][1]);
            q.w = (R[1][0] - R[0][1]) / s;
            q.x = (R[0][2] + R[2][0]) / s;
            q.y = (R[1][2] + R[2][1]) / s;
            q.z = 0.25 * s;
        }
    }

    return q;
}

// 打印四元数的函数
void printQuaternion(const Quaternion &q) {
    std::cout << "Quaternion: (x = " << q.x << ", y = " << q.y << ", z = " << q.z << ", w = " << q.w << ", )\n";
}

int main() {
    // 设定旋转矩阵
    double R[3][3] = {
        -0.8545994, -0.5192878,  0.0000000,
        -0.5192878,  0.8545994,  0.0000000,
         0.0000000,  0.0000000, -1.0000000
    };

    // 将旋转矩阵转换为四元数
    Quaternion q = matrixToQuaternion(R);

    // 打印四元数
    printQuaternion(q);

    return 0;
}

编译和运行:

  1. 将以上代码保存到一个文件,例如 matrix_to_quaternion.cpp

  2. 然后在终端执行以下指令编译该程序(文件名自行修改):

    g++ matrix_to_quaternion.cpp -o matrix_to_quaternion
    
  3. 编译成功后,使用以下指令运行程序:

    ./matrix_to_quaternion
    
  4. 上述程序中提供的旋转矩阵示例,运行输出的对应的四元数如下所示:

在这里插入图片描述

Quaternion: (x = -0.26963, y = 0.962964, z = 0, w = 0, )

在这里插入图片描述

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐