Torque as Quaternion

Started by
8 comments, last by DrGUI 19 years, 1 month ago
In my thread 'Moment to Orientate Object', two cool people, hplus0603 and oliii suggested some great solutions, however, this require me to be able to apply the moment or torque as a quaternion. I need you! Here is how I apply a vector as a moment in my numerical integrator (only simple Eular ATM): //Angular //body.AccelerationAngular = body.InertiaInverse * // (body.Moments - // (body.VelocityAngular ^ // (body.Inertia * body.VelocityAngular))); body.AccelerationAngularBody = Vector3.TransformNormal(momentsBody - (Vector3.Cross(body.VelocityAngularBody, Vector3.TransformNormal(body.VelocityAngularBody, body.InertiaBody))) , body.InertiaBodyInverse); ... //Angular body.VelocityAngularBody += body.AccelerationAngularBody * timeDelta; body.Orientation += QuaternionMath.Scale(QuaternionMath.Multiply(body.Orientation, body.VelocityAngularBody), 0.5f * timeDelta); Cheers!
Advertisement
A quaternion represents a rotation, i don't see how it could represent a vector quantity in 3D, which torque is. I'm using Dave Eberly's examples, representing the torque as a function returning a Vector3.
torque and rotation velocity is just vectors, parallel to axis of rotation and with length proportional to magnitude of torque or rotation speed. That way, vector addition and subtraction produce meaningful results. In all my programs, things like rotation velocity is vectors. It can be sometimes arguably better/more efficient to use vector-and-scalar instead, where vector is unit-length, and scalar is magnitude of rotation velocity, but normally, in physics, rotation velocity and torque is just vectors.
see this article for a simple example of how to integrate a quaternion orientation from torque and angular momentum vectors

http://www.gaffer.org:8080/articles/Physics3D.html

source code implementing what is described in the article is available here:

http://69.55.229.29/downloads/GamePhysics.zip
I think he already knows how to integrate with quaternions - he's doing it in his code. He's asking about something else.

I'm just learning physics myself, so I'm just offering some thoughts, not answers. I read this and your other thread, and I have a couple questions about what you're trying to do. I gather you have an object that you want to orient towards another object, and you want to achieve this through physics simulation rather than direct manipulation of the object's orientation. So:

1. Is the object constrained to be stationary? Or does it translate as well as rotate?

2. Can it rotate about any axis? Or is the rotation constrained?

3. Is it a 'free' object? Attached to a joint? Part of a hierarchy?

4. Do you want to orient towards the target in one step? Over a particular time interval? Just move in that direction?

The best solution will be dependent on the above questions. But here are some general thoughts.

When you say 'apply a quaternion as torque', I take that to mean you have a quaternion that represents a rotation from one orientation to another, and you want to apply a torque that will result in that rotation.

As I understand it, the direction of a torque vector is parallel to the axis about which it induces rotation. Torque is change in angular momentum, and angular momentum is related to angular velocity via the inertia tensor.

The vector portion of a quaternion represents the (scaled) axis of rotation, so a corresponding torque should be parallel to this axis. As for the length of the torque vector, we simply have to decide how much acceleration we want to induce, or how 'quickly' we want to get moving in that direction.

To better choose the length for the torque vector, we would need to know more, such as over what time interval you wanted the rotation to occur.

It would be useful in addressing your question to examine your code, but I must admit I find it a little hard to read :-) I don't think there's much to be gained performance-wise by combining the operations. It would be easier to follow if each operation were on a separate line and clearly labeled. I'm sure the code is correct, but it would still be informative to be able to easily read through it.

Standard disclaimer: I don't have enough experience in math and physics to gaurantee the accuracy of the above information, so I may have gotten something wrong somewhere (in which case I hope I'll be corrected).

[Edited by - jyk on March 10, 2005 11:54:21 PM]
Quote:Original post by jyk
I think he already knows how to integrate with quaternions - he's doing it in his code. He's asking about something else.
.

i doubt it. torque and angular momentum are simply not representable as quaternion values.
Sorry, I should have provided a link to my other thread to clarify:
Moment to Orientate Object

I use vectors to represent torque at the moment, but I am trying to implement the suggestions in the thread above.

