I'm using the Eigen C++ library. Multiplying a quaternion with it's inverse should always give the zero rotation, right?
I have a specific testcase where it doesn't.
// This case works fine:
OrientationTestsEigen(1.7118, 0.8036, 1.5977);
// This fails:
OrientationTestsEigen(1.7118679426016505, 0.80361404966200567, 1.5977764119637190);
Test code:
bool approxEqual(double a, double b)
{
return fabs(a - b) < 0.0001;
}
void QuaternionToYPR(const Quaterniond& quat, double &y, double &p, double &r)
{
Eigen::Vector3d rpy = quat.toRotationMatrix().eulerAngles(2, 0, 1);
r = rpy.x();
p = rpy.y();
y = rpy.z();
}
void OrientationTestsEigen(double yaw, double pitch, double roll)
{
// Convert Yaw, Pitch, Roll to Quaternion
Eigen::AngleAxisd yawAngle(yaw, Eigen::Vector3d::UnitY());
Eigen::AngleAxisd pitchAngle(pitch, Eigen::Vector3d::UnitX());
Eigen::AngleAxisd rollAngle(roll, Eigen::Vector3d::UnitZ());
Quaterniond quaternionRepresentation = rollAngle * pitchAngle * yawAngle;
// quat * quat.inverse() should result in zero rotation
Quaterniond shouldBeZero = quaternionRepresentation * quaternionRepresentation.inverse();
double y3, p3, r3;
QuaternionToYPR(shouldBeZero, y3, p3, r3);
assert(fabs(y3) < 0.001);
assert(fabs(p3) < 0.001);
assert(fabs(r3) < 0.001);
}
I find it very strange that the first case works, but the second (with only a tiny difference in values) fails. What I'm getting is:
Why do we get 180° roll in the second case, and not zero?
The same rotation can be represented by MULtiple Euler angles (yaw, pitch, roll). So your comparison is not correct.
You can compare rotation matrices or estimate angle of rotation between result quaternion and Identity quaternion.
shouldBeZero.angularDistance(Quaterniond::Identity());