Moving physic objects with constraints

elLolo
Posts: 14
Joined: Thu Dec 11, 2008 2:18 pm

Moving physic objects with constraints

Post by elLolo »

Hello,

it seems that Bullet provides three kind of objects:
- physic objects that can be moved only through applied constraints
- kinematic objects that can be moved with rigidBody->setWorldPosition(blah) (except if I use MotionState then I have to use motionState->setWorldPosition())
- static objects that cannot be moved.

Am I right?

I would like to build an application with physic and kinematic objects. The scenario is as follows:
1/ there is a plate which is a physic object, with 3 rings attached to it
2/ there are 3 pliers which are kinematic object (so they always stay into the air)
3/ one pliers grips a ring and carry the plate. As a consequence, the plate is dragged on the floor
4/ another pliers grips a ring. So, the plate is now carried into the air but it is directed to the floor
5/ the last pliers grips the last ring so now the plate is carried and kept horizontal.

I think that I will have to use Point2PointConstraints for links between pliers and rings.
But, will my plate be "stable" with 3 constraints on it?!
Will the interactions with the plate be precise?

Moreover, what would happen if I remove the rings in order to have pliers directly griping the plate? I think I will have to use 6DofConstraints so my plate may become unstable.

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

Re: Moving physic objects with constraints

Post by rponomarev »

Hello Laurent,

Stability of such a system mostly depends on animation of your kinematic objects.

Constraint attached to a dynamic body adds several equations to linear system that defines the resulting motion of the body.
For example, the 6DOF constraint could add from 0 to 6 equations to the system.
In your case each point2point constraint adds 3 equations, so the resulting number is 9.
If animation of the pilers allows a stable solution of the system (i.e. all 9 equations could be satisfied), the constraint solver should find it.
I wrote a small test that works. All objects are boxes for simplicity.
I assumed that your "rings" are permanently attached to the plate, so the plate and 3 rings act as one rigid body.
I used a compound shape to do this.
You may copy/paste the code below to Bullet ConstraintDemo.cpp (and comment out other constraints in the demo)

Best regards,
Roman

Code: Select all

// to global variables
#define ENABLE_3_PILER_DEMO 1

#if ENABLE_3_PILER_DEMO
	btScalar sTime = btScalar(0.f);
	btRigidBody* spPiler0 = NULL;
	btRigidBody* spPiler1 = NULL;
	btRigidBody* spPiler2 = NULL;
#endif


// to the end of ConstraintDemo::initPhysics()