jyk,
1. yes, the object can be translated
2. it can rotate around any axis (I don't think I would know how to constrain anyway)
3. free object
4. I want to orientate it in a time period, or apply a torque that will turn it in around that amount of time (manual tuning - not too critical)

I'll outline my basic idea (actually the concept was a friend's):
Rock Paper Scissors
There are two yellow spherical face on either side of the screen grinning manically at you, with their hands close to them (left face has hand on right side and vica versa). When you make a selection, the hands bob up and down on a sine wave, then are, under the control of the physics simulator, propelled toward each other with some random variation. This variation gives some nice angular effects when they collide. To make them collide, they home in on each other and orientate to each other. The loser hand dies in some way (just fades ATM), then the winning hand carries on to hit the loser face which also dies.
I currently set the orientation of the hands. Now, I would like to fully simulate the hands to give greater realism, which means that angular effects and so my lighting and cartoon rendering can be shown off.

Just to clarify: I have already got my physics simulator working with torque as a vector, collision detection with spheres, and collision response.

Thank you very much for your help

EDIT: jyk seems to be on the right lines...
EDIT: quoted wrong bit[grin]
Quote:
The vector portion of a quaternion represents the (scaled) axis of rotation, so a corresponding torque should be parallel to this axis. As for the length of the torque vector, we simply have to decide how much acceleration we want to induce, or how 'quickly' we want to get moving in that direction.


[Edited by - DrGUI on March 13, 2005 3:49:05 AM]
Quote:i doubt it. torque and angular momentum are simply not representable as quaternion values.
I mentioned applying a torque to induce a specific rotation, but never said anything about representing torque or angular momentum as quaternions.

But maybe I'm misunderstanding your post.
I had a look at Gaffer's page:
Quote:
void recalculate()
{
angularVelocity = angularMomentum * inverseInertia;

orientation.normalize();

spin = 0.5f * Quaternion(0, angularVelocity.x, angularVelocity.y, angularVelocity.z) * orientation;
}


To apply a quaternion as suggested in my other thread, could I just multiply with that quaternion rather than the vector? My trouble would be apply the inertia tensor to it though...

Here are the suggestions quoted:
Quote:Original post by hplus0603
apply counter-torque as a quaternion (if you have "apply torque as quaternion" in your engine).

Quote:Original post by oliii
AddAngularAcceleration(fAngAccel, xAxisOfRotation);


Anyone know how to implement these?
Ratings 4 u!
I got it working using oliii's orientation code and jyk's observation about torque, thanks everyone.
Here is the working code if you are interested (C#). It works with parellel vectors. I don't know why I had to negate the toTarget vector, but hey, it works:
Vector3 homingAccelBody = new Vector3(0, 0, 0); //default to no accelerationfloat timeToIntercept = toTarget.Length() / Velocity.Length(); //based roughly on distanceif (!float.IsInfinity(timeToIntercept)) //is infinity if velocity is 0{	//Get the normalized target direction	Vector3 targetDirN = -toTarget;	targetDirN.Normalize();	//Get the normalized current forward vector	Vector3 currentDirN = QuaternionMath.VectorRotate(Orientation, new Vector3(0, 0, 1)); //normalized enough	//Calculate the axis of rotation and the difference around it between current and target directions	Vector3 axisOfRotation = Vector3.Cross(currentDirN, targetDirN);	axisOfRotation.Normalize();	float cosDeltaAngle = Vector3.Dot(currentDirN, targetDirN);	System.Diagnostics.Debug.Assert(-1 <= cosDeltaAngle && cosDeltaAngle <= 1);	float deltaAngle = (float)System.Math.Acos(cosDeltaAngle);	//Work out the current rotation around the axis	float velAngle = Vector3.Dot(VelocityAngular, axisOfRotation);	//Calculate the acceleration aorund the axis needed to get to targetDir at time + timeToIntercept	float accelAngle = -2.0f * (deltaAngle + velAngle * timeToIntercept) / (timeToIntercept * timeToIntercept);	//Scale the axis by the angle to get the torque then rotate it to body space	if (!float.IsNaN(accelAngle)) {		Quaternion worldToBody = QuaternionMath.Conjugate(Orientation);		worldToBody.Normalize();		homingAccelBody = QuaternionMath.VectorRotate(worldToBody, axisOfRotation * accelAngle);	}}

This topic is closed to new replies.

Advertisement