我注意到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库得到了错误的结果。
1条答案
按热度按时间11dmarpk1#
您的Qt代码片段使用Tait-BryanAngular 从EulerAngular 创建四元数。泰特-布莱恩角是特定类型的欧拉角,其中每个旋转围绕不同的轴(x,y,z)发生。
相反,另一个库可能使用不同的旋转约定。例如,它可能使用ZYX欧拉角来创建四元数,该四元数先绕z轴旋转,然后绕y轴旋转,最后绕x轴旋转。这些约定的差异可能导致结果的差异。
要解决此问题,需要确保在两个库中以相同的顺序和次序应用旋转。如果另一个库使用不同的约定,则需要相应地调整代码以匹配该约定。
这里有一个例子,你可以调整其他库的方法来匹配Qt库的约定:
字符串
这段代码调整了操作的顺序,以符合Qt库的约定,这可能会解决您所看到的差异。但是,在使用任何库之前,都应该确保理解其使用的约定,因为不同的库可能具有不同的四元数操作约定。