Conveyor belt

Mr.Orange
Posts: 11
Joined: Mon Apr 18, 2011 10:03 am

Conveyor belt

Post by Mr.Orange »

Hey guys,

I'm currently working on a conveyor belt simulation and I'm having some problems with that.

For collision detection I use iteration over manifold points, everything works fine with that.

Code: Select all

   int numContacts = contactManifold->getNumContacts();
	for (int j=0;j<numContacts;j++)
	{
		btManifoldPoint& pt = contactManifold->getContactPoint(j);

		pt.m_lateralFrictionInitialized = true;
		pt.m_lateralFrictionDir1.setValue(activeConveyor->getDirection().x(), activeConveyor->getDirection().y(), activeConveyor->getDirection().z());
		pt.m_lateralFrictionDir1.normalize();
		pt.m_contactMotion1 = activeConveyor->getVelocity();
		pt.m_combinedFriction = 10;
	}
m_combinedFriction uses just a dummy value. activeConveyor basically is a rigid body with some additional information (velocity, direction). I took the code from here: http://www.bulletphysics.org/Bullet/php ... f=9&t=3555

My scene is set up like this:
A cube falls down from a slightly elevated position on another, bigger cube representing the conveyor.
Both the cube and the conveyor are created via convex hull shapes.
I can change the velocity and direction of the conveyor dynamically during simulation.

As long as I set the velocity of the conveyor before the cube impacts everything works perfectly fine. The cube collides with the conveyor, the friction is applied and the cube moves along the specified direction.
But if I set the velocity of the conveyor to zero and wait until the cube comes to a complete rest on the conveyor, then change the velocity to a different value, it doesn't work anymore. The cube just remains in its original position.

Anyone got a clue why that happens and how to avoid this behavior?

Thanks a lot for your help!
Greets
Mr.Orange
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm

Re: Conveyor belt

Post by dphil »

You might have to activate "resting" objects on your conveyor belt when you set its velocity:

Code: Select all

rigidBody->activate(true);
Edit: though I see from Salb's thread that you are already familiar with body activation...
Mr.Orange
Posts: 11
Joined: Mon Apr 18, 2011 10:03 am

Re: Conveyor belt

Post by Mr.Orange »

Hey dphil,
wow, thank you very much! It works like a charm...
You're right, I know the body->activate() method, but I've no idea what it's actually doing and why I sometimes need it and sometimes don't need it.

For the sake of completeness here my full conveyor source code:

Code: Select all

   activeCollisionObject->activate(true);

	int numContacts = contactManifold->getNumContacts();
	for (int j=0;j<numContacts;j++)
	{
		btManifoldPoint& pt = contactManifold->getContactPoint(j);

		pt.m_lateralFrictionInitialized = true;
		pt.m_lateralFrictionDir1.setValue(activeConveyor->getDirection().x(), activeConveyor->getDirection().y(), activeConveyor->getDirection().z());
		pt.m_lateralFrictionDir1.normalize();
		pt.m_contactMotion1 = activeConveyor->getVelocity();
		pt.m_combinedFriction = calculateCombinedFriction(activeConveyor->getFriction(), activeCollisionObject->getFriction());
		pt.m_combinedRestitution = calculateCombinedRestitution(colObj0->getRestitution(),colObj1->getRestitution());
	}
cya,
Mr.Orange
serengeor
Posts: 22
Joined: Mon Dec 20, 2010 7:13 pm

Re: Conveyor belt

Post by serengeor »

Mr.Orange wrote:Hey dphil,
wow, thank you very much! It works like a charm...
You're right, I know the body->activate() method, but I've no idea what it's actually doing and why I sometimes need it and sometimes don't need it.
You need them when rigid bodies get deactivated (they get in some sort of sleep state, which speeds up simulation).
Mr.Orange
Posts: 11
Joined: Mon Apr 18, 2011 10:03 am

Re: Conveyor belt

Post by Mr.Orange »

Hi serengor,

thanks a lot for your explanation, that makes sense of course.

Unfortunately further testing showed that my conveyor belt doesn't work with soft bodies. So I gotta do more research on this.... :roll:

cya,
Mr.Orange
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm

Re: Conveyor belt

Post by dphil »

In case it helps, note that soft body friction is controlled via the softBody->m_cfg.kDF parameter (0 = no friction, 1 = max).
Mr.Orange
Posts: 11
Joined: Mon Apr 18, 2011 10:03 am

Re: Conveyor belt

Post by Mr.Orange »

Hi dphil,

thanks again for the tip! These soft bodies can be quite anoying :? .
Your little hint brought up another question: what's the friction range for rigid bodies? It's defenitely not just from 0.0 to 1.0. As usual, the source code is not documented properly. According to other posts here in the forum and some bullet demos, it's at least from 0 to 10.

Whatever, my soft body conveyor still doesn't work. I can't get any collision response from my soft bodies. I iterate over the contact manifolds, but nothing...

Here's the code for my collision processing:

Code: Select all

   int numManifolds = this->dynamicsWorld->getDispatcher()->getNumManifolds();
	for (int i=0;i<numManifolds;i++)
	{
		btPersistentManifold* contactManifold =  this->dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
		if (contactManifold->getNumContacts() > 0)
      {
		   /* do some stuff here with the objects and contact points */
      }
	}
My world is set up like this:
A convex rigid body in the shape of a stretched cube with zero mass acts as a conveyor. A soft body represented by a small cube falls down on the conveyor.

What occurs to me is that numManifolds is always zero, but when I replace the soft body by a rigid body it becomes 1. Maybe I'm using the wrong dispatcher/broadphase/collisionConfiguration?

