apply a force/impulse relative to a rigidbody

Post Reply
beaugard
Posts: 8
Joined: Sat Feb 16, 2008 5:12 pm

apply a force/impulse relative to a rigidbody

Post by beaugard » Sun Jul 13, 2008 10:44 pm

I am designing a simple controller for my player class, which is a simulated rigid body. What I want is to attach "thrusters" to the rigid body which can be manipulated by a throttle - so I want to apply the scaled force to the body in object space, so to say.

Since the applyForce method takes a force vector in world space, I have to transform my original vector.
I tried simply rotating the vector like this:

Code: Select all

	btQuaternion worldQuat(body_->getOrientation());
	btVector3 rotaxis(worldQuat.getX(), worldQuat.getY(), worldQuat.getZ());
	if(rotaxis.length() > 0)
		rotaxis.normalize();
	fvec = fvec.rotate(rotaxis, worldQuat.getW());
but this gives me the wrong result. I also tried other methods for rotating, as well as home-brew matrix code, but to no avail. By now this simple problem is eating my brain.

What is the right way of achieving the transform?

beaugard
Posts: 8
Joined: Sat Feb 16, 2008 5:12 pm

Re: apply a force/impulse relative to a rigidbody

Post by beaugard » Tue Jul 15, 2008 10:16 pm

Maybe my previous question was a bit fussy. I have made a simpler controller test to specify my problem better.

Now I want to simply apply a force on an axis in local space/object space. This is how I do it (doesn't work):

Code: Select all

void SimpleRigidBodyController::applyForce(size_t axis, btScalar amount)
{
	btTransform tr = body_->getWorldTransform();
	btVector3 force;

	btVector3 orforce(0,0,0);
	orforce[axis] = 1;
	force = tr.getBasis() * orforce;
//Alternative to matrix multiplication, doesn't work either.
//	force = quatRotate(tr.getRotation(), orforce);

// Alternative to the above block? Doesn't work either.
//	force = btVector3 (tr.getBasis()[0][axis], tr.getBasis()[1][axis], tr.getBasis()[2][axis]);

	force *= amount * FORCE_SCALING;
	body_->applyCentralForce(force);
}
It works as long as the basis is identity, but as soon as I rotate, everything breaks down (movement is not as expected). Could someone enlighten me on what I am doing wrong? It seems to me to be an embarrasingly simple problem but I've been banging my head against this for way to long and just can't get it right!

artcar12
Posts: 2
Joined: Mon Mar 15, 2010 1:29 pm

Re: apply a force/impulse relative to a rigidbody

Post by artcar12 » Mon Mar 15, 2010 2:51 pm

I have the same problem and I cannot find any clear answer on this forum or anywhere else for that matter. I want to apply a force to a body relative to the direction that it is facing. Ie I have a box laying on the ground and I use applyforce(0,10,0) and it goes straight up in the air. When the box flips over, the same call applyforce(0,10,0) should now push it into the ground because it is applying the force based on which way the object is facing.

This would seem like such a common problem that it would be addressed in the tutorial section. But like I said I can't find a way to do it. If someone has a concise snippet could you please post it?
Last edited by artcar12 on Tue Mar 16, 2010 5:30 am, edited 2 times in total.

InvisibleCalm
Posts: 4
Joined: Sat Jan 09, 2010 12:10 am

Re: apply a force/impulse relative to a rigidbody

Post by InvisibleCalm » Mon Mar 15, 2010 5:55 pm

Wow, this is an old thread. Not sure if this is the correct answer or not, but I just wrote some code to do this over the weekend. If you get your RigidBody's btTransform and then multiply it by your force as a btVector3 and subtract the RigidBody origin from that, the return will be your force relative to your object's orientation. Now just apply this as a centeralForce/Impulse (remember per simulation tick).

Basically:

Code: Select all

btVector3 relativeForce = btVector3(0,10,0);
btTransform* boxTrans;
boxRigidBody->getMotionState()->getWroldTransform(boxTrans);
btVector3 correctedForce = (boxTrans * relativeForce) - boxTrans.getOrigin();
boxRigidBody->applyCentralForce(correctedForce);

artcar12
Posts: 2
Joined: Mon Mar 15, 2010 1:29 pm

Re: apply a force/impulse relative to a rigidbody

Post by artcar12 » Tue Mar 16, 2010 5:37 am

The code above works. Thanks, you have no idea how long I banged my head against this.

User avatar
rponomarev
Posts: 56
Joined: Sat Mar 08, 2008 12:37 am

Re: apply a force/impulse relative to a rigidbody

Post by rponomarev » Wed Mar 17, 2010 7:27 pm

Hello,

Try this to avoid extra calculations:

Code: Select all

btVector3 relativeForce = btVector3(0,10,0);
btMatrix3x3& boxRot = boxRigidBody->getWorldTransform().getBasis();
btVector3 correctedForce = boxRot * relativeForce;
boxRigidBody->applyCentralForce(correctedForce);
Hope this will help,
Roman

User avatar
ejtttje
Posts: 96
Joined: Mon Nov 03, 2008 9:57 pm

Re: apply a force/impulse relative to a rigidbody

Post by ejtttje » Thu Mar 18, 2010 7:31 pm

Also, for anyone reading through this, original post is very convoluted (and actually, incorrect; W is not the angle) method of using a quaternion to rotate a vector... don't convert back to axis/angle, just use the quaternion's operator*:

Code: Select all

btQuaternion worldQuat(body_->getOrientation());
fvec = worldQuat * fvec;
However btRigidBody (via its superclass btCollisionObject), internally stores a btTransform, so it is more efficient in this case to use body->getWorldTransform().getBasis() to use the 3x3 rotation matrix instead of converting to a quaternion (as pointed out in previous post)

Post Reply