c++ “QQuaternion”旋转如何工作?

thigvfpy  于 2023-08-09  发布在  其他
关注(0)|答案(1)|浏览(133)

我注意到Qt库和其他库之间通过quaternion的向量旋转的差异。
这就是Qt的实现。

QQuaternion QQuaternion::fromEulerAngles(float pitch, float yaw, float roll)
{
    // Algorithm from:
    // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60

    pitch = qDegreesToRadians(pitch);
    yaw = qDegreesToRadians(yaw);
    roll = qDegreesToRadians(roll);

    pitch *= 0.5f;
    yaw *= 0.5f;
    roll *= 0.5f;

    const float c1 = std::cos(yaw);
    const float s1 = std::sin(yaw);
    const float c2 = std::cos(roll);
    const float s2 = std::sin(roll);
    const float c3 = std::cos(pitch);
    const float s3 = std::sin(pitch);
    const float c1c2 = c1 * c2;
    const float s1s2 = s1 * s2;

    const float w = c1c2 * c3 + s1s2 * s3;
    const float x = c1c2 * s3 + s1s2 * c3;
    const float y = s1 * c2 * c3 - c1 * s2 * s3;
    const float z = c1 * s2 * c3 - s1 * c2 * s3;
}

字符串
这是一个库实现:

void Quaternion_fromEulerZYX(double eulerZYX[3], Quaternion* output)
{
    assert(output != NULL);
    // Based on https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
    double cy = cos(eulerZYX[2] * 0.5);
    double sy = sin(eulerZYX[2] * 0.5);
    double cr = cos(eulerZYX[0] * 0.5);
    double sr = sin(eulerZYX[0] * 0.5);
    double cp = cos(eulerZYX[1] * 0.5);
    double sp = sin(eulerZYX[1] * 0.5);

    output->w = cy * cr * cp + sy * sr * sp;
    output->v[0] = cy * sr * cp - sy * cr * sp;
    output->v[1] = cy * cr * sp + sy * sr * cp;
    output->v[2] = sy * cr * cp - cy * sr * sp;
}


注意最后三个字符串。x和y在表达式中具有不同的符号。而Qt函数对应的是常见的Euler angles矩阵乘法,而不是其他库的实现。
所以我很困惑另一个图书馆是如何运作的?因为我使用非Qt库得到了错误的结果。

11dmarpk

11dmarpk1#

您的Qt代码片段使用Tait-BryanAngular 从EulerAngular 创建四元数。泰特-布莱恩角是特定类型的欧拉角,其中每个旋转围绕不同的轴(x,y,z)发生。
相反,另一个库可能使用不同的旋转约定。例如,它可能使用ZYX欧拉角来创建四元数,该四元数先绕z轴旋转,然后绕y轴旋转,最后绕x轴旋转。这些约定的差异可能导致结果的差异。
要解决此问题,需要确保在两个库中以相同的顺序和次序应用旋转。如果另一个库使用不同的约定,则需要相应地调整代码以匹配该约定。
这里有一个例子,你可以调整其他库的方法来匹配Qt库的约定:

void Quaternion_fromEulerZYX(double eulerZYX[3], Quaternion* output)
{
    assert(output != NULL);
    // Adjusted to match the Qt library's convention
    double cy = cos(eulerZYX[1] * 0.5);  // yaw
    double sy = sin(eulerZYX[1] * 0.5);  // yaw
    double cr = cos(eulerZYX[2] * 0.5);  // roll
    double sr = sin(eulerZYX[2] * 0.5);  // roll
    double cp = cos(eulerZYX[0] * 0.5);  // pitch
    double sp = sin(eulerZYX[0] * 0.5);  // pitch

    output->w = cy * cr * cp + sy * sr * sp;
    output->v[0] = cy * sr * cp - sy * cr * sp;
    output->v[1] = cy * cr * sp + sy * sr * cp;
    output->v[2] = sy * cr * cp - cy * sr * sp;
}

字符串
这段代码调整了操作的顺序,以符合Qt库的约定,这可能会解决您所看到的差异。但是,在使用任何库之前,都应该确保理解其使用的约定,因为不同的库可能具有不同的四元数操作约定。

相关问题