Quaternion Gimbal Locks with applyTorqueImpulse

jmclaine
Posts: 2
Joined: Mon Jun 17, 2013 8:35 pm

Quaternion Gimbal Locks with applyTorqueImpulse

Post by jmclaine »

The following will Gimbal Lock, and I have no idea why:

Code: Select all

btRigidBody* mRigidBody;

// Must be called or it will stop moving.
mRigidBody->activate();

// Not sure if this matters, but...
mRigidBody->applyCentralImpulse( btVector3( impulseX, impulseY, impulseZ ));

// Gimbal Locks Pitch when Yaw is at 90 degrees.
mRigidBody->applyTorqueImpulse( btVector3( mAngularSpeedY, mAngularSpeedX, 0 ));
The strange thing is that all the other objects not forcing impulses do not gimbal lock.

I have also tried:

Code: Select all

btTransform transform = mRigidBody->getWorldTransform();
btQuaternion rotation = mRigidBody->getOrientation();

transform.setRotation( btQuaternion( btScalar(mAngularSpeedY), btScalar(mAngularSpeedX), btScalar(0) ) * rotation );
mRigidBody->setWorldTransform( transform );
etc.

The quaternions always Gimbal Lock. Is there a way to rotate rigid bodies manually without Gimbal Lock?
jmclaine
Posts: 2
Joined: Mon Jun 17, 2013 8:35 pm

Re: Quaternion Gimbal Locks with applyTorqueImpulse

Post by jmclaine »

After further testing...

The applyTorqueImpulse does indeed Gimbal Lock, however, I found a solution that may be useful to others.


Reverse multiplication order.

This will prevent the locking, but will reverse rotation directions if pitch exceeds -90 or 90 degrees.

Additionally, there is no slerp between rotations so the changes are rough.

Behaves as expected.

Code: Select all

btTransform transform = mRigidBody->getWorldTransform();
btQuaternion rotation = mRigidBody->getOrientation();

transform.setRotation( rotation * btQuaternion( btScalar(mAngularSpeedY), btScalar(mAngularSpeedX), btScalar(0) ));  // reverse multiplication
mRigidBody->setWorldTransform( transform );


Additionally, I have found that many people have questions about how to create a camera.

I hope the following will be useful for those that really want a smooth camera using Bullet Physics.

* Sorry. No perspective or view transform given. That goes into another realm. *

Code: Select all

// Move in a direction. Should be getting orientation matrix Right, Up, and Forward.
mRigidBody->applyCentralImpulse( btVector3( impulse.x, impulse.y, impulse.z ) * mSpeed );

// Rotate using interpolated quaternions.
btTransform transform = mRigidBody->getWorldTransform();

btQuaternion qCurrent = transform.getRotation();

static btQuaternion qFinal = qCurrent;

// btVector3 diff => rotation vector (i.e. Euler)
if( diff.length2() > 0 )
{
	static btVector3 rot;
	rot += diff * DEGREES_TO_RADIANS;
	
	qFinal = btQuaternion( rot.x, rot.y, rot.z );
}

// For some reason, the slerp likes to call an assert.  The if statement prevents it from being called.
// clamp => clamp value to between 0 and 1 (in this case)
if( qCurrent.length2() > 0 && qFinal.length2() > 0 )
	transform.setRotation( slerp( qCurrent, qFinal, clamp( deltaTime * mAngularSpeed, 0.0f, 1.0f )));

mRigidBody->setWorldTransform( transform );
nhughes
Posts: 1
Joined: Sat Aug 31, 2013 7:36 pm

Re: Quaternion Gimbal Locks with applyTorqueImpulse

Post by nhughes »

Quaternions, inherently, are not subject to gimbal lock. Please see my material at

noelhughes.net

for comprehensive material on quaternions.

Noel Hughes