Dynamic body linked to Kinematic body by hinge constraint

Post Reply
tomhog
Posts: 6
Joined: Mon Jul 04, 2011 4:37 pm

Dynamic body linked to Kinematic body by hinge constraint

Post by tomhog »

Hi All

I'm using bullet to simulate a player holding a piece of wood.
The piece of wood is offset just infront of the player pointing upward. This is the dynamic body

The player can rotate the camera, and with it a kinematic body offset to the base of the dynamic body

The wood dynamic body is linked to the players kinematic body via a hinge contraint.

So when the player rotates the camera, it rotates the kinematic body (via a motionstate) and with it the hinge
and the attached dynamic body.

This works and I can rotate around, with the wood following me.

The problem is, if I rotate too quickly, the dynamic body (wood), vibrates side to side.
Only a small distance but at a high frequency so it is noticeable.

Below is my code, I'm afraid I'm using osg bullet so it may look a little strange

Code: Select all

 axeOffset = axenode->getWorldMatrices()[0];//*osg::Matrix::translate(comOffset);
    
    _playerMotionState = new GyroAttachedMotionState(axeOffset);
    
    btRigidBody::btRigidBodyConstructionInfo rbInfo(btScalar(0), _playerMotionState, new btBoxShape(btVector3(1.0f, 1.0f, 1.0f)),
                                                    btVector3(btScalar(0), btScalar(0), btScalar(0)));
    playerBody = new btRigidBody(rbInfo);
    playerBody->setCollisionFlags(playerBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
    playerBody->setActivationState(DISABLE_DEACTIVATION);
    
    osgBulletUtils::getPhysicsWorld()->addRigidBody(playerBody);
    
    axenode->setMatrix(osg::Matrix());
    axenode->getParent(0)->removeChild(axenode);
    scene->asGroup()->addChild(axenode);
    
    //create the rigid body represnting the axe
    osg::ref_ptr< osgbDynamics::CreationRecord > cr = new osgbDynamics::CreationRecord;
    cr->_sceneGraph = axenode; //use the axe sub graph to generate the body
    cr->_mass = 1.;
    cr->_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; //try using  tri mesh to represent the axe
    cr->_parentTransform = axeOffset; //axe pivot seems to alreadt be at origin so we can use identity
    //cr->setCenterOfMass(comOffset);
    axeBody = osgbDynamics::createRigidBody( cr.get());
    axeBody->setActivationState( DISABLE_DEACTIVATION );
    
    //add the rigid body to the physics sim
    osgBulletUtils::getPhysicsWorld()->addRigidBody(axeBody, COL_AXE, axeCollidesWith);
    
    //compute the position of the hinges pivot
    //in axeBody coord space
    osg::Vec3 osgOrigin = osg::Vec3(0.0,0.0,0.0);
    btTransform m = axeBody->getWorldTransform();
    btVector3 v = m.getOrigin();
    osg::Vec3 bulletOrigin = osgbCollision::asOsgVec3(v);
    osg::Vec3 axisOffset = osgOrigin - bulletOrigin;
    
    //create the physics hinge to constrain our rigid body
    const btVector3 btPivot = osgbCollision::asBtVector3(axisOffset);
    btVector3 btAxisA( 1.0f, 0.0f, 0.0f );
    btVector3 btPivotB( 0.0, 0.0f, 0.0f );
    hinge = new btHingeConstraint( *axeBody, *playerBody, btPivot, btPivotB, btAxisA, btAxisA );
    hinge->setLimit( M_PI*0.25f, M_PI );
    
    //apply a motor to the axe hinge so it pushes back against the log
    //and back into position when removed
    float	targetVelocity = -100000.0f;
    float	maxMotorImpulse = 100000.0f;//this has to be high enough to resist the axe falling back
    hinge->setMotorTarget(0, 2.0f);
    hinge->enableAngularMotor(true, targetVelocity,maxMotorImpulse);
    
    //add the hinge to the physics world
    osgBulletUtils::getPhysicsWorld()->addConstraint( hinge, true );

The motor force is to stop the piece of wood falling backward, the limits then stop
it going too far forward. The idea is that the hinge will allow the user to walk
into objects and the piece of wood will lean backward a little rather then just trying
to drive straight through it (like if it was a kinematic object).

Anyhow, I hope I've explained myself. Any more info needed let me know

Cheers
Tom

PS
The sim is running at around 40 fps if it's relevant
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: Dynamic body linked to Kinematic body by hinge constrain

Post by Erwin Coumans »

One way to resolve this is to adjust the velocity (and possibly position) of the dynamic body based on the kinematic body, so that it travels at the same speed, before the physics simulation, and then let the physics simulation deal with the remaining errors.

Is there a way to directly re-position the dynamic body?

You can compute the linear and angular velocity of the kinematic object, and pass it to the dynamic rigid body, see

static void btTransformUtil::calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
in Bullet/src/LinearMath/btTransformUtil.h

Use the transform0 and transform1 of the kinematic object, at the attachment location.
tomhog
Posts: 6
Joined: Mon Jul 04, 2011 4:37 pm

Re: Dynamic body linked to Kinematic body by hinge constrain

Post by tomhog »

Hi Erwin

Thanks for the suggestions, I will try out setting the velocity etc myself.

>>Is there a way to directly re-position the dynamic body?

Would this still allow me to use the hinge, as i want the hinge so the
object has a little give to it if I push up against static objects.

I take it if I directly set the dynamic objects pose it would be via its
center of mass using the motionstate->setWorldTransform ?

I did also wonder if perhaps just adding a little smoothing to
my user input might help as you can turn pretty fast (it's using a gyro)

Cheers
Tom
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: Dynamic body linked to Kinematic body by hinge constrain

Post by Erwin Coumans »

You can blend/interpolate between the original transform and new transform, instead of setting the full new transform based on the kinematic object.

Note that you can also try to set (part of) the linear/angular velocity, in addition to modifying the transform manually.
It is best to use body->setCenterOfMassTransform(newTrans);

Such blending/interpolation also happens when applying cloth simulation to fast animated characters. Michael Ewart wrote a nice article
in Game Physics Pearls, I can highly recommend the book. There is also an digital Kindle version:
http://www.amazon.com/Game-Physics-Pear ... 1568814747

Ideally we create some Bullet demo to show how this works.
Post Reply