Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to write some unit tests and realize I don't know how to compare quaternions. I need to know if two quaternions represent the same orientation (the object would be facing the same way). With a vector like position I'd simply compare the parts and check they are close enough, but for quaternions the values can be very different.

How can I compare two quaternions?

share|improve this question
    
I'm not sure if it is standard practice, but in e.g. Java and Unity the quaternions are stored as four float values. Simply compare these to eachother as outlined in these posts: answers.unity3d.com/questions/288338/… stackoverflow.com/questions/5803627/quaternion-comparision –  Tholle May 15 at 7:19
1  
@Tholle the user is also concerned with the impact of applying the quaternion to transform/rotate a 3D entity (i.e. pose-wise). Two different quaternions can achieve the same rotation (e.g. q and -q). The naive (computationally-wise) way would be to apply both quaternions to the same vector and see if their vector results are different.. –  teodron May 15 at 7:52
add comment

3 Answers 3

up vote 6 down vote accepted

If your two quaternions are q1 and q2, they represent the same rotation if either of these two conditions hold:

  1. q1 is component wise approximately equal to q2 OR
  2. q1 is component wise approximately equal to -q2

Knowing this, you can write a fairly simplistic equality tester that suits your goal.

share|improve this answer
7  
+1, one nitpick though, q and -q represent the same orientation (which was being asked for), but not the same rotation. This is crucial when interpolating. –  falstro May 15 at 8:04
    
@falstro, I think I understand what you mean: the rotation axes are inversed, but the argument angle is also negated between q and -q when represented as an angle-axis rotation operator. So, indeed, technically the effect of these rotations is the same, although the operators are not. And, yes, when SLERPING, one has to make sure q1 and q2 lie on the same hemisphere of the S3 hypersphere in order for the slerp to take the shortest path. –  teodron May 15 at 9:30
1  
Exactly, when you execute either rotation, you'll end up with the same orientation, but interpolate it (whether you lerp or slerp or some other fancy interpolation), you'll see it is turning different ways. And yes, the angle argument is negated, but that's the same as 2pi-angle, so it's turning the long way around the negated axes. Sometimes this is what you want though; it's just something to be aware of, q1 dot q2 > 0 results in the short turn, q1 dot q2 < 0 takes the long turn. –  falstro May 15 at 9:58
add comment

Just because it hasn't been mentioned. Since quaternions used for spatial orientation are always unit length (or should be), the following will also work.

abs(q1.dot(q2)) > 1-EPS

where EPS is some fudge factor to allow for small errors due to limited floating point precision. If (and only if) both quaternions represent the same orientation then q1 = +- q2, and thus q1.dot(q2) = +- 1. If you want to make sure they're the same rotation (rather than just orientation), then remove the abs.

share|improve this answer
    
Actually I said that :) –  bogglez May 15 at 16:36
    
@bogglez true. Was hidden in the tl;dr text. :) –  falstro May 15 at 16:46
    
Haha. Long introduction because somebody commented it would be enough to check for equality! –  bogglez May 15 at 17:53
    
+1, pretty elegant and, perhaps even more numerically efficient than my answer (provided SIMD operations are used :) ). –  teodron May 16 at 13:25
add comment

Quaternions are stored as 4 floats or doubles, often called x, y, z and w, where the first three represent an axis and w the degree of rotation around that axis.

A naive approach would be to just compare those numbers of two quaternions for equality. However, because floating point calculations involve an error, you should at least use an error, often called eps (for epsilon) and compare each component like

    double const eps = 1e-12; // some error threshold
    abs(quat1_x - quat2_x) < eps // similar enough?
    // repeat for other values..

A better test would be to calculate the dot product of the two quaternions and test whether it is close to 1.0. You should look up the equation of quaternions with sin and cos and just dot two quaternions, then you should readily see why this works.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.