简洁明了的搞清楚四元数和旋转矩阵的关系及使用

文章目录

  • 1 混淆的哪里?
  • 2 两种旋转
    • 2.1 回答第一个问题
    • 2.2 回答第二个问题
  • 3 总结

1 混淆的哪里?

关于四元数和旋转矩阵,使用过程中很容易迷糊,很重要的原因是没有区分好『坐标系的旋转』和『向量的旋转』。

不想看详细的说明过程可以直接看总结部分。

2 两种旋转

下面首先来区分这两种旋转。以一个飞机为例,假设惯性系为N(XYZ)系(下图中的黑色坐标系),B系(X’Y’Z’)与飞机固连(下图中的蓝色坐标系)。t0时刻,飞机的B系与N系完全重合。
简洁明了的搞清楚四元数和旋转矩阵的关系及使用_第1张图片
坐标系的旋转: N系的XYZ旋转到B系的X’Y’Z’,对应的四元数为q,V并没随着B系的转动而转动,如上图所示。坐标系旋转后,有1个信息是我们想知道的:

  • V向量在B系中的坐标是多少?(第一个问题)

向量的旋转: R向量从初始位置旋转到了R’的位置,对应的四元数为q,如下图所示。
简洁明了的搞清楚四元数和旋转矩阵的关系及使用_第2张图片
向量旋转后,同样有1个信息是我们想知道的:

  • R’向量在N系中新的坐标是多少?(第二个问题)

从上面可以看出,旋转可以指坐标系的旋转,也可以指向量的旋转,他们代表的含义是完全不同的,所以当谈到旋转时,一定要搞清楚这个前提条件:究竟是『谁』被旋转了。

2.1 回答第一个问题

  • V向量在B系中的坐标是多少?
    V向量在空间中的位置并没有变,只是它在B系中有另一个坐标表示方法。

V’ = q-1 * V * q

上式中,由于四元数quaternion并不能与vector直接运算,需要把V转换为纯四元,即实部为0的四元数。如果使用eigen来实现,有几种的不同的方法,但是最终的结果都是一样的。

// 场景一:N系中的向量Vn_in_N在B系表示
    float angle = 30 * (3.1415926 / 180.f);
    Vector3f Vn_in_N = { 0, 0, 1 };
    Quaternionf q(AngleAxisf(angle, Vector3f::UnitX()));

    // 方法1:
    Vector3f Vn_in_B = (q.conjugate() * Quaternionf(0, Vn_in_N.x(), Vn_in_N.y(), Vn_in_N.z()) * q).vec();
    cout << "Vn_in_B = " << Vn_in_B << endl;
    cout << endl;

    // 方法2:
    Vn_in_B = q.matrix().transpose() * Vn_in_N; // q.matrix()为Cbn,b系到n系的坐标变换矩阵
    cout << "Vn_in_B = " << Vn_in_B << endl;
    cout << endl;

    // 方法3:Eigen中对 * 进行了运算符重载,本质上与方法2是相同的
    Vn_in_B = q.conjugate() * Vn_in_N;
    cout << "Vn_in_B = " << Vn_in_B << endl;
    cout << endl;

如果B系中有已知的向量V2’,那么它在N系中的表示V2为:
V2 = q * V2’ * q-1
使用eigen实现的代码就不赘述了。

2.2 回答第二个问题

  • R向量被旋转后,它在空间中的位置发生了变化,有一个新的坐标R’
    R’ = q * R * q-1

有一点值得注意的是,很多场合把q转换为旋转矩阵Cbn(b–>n),这里的Cbn指的是把B系中已知的向量Vb在N系中的坐标是多少Vn,即:
Vn = Cbn * Vb
简洁明了的搞清楚四元数和旋转矩阵的关系及使用_第3张图片
上面代码中的 q.matrix() 就是Cbn

3 总结

以下的结论务必记住。

如果一个向量 V 固定,坐标系旋转按照四元数 q 进行了旋转,得到了一个新坐标系,则该向量分别在新旧坐标系中投影表达式间的关系可以表示为:
V’ = q-1 * V * q

如果一个坐标系固定, 一个向量 V按照四元数 q 相对该坐标系进行了转动,得到一个新的向量 V’,则新旧向量之间的关系为:
V’ = q * V * q-1

你可能感兴趣的:(数学,飞控)