Code: Select all

btBroadphaseInterface* broadphase = new btDbvtBroadphase();	
btDefaultCollisionConfiguration* collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
Or maybe something's wrong with my soft body collision config?

Code: Select all

this->softBody->setCollisionFlags(this->softBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); // I know this is actually for collision callbacks
this->softBody->m_cfg.collisions = btSoftBody::fCollision::CL_RS + btSoftBody::fCollision::CL_SS;

Anyone got a working collision detection for soft bodies and can post his soft body creation and config code here?
I'm really fed up with the soft body stuff right now :cry:, but I won't give up! 8)

Thanks for your help guys!
cya

Mr.Orange
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm

Re: Conveyor belt

Post by dphil »

In the bullet source code (btSodtBody.h) kDF is documented as being in the range [0,1]... though I suppose it's possible the actual implementation diverged from this at some point. Mind you... I just did a search through the entire bullet source and found no case where kDF was actually being used. Hm.

Anyway, since your problem seems to be collision detection, you say the soft body cube "falls down on the conveyor". Does it properly land on the conveyor and not fall through? If this is the case, then the collision detection appears to be working, it's just that the manifold stuff isn't doing what you expect, and you might need to get that info a different way. I haven't worked with manifolds much (and only with rigid bodies), so I can't suggest much there.
Since you are using the cluster collision flags, I assume you already made a call to create clusters?

Code: Select all

softBody->generateClusters(...);
Your broadphase/collisionConfiguration/dispatcher should be fine.
Mr.Orange
Posts: 11
Joined: Mon Apr 18, 2011 10:03 am

Re: Conveyor belt

Post by Mr.Orange »

Hey dphil,

thanks a lot for your time and consideration. I hope I'll be as familiar with the bullet engine and source code as you someday and can help you with YOUR problems!

Anyways, my soft body collides with the conveyor and does not fall through. So there must be some kind of collision detection. But as mentioned before,

Code: Select all

getDispatcher()->getNumManifolds()
always returns zero.
When I try it with callbacks

Code: Select all

dynamicsWorld->getSolverInfo().m_numIterations = 4;
dynamicsWorld->getSolverInfo().m_solverMode = SOLVER_SIMD+SOLVER_USE_WARMSTARTING+SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;
dynamicsWorld->getDispatchInfo().m_enableSPU = true;

gContactAddedCallback = ObjectEnterCallback;		
gContactDestroyedCallback = ObjectLeaveCallback;
both ObjectEnterCallback and ObjectLeaveCallback are never called. I'll try playing around with the solver constants and collision config stuff. Maybe something's wrong with them...

cya,
Mr.Orange

P.S.: yes, I call softBody->generateClusters() :)
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Conveyor belt

Post by Flix »

I've never tried to do a conveyor belt that works with soft bodies.

As far as I know it's not currently possible to detect collisions between rigid bodies and soft bodies in Bullet so you can iterate the contact manifold, but these collisions are not currently reported. (And I think that it's the same for soft-soft collisions).

So maybe what you're trying to do it's not possible at the moment.

Anyway a simple conveyor belt can be created by simply adding a linear velocity to a static object representing the belt ( sparkprime approach ).

The point is that you must try to achieve it without "collision events".

Hope it helps.
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm

Re: Conveyor belt

Post by dphil »

Looking into it a bit more, it seems that if you are using VF_SS or SDF_RS collision processing, info for nodes that are currently colliding with a soft or rigid body are stored in the soft body's m_rcontacts and m_scontacts vectors. I just tried this and it seems to work, though I get a much high number of contacts being generated than I expected, though perhaps it's storing bounding volume collisions (which may overlap much more). Anyway, from any element in one of these vectors you can get a pointer to the colliding object, and check if it is your conveyor belt. If so, apply a velocity to the soft body.

The analogous structure for cluster collisions seems to be soft body's m_joints vector. I tried colliding cluster-based sb's and it seems to be empty during no collision, and non-empty during collision.

So you could iterate over each soft body, check the appropriate m_rcontacts/m_scontacts/m_joints vector, and if it's not empty, iterate over its elements to see what is being collided with. However, this does seem a bit messy and not terribly efficient, and I'm not sure it was every meant to be used like this (granted, m_rcontacts and m_scontacts are used for debug drawer soft body rendering purposes; see btSoftBodyHelpers), so perhaps in the end Flix's suggestion of avoiding using specific contacts altogether might be a better route.

Oh, and a small correction to my earlier post: kDF is in fact being used. Turns out the default xcode project I was using created by the cmake files wasn't actually including all of the source files as I thought it was.
Mr.Orange
Posts: 11
Joined: Mon Apr 18, 2011 10:03 am

Re: Conveyor belt

Post by Mr.Orange »

Hi guys,

thanks a lot for your replies.

@dphil:
I could reproduce the behavior using VF_SS and SDF_RS. The contyct points are stored in m_rcontacts and m_scontacts. With CL_SS and CL_RS though, it didn't work. The "m_capacity" and "m_data" members of m_joints seem to change on collision, but the m_joints array itself remains empty.

@Flix:
Soft and rigid bodies actually do collide so there must be some way of detecting their collisions. You are right, a moving rigid body with a linear velocity would be easier to realize on first glance and especially if I had to simulate only one body beeing transportet, but unfortunately it's not the same. To achieve a "realistic" simulation, I'd have to model every member of the conyeor, connect them via joints and create a circle-like movement. Not so easy anymore...

Ok, I'll stay on this, maybe I'll find out something more.

cya,
Mr.Orange