Quaternions

BlitzMax Forums/BlitzMax Programming/Quaternions

Chroma(Posted 2007) [#1]
I'm a fan of quaternions, actually I'm addicted to them. I understand fundamentally how they work. I've ported a lot of quaternion code and libs for my own use. What I'd like to do here is get opinions and knowledge from some of you who have better insight about them than I do. Here's what I know about them:

1. Made up of w,x,y,z
2. they are unitless
3. 1,0,0,0 is called an identity
4. they avoid gimbal lock

There's also something called angle-axis that I've recently come across. It looks like angle-axis is a GL thing that's used to access a quaternion and rotate the model in GL.

Through my personal experience I know that when you're using quats you are dealing with VERY small numbers. Stuff like 0.0001 gives you a decent turn speed. Putting 0.1 into a quat makes is spin like it's possessed.

Please post what you know about them and also your experiences with quaternions, good or bad. Maybe we can all learn from each other.


FlameDuck(Posted 2007) [#2]
Quaternions are non-commutative (which means that factorial order is important) complex numbers with one real component (w) and 3 imaginary parts, useful in spatial dynamics and physics for calculating orientation.

Angle-axis, on the other hand is a one-dimensional rotation around an arbitrary three dimensional axis.

While the number of components needed to represent an orientation are the same in both cases, they are not immediately interchangeable.


Chroma(Posted 2007) [#3]
FD, all rotations are a one-dimensional rotation around an arbitrary three dimensional axis. The axis direction is defined by the x,y,z component which actually is just a direction vector showing where the axis is pointed. The angle is the rotation speed in radians. That's why quaternions are so useful for rotations, because they are set up just like that.

q = rotation speed in radians
x = direction vector component x (normalized)
y = direction vector component y (normalized)
z = direction vector component z (normalized)

Once you get your head around the fact that an object can only spin on one axis and that the axis is a direction vector, it all falls into place nicely.

Here's linear movement (simplified):
force = 0
acceleration = force / mass
velocity :+ acceleration * dt
position :+ velocity * dt

Rotation has equivalent components:
torque = 0
angularAcceleration = torque / inverseMass
angularVelocity :+ angularAcceleration * dt
orientation = 0.5 * Quaternion(0, angularVelocity.x, angularVelocity.y, angularVelocity.z) * orientation

I may be slightly off on the rotation and I'm still identifying the correction sequence and terminology.


big10p(Posted 2007) [#4]
I've looked into learning about quaternions, but every site I've visited quickly descends into math moonspeak.

I figure life is too short to bother.


Chroma(Posted 2007) [#5]
I know what you mean big10p. I understand them basically now. And if you put it in simple terms it's not too bad.

Pseudo-code:
torque.zero()
torque.x = 1.0
angularMomentum :+ torque * dt
angularVelocity = angularMomentum * inverseInertiaTensor
orientation.normalize()
spin = 0.5 * Quat(0, angularVelocity.x, angularVelocity.y, angularVelocity.z) * orientation
orientation :+ spin * dt
euler = EulerFromQuat( orientation )
RotateEntity blah, euler.x, euler.y, euler.z

This works really well. But there are some things I've noticed. The z axis is always a local rotation while the x and y axis rotate globally. I'm not sure if this is normal. Does anyone else know?


Gabriel(Posted 2007) [#6]
Why are you converting from Quat to Euler? That's only going to get you into trouble, as there are an infinite number of euler angle combinations for any given Quaternion orientation. If, for example, you add render tweening into the mix, kaboom!


Chroma(Posted 2007) [#7]
Then would you suggest converting Quat to Angle-Axis? Either way you have to get it down to the euler angles so you can use RotateEntity. What am I missing?


Gabriel(Posted 2007) [#8]
Well this is in the BlitzMax forum, so I didn't necessarily assume that you were using Blitz3D or even MiniB3D. I mean you're right that if all you've got is TurnEntity, you've got to come back to Euler Angles, and I don't think it will matter how you get there. I don't know, but I don't think Axis Angles will help you, there are still an infinite number of Euler represenations.

If you're using B3DSDK, why are you using quaternions at all? If you're using MiniB3D, doesn't it have any matrix or quaternion commands? If not, could you not add some? You seem to be proficient with Quaternions, so I would have thought a GetQuaternion() and SetQuaternion() function pair would have been ok.


Chroma(Posted 2007) [#9]
Well this is in the BlitzMax forum, so I didn't necessarily assume that you were using Blitz3D or even MiniB3D.
I'm using BlitzMax. Hence that's why it's in the BlitzMax forum.

I mean you're right that if all you've got is TurnEntity,
TurnEntity? There's RotatEntity too.

you've got to come back to Euler Angles, and I don't think it will matter how you get there.
It does matter. It also matters in what order you do the rotations.

I don't know, but I don't think Axis Angles will help you, there are still an infinite number of Euler represenations.
Angle-Axis is actually pretty handy to use in OpenGL. No idea what you mean by the inifinite number of Euler representations, but I'm looking for 6DOF (no gimbal lock). And to expand on that a bit, I'm looking to get this working right so I can add torques at certain locations (aileron etc).

If you're using B3DSDK, why are you using quaternions at all?
I never stated I was using B3DSDK. I'm using quaternions to avoid gimbal lock...

If you're using MiniB3D, doesn't it have any matrix or quaternion commands?
I'm sure you're quite aware that MiniB3D has matrix and quats in it.

If not, could you not add some?
It already has some...

You seem to be proficient with Quaternions,
Not really but I'm getting there. Thanks for the compliment.

so I would have thought a GetQuaternion() and SetQuaternion() function pair would have been ok.
Sure that sounds ok to me. That why I put those commands in my own quat lib about 3 years ago...

Please, if you actually would like to help that'd be great man. I'm just stuck on trying to do local rotations. As in taking the current orientation and adding the new rotation to it. Which I thought I was doing but it's not working quite right.


Gabriel(Posted 2007) [#10]
I don't know what all the hints and comments about what I'm supposed to know and not know are all about. I don't know if you think I have the solution and I'm just being difficult or something, but my crystal ball is in for repairs so I don't know half of what you appear to think I do or think I should know.

Anyway, in short, I don't know why you think that axis angle rotations will be any different to quaternions, because they're practically the exact same thing, as you yourself stated when you replied to FlameDuck. If you're convinced they are, go ahead and prove me wrong.

You get an infinite number of Euler representations because 360,720,0,-360,1080,-720,-1080, ad infinitum are all the same angle. Getting back -180 when you expected 180 is why things like tweening and interpolation will make things explode.

You don't need quaternions to avoid gimbal lock. It's just one ( possibly over complicated ) way of avoding gimbal lock. There's a good article on Nehe about the mythical necessity of quaternions for flight sims. I have nothing against them, I use them, but I use them because I need them, and I think they're too fussy to bother with unless you *really* need them.

As I said, I have no idea why you think I know so much about MiniB3D and I'm just holding back from helping you, but I know absolutely nothing about it apart from that it uses OpenGL. If it already has quaternions as you say ( and apparently you're sure I know ) then just use them instead of TurnEntity and RotateEntity. Then all your tweening and interpolating problems, not to mention the imprecise nature of Quat>Euler conversions will be gone.

I think that answers everything I can answer. There isn't any more. I'm not holding back or being difficult, I'm just trying to help despite not being a MiniB3D user, an OpenGL coder or a flight-sim programmer.


Chroma(Posted 2007) [#11]
Nah I don't think any of that. I'm just looking for people to post what they know about quaternions. Ok cool I'll check out NeHe and see what I can find out.

Also I think quats make applying torque to rotations really easy. I'm just missing something somewhere in my code. Hopefully I'll figure it out soon. Worst case scenario is that everything is working fine and I'm apply torque in the wrong manner... I may be applying torque in a global manner instead of applying torque to the rotated orientation and then computing it.

I think you're assuming I'm using turnentity and rotatentity in the rotation code itself. I'm use using RotateEntity to do the final visual rotation of the 3d model, that's all.

Thanks for the tips.


Chroma(Posted 2007) [#12]
I think what my big problem is, is trying to duplicate the TForm commands from B3D. As in you have an aileron positioned in local space. The aircraft rotates and the aileron changes places in global space. I need to know how to rotate a point locally using a quaternion. Gah...


Damien Sturdy(Posted 2007) [#13]
Ehhh. sounds like you need to look up Matrix stuff... :)

Multiply the global matrix by the local matrix and you get a matrix containing that global point as if it was in "local space" to its parent.

I recently got my head around this myself. it's not as scary as it sounds!


Chroma(Posted 2007) [#14]
I could have sworn you could rotate points with quaternions and avoid matrices altogether. I must be doing something wrong. If I figure it out I'll post it Cyg.


JoshK(Posted 2007) [#15]
I have this. I don't really remember what I wrote it for:

Function RotatePointAroundVector(x#,y#,z#,u#,v#,w#,a#)
ux#=u*x
uy#=u*y
uz#=u*z
vx#=v*x
vy#=v*y
vz#=v*z
wx#=w*x
wy#=w*y
wz#=w*z
sa#=Sin(a)
ca#=Cos(a)
VECTOR_x#=u*(ux+vy+wz)+(x*(v*v+w*w)-u*(vy+wz))*ca+(-wy+vz)*sa
VECTOR_y#=v*(ux+vy+wz)+(y*(u*u+w*w)-v*(ux+wz))*ca+(wx-uz)*sa
VECTOR_z#=w*(ux+vy+wz)+(z*(u*u+v*v)-w*(ux+vy))*ca+(-vx+uy)*sa
End Function


Gabriel(Posted 2007) [#16]
Halo's code looks good at a glance but if you need any more help, I have a TFormPoint in my engine which works entirely with Vectors and Quaternions, no matrices. It will only look like pseudo code without all my maths classes ( which are messy and besides you have your own and Halo posted his recently ) but they will give you the method you need to do it.


Chroma(Posted 2007) [#17]
Sure that would be awesome Gab.