Mixing Euler and Quaternion Math?
Miscellaneous Forums/General Discussion/Mixing Euler and Quaternion Math?
Does anyone have any good links on mixing Euler and Quaternion Math? I'm having a nasty bug in my game engine from effectively doing this :
GetEulerRotation()
SetEulerRotation()
GetQuatOrientation()
SetQuatOrientation()
The X axis ( both Euler and Quaternion ) are slowly drifting away from 0. I'm not sure if this is a bug in my code, a bug in the 3d engine I'm using or a problem inherent with using two different orientations. I was inclined to think the latter, but I'm suspicious that it only affects the x axis. Also Ogre seems to use mix both coordinate systems happily and I believe B3D even mixes both internally, so that makes me suspicious too.
So I'm wondering
A) Does this seem right that it should be happening?
B) Do you have any good reading material on quats and eulers playing happily ( or not! ) together for me?
Any help much appreciated, it's extremely annoying at the moment.
Quats need to be normalised or errors begin to creep in. Not sure if this would cause your problem though.
Also, it may simply be a matter of floating point rounding errors.
I don't think that would be the problem, but perhaps I'm wrong. I'm not altering the quaternion values at all. I just sent back what it gives me after all, so if it were a problem it would be engine-side.
Since 0,0,0 on Euler Axes is 1,0,0,0 on Quaternion, it shouldn't even be a problem with floating point math. Actually, if it was floating point inaccuracy, it should affect all three/four axes anyway, I guess. And again if it is floating point inaccuracy, it must surely be engine-side because it would eventually settle upon a value it could represent without inaccuracy, surely? It wouldn't have a constant increase like that.
I found trying to mix euler and quaternion values to be a royal pain in the backside. I came to the conclusion that they should/could not be mixed without getting some really strange results. The system I use to get perfectly accurate results is that I take an initial euler rotation and convert it to a quaternion. ALL calculations are then carried out using quaternions only. The final quaternion result is then converted back to a euler rotation. This works fine for me without any issues.
You also need to check that the quat/euler conversion functions you are using are correct - there are a lot out there that are just plain wrong or are designed for different coordinate systems and will require tweaking.
it sounds like what Flameduck says, and atm there is no fix for rounding errors that I have come across.
it sounds like what Flameduck says, and atm there is no fix for rounding errors that I have come across.
Then why do the other components which hold the exact same values remain unaffected?
You also need to check that the quat/euler conversion functions you are using are correct
I'm not using any. They're all part of the engine.
You might be right about the systems being incompatible though. I had in mind to do exactly what you describe. I couldn't find any documentation on doing it though. Do you have any links on doing it that way?
What if you reverse the order?
That's just it there is no order, and no rotation. I'm creating a mesh and leaving it's rotation as 0,0,0 in Euler angles ( which I believe is 1,0,0,0 in Quaternions. I do not rotate it at all. The only thing I do is as shown above. Get the rotation, and set the same value back. Get the orientation and set the same value back. Nothing should change, and the y and z coordinates do not change. Just the x.
I mean:
GetQuatOrientation()
SetQuatOrientation()
GetEulerRotation()
SetEulerRotation()
Why do you need to keep getting and setting?
I mean:
GetQuatOrientation()
SetQuatOrientation()
GetEulerRotation()
SetEulerRotation()
Doh! Sorry, I thought you meant order of rotations. Good question. Let me try that..
Same result. Well I didn't check the exact amounts by which they're changing, but as far as the eye can see without a calculator and a very long sheet of paper, exactly the same.
Why do you need to keep getting and setting?
Eulers - because the engine simply needs the ability to get and set angles of objects. It's a pretty basic requirement that I be able to retrieve the orientation of an object, change it and put it back.
Quaternions - In order to implement render tweening. Euler angles cannot be tweened, only quaternions, which have to be SLERP'ed.
Why put it back if the values haven't changed at all?
It's a demonstration. Normally they will have changed, and they go far far worse than this. For demonstration purposes, putting them back when they haven't changed is the only way to determine if they're changing when they shouldn't.
REMOVED: I thought I had it, but it was just a cached module giving me false hope.
EDIT: Grr.. done it again.
Umm, i would have thought you will always get rounding converting between the two, in blitz3d you need to force a quart to euler conversion to see the error:
Graphics3D 640,480
c=CreatePivot()
TurnEntity c,0,30,0
TurnEntity c,0,-30,0
Print EntityYaw(c)
if you stopped editing your posts it would be interesting to compare the errors
Yes sorry, I edited my post because the problem wasn't actually occuring in TV, not because it was occuring in Blitz3d. It doesn't occur in either if I don't use quaternions, nor if I don't use Euler, only if I use both. But SEPARATELY.
Yes, of course you get errors if you start actually transforming the entity, but I'm NOT transforming anything. I just leave it at 0,0,0 which is 1,0,0,0 in Quaternion orientation. Both 1 and 0 can be realized correctly in floating point math, so there is nothing to be incorrectly rounded by floating point inaccuracy. I should be setting and getting it at 0,0,0 and 1,0,0,0 over and over.
Furthermore, I'm not converting between the two though, am I? I'm getting Euler, setting Euler, and separately getting Quat, setting Quat. And again, the only values they should ever have are 1.0 and 0.0 which can both be expressed as floating point numbers.
And further proof for those who doubt me ( even though the fact that all other axes hold the same values but are unaffected should be proof enough ) here's an interesting tidbit. If I create a mesh in TV3D and don't set it's rotation, orientation or matrix, guess what? It isn't at 0,0,0 at all.. it's at 0.01978234,0,0 and guess what the first value is when the bug occurs in my above example? Yes, that's right, it's 0.01978234
Now I don't know about you, but it seems a little bit coincidental to me that all meshes are initially rotated to exactly the same floating point value ( to 8 decimal places, no less ) when you don't do anything as they are with the above code.
That's what? A one in 10,000,000 chance? 30,000,000 if you consider that it could have happened on two other axes, I guess. It just happens to be on the x coordinate.
If it's 'drifting' (by a 'small' amount), it's probably a floating point precision issue.
It's likely to show up more on axis than another depending on the order of operations.
Not needed. See below.
No need to worry any more anyway. I've just talked to engine creator on IRC who confirmed that it's not floating point inaccuracy. We dicussed the problem and the solution and we both think that using Quaternions for everything is probably the best one. I had a feeling that might be the best solution before I started, and when Ricky said the same thing, it kinda validated it because you must have gone through hell with rotations creating Pacemaker.