#if ENABLE_3_PILER_DEMO
	{ // 3 constraints between kinematic objects a single dinamic object
		btTransform tr;
		tr.setIdentity();
		// Create kinematic piler 0
		tr.setOrigin(btVector3(btScalar(0.), btScalar(0.), btScalar(-3.)));
		spPiler0 = localCreateRigidBody( 1.0, tr, shape);
		spPiler0->setCollisionFlags( spPiler0->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
		spPiler0->setActivationState(DISABLE_DEACTIVATION);
		// Create kinematic piler 1
		tr.setOrigin(btVector3(btScalar(3.), btScalar(0.), btScalar(3.)));
		spPiler1 = localCreateRigidBody( 1.0, tr, shape);
		spPiler1->setCollisionFlags( spPiler1->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
		spPiler1->setActivationState(DISABLE_DEACTIVATION);
		// Create kinematic piler 2
		tr.setOrigin(btVector3(btScalar(-3.), btScalar(0.), btScalar(3.)));
		spPiler2 = localCreateRigidBody( 1.0, tr, shape);
		spPiler2->setCollisionFlags( spPiler2->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
		spPiler2->setActivationState(DISABLE_DEACTIVATION);
		// Create plate and 3 rings as a dynamic object with compound shape
		// Create a compound shape
		btCompoundShape* compoundPlate = new btCompoundShape();
		m_collisionShapes.push_back(compoundPlate);
		// Add plate
		btCollisionShape* plateShape = new btBoxShape(btVector3(6., 0.5, 6.));
		m_collisionShapes.push_back(plateShape);
		btTransform localTrans;
	    localTrans.setIdentity();
		localTrans.setOrigin(btVector3(0,0,0));
		compoundPlate->addChildShape(localTrans,plateShape);
		// add rings 0-2
		btCollisionShape* ring0Shape = new btBoxShape(btVector3(0.5, 0.5, 0.5));
		m_collisionShapes.push_back(ring0Shape);
		localTrans.setOrigin(btVector3(0,1.5, -3.));
		compoundPlate->addChildShape(localTrans, ring0Shape);
		btCollisionShape* ring1Shape = new btBoxShape(btVector3(0.5, 0.5, 0.5));
		m_collisionShapes.push_back(ring1Shape);
		localTrans.setOrigin(btVector3(3.,1.5, 3.));
		compoundPlate->addChildShape(localTrans, ring1Shape);
		btCollisionShape* ring2Shape = new btBoxShape(btVector3(0.5, 0.5, 0.5));
		m_collisionShapes.push_back(ring2Shape);
		localTrans.setOrigin(btVector3(-3.,1.5, 3.));
		compoundPlate->addChildShape(localTrans, ring2Shape);
		// create a dynamic rigid body with compound shape
		tr.setOrigin(btVector3(btScalar(0.), btScalar(-6.), btScalar(0.)));
		btRigidBody* pPlate = localCreateRigidBody( 1.0, tr, compoundPlate);
		pPlate->setActivationState(DISABLE_DEACTIVATION);
		// attach piler0 to the plate
		btVector3 pivA0(0., 3., -3.);
		btVector3 pivB0(0., -3., 0.);
		btTypedConstraint* p2p0 = new btPoint2PointConstraint(*pPlate,*spPiler0, pivA0, pivB0);
		m_dynamicsWorld->addConstraint(p2p0);
		// attach piler1 to the plate
		btVector3 pivA1(3., 3., 3.);
		btVector3 pivB1(0., -3., 0.);
		btTypedConstraint* p2p1 = new btPoint2PointConstraint(*pPlate,*spPiler1, pivA1, pivB1);
		m_dynamicsWorld->addConstraint(p2p1);
		// attach piler2 to the plate
		btVector3 pivA2(-3., 3., 3.);
		btVector3 pivB2(0., -3., 0.);
		btTypedConstraint* p2p2 = new btPoint2PointConstraint(*pPlate,*spPiler2, pivA2, pivB2);
		m_dynamicsWorld->addConstraint(p2p2);
	}
#endif

// to ConstraintDemo::clientMoveAndDisplay()
// just before the m_dynamicsWorld->stepSimulation() call 
#if ENABLE_3_PILER_DEMO
		sTime += dt; // global time
		// Period of rotation is 2 seconds
		btScalar w0 = sTime / btScalar(2.f);
		w0 -= btScalar((int)w0);
		// rotate pilers
		btScalar angle = w0 * SIMD_2_PI;
		btScalar fx = btCos(angle);
		btScalar fy = btSin(angle);
		btTransform tr;
		tr.setIdentity();
		tr.setOrigin(btVector3(fx, fy, -3.));
		spPiler0->getMotionState()->setWorldTransform(tr);
		tr.setOrigin(btVector3(3. + fx, fy, 3.));
		spPiler1->getMotionState()->setWorldTransform(tr);
		tr.setOrigin(btVector3(-3. + fx, fy, 3.));
		spPiler2->getMotionState()->setWorldTransform(tr);
#endif
elLolo
Posts: 14
Joined: Thu Dec 11, 2008 2:18 pm

Re: Moving physic objects with constraints

Post by elLolo »

:shock:

Thank you very much! :D
It is what I expected.

If you think that it could be worth to add this demo or something around this idea to Bullet demos feel free to do that.