Conveyor belt speed problem (using friction model)

Post Reply
User avatar
Neo
Posts: 10
Joined: Fri Feb 19, 2016 2:04 am

Conveyor belt speed problem (using friction model)

Post by Neo »

Hello, I'm trying to make a tracked vehicle, like tank, in Bullet. And for the tracks, I decide to use friction model.
The code is much more the same as the post discussed here:
http://bulletphysics.org/Bullet/phpBB3/ ... 076#p21441
http://bulletphysics.org/Bullet/phpBB3/ ... php?t=6730
But the problem is, the friction motion seems to have a maximum value of 10. No matter how big value the variable m_contactMotion1 is set, the object can only reach the speed of the maximum of 10.
Like in my game when I set the tank speed to 20, and it can only run at the highest speed of 10.

And suggestions? :roll:
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Conveyor belt speed problem (using friction model)

Post by drleviathan »

You don't modulate the velocity of the "conveyor" by adjusting the friction coefficient. You modulate it by actually setting its velocity, and you can set its magnitude to be as long as you like.

The way to make a conveyor is to create a "kinematic" object that isn't actually moving. That is, you don't actually allow its WorldTransform to change over time, but you nevertheless give it a non-zero velocity. When dynamic objects collide with the conveyor the ContactPoint uses the non-zero velocity of the conveyor to push the dynamic objects as if the surface of the conveyor is moving.

The friction coefficient merely determines the maximum ratio of the magnitude of the friction force over that of the normal force.
User avatar
Neo
Posts: 10
Joined: Fri Feb 19, 2016 2:04 am

Re: Conveyor belt speed problem (using friction model)

Post by Neo »

drleviathan wrote:You modulate it by actually setting its velocity, and you can set its magnitude to be as long as you like.
I see. So now instead of modify the friction, I calculate the forward direction vector on contact point and set the velocity on it. Below is my code:

Code: Select all

		btVector3 minDir;//forward direction of closest contact point
		float t_speed = core::abs_(m_speed);//m_speed is current track speed (negative means backwards)
		for (int j = 0; j < pm->getNumContacts(); j++)
		{
			btManifoldPoint& point = pm->getContactPoint(j);

			point.m_lateralFrictionInitialized = true;
			point.m_lateralFrictionDir1.setValue(dir.X, dir.Y, dir.Z);//dir is current forward direction of track object
			//point.m_lateralFrictionDir1.normalize(); comment this line because dir is already normalized before in my code

			point.m_contactMotion1 = 2;
			point.m_combinedFriction = 9;
			point.m_combinedRestitution = combinedRestitution;
			if (abs_(point.m_distance1) < min_distance)
			{
				//find closet contact point
				min_distance = abs_(point.m_distance1);
				btVector3 herizonLeft = point.m_lateralFrictionDir1.cross(
										point.m_normalWorldOnB);
				//calculate forward direction of contact point
				minDir = point.m_normalWorldOnB.cross(herizonLeft);
			}
		}
		//set velocity
		if (pm->getNumContacts() > 0)
		{
			btVector3 vel_new = t_speed * minDir;
			bt_rigidbody->setLinearVelocity(vel_new);//rigidbody is track itself
		}
Is this the right way to do it?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Conveyor belt speed problem (using friction model)

Post by drleviathan »

No, I think the most important part is that you add the track as a kinematic object:

Code: Select all

body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
world->addRigidBody(body);
Then whenever you change its velocity make sure it is active so that it will wake up any inactive dynamic objects that might be touching it.

Code: Select all

body->setLinearVelocity(velocity);
body->activate();
User avatar
Neo
Posts: 10
Joined: Fri Feb 19, 2016 2:04 am

Re: Conveyor belt speed problem (using friction model)

Post by Neo »

drleviathan wrote:No, I think the most important part is that you add the track as a kinematic object:

Code: Select all

body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
world->addRigidBody(body);
[/code]
I think you get me wrong. What I want do is to make a inverse conveyor belt. Rather than move other objects, it should be able to move itself like a tank's track.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Conveyor belt speed problem (using friction model)

Post by drleviathan »

Ah yes, I did misunderstand. I don't know how to do exactly what you're trying. The only ideas I have to offer are:

(1) It might be possible to make a real tank tread using the multi-body stuff. I don't have much more to offer here except that it would probably require small substeps like the next idea:

(2) A multi-wheel tank approximation might be possible using rows of wheels connected with motorized constraints, say 4 or 5 wheels on a side. One problem with this is: when you have lots of constraints in one connected system you need small timesteps. You'd probably need to substep the simulation at 200Hz or higher. I've personally seen 4 wheel robots work with pure Bullet physics (stepped at 240Hz).

(3) You could use the btRaycastVehicle and fake tread friction.
User avatar
Neo
Posts: 10
Joined: Fri Feb 19, 2016 2:04 am

Re: Conveyor belt speed problem (using friction model)

Post by Neo »

Thanks for advice. Multiple objects solution seems great for single tank simulation. However cause this is a game, it's hard to keep a nice frame rate while simulate multiple, at least 10 tanks.
After tried ray cast vehicle, I think make conveyor a rigidbody may be a moderate solution.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Conveyor belt speed problem (using friction model)

Post by drleviathan »

I just had another idea that uses collision groups:

(A) Each tank is put into a special collision group. TankGroup collides with everything, including ConveyorGroup.
(B) ConveyorGroup collides with nothing except TankGroup.
(C) Each tank gets two conveyors, one for each tread. A conveyor has a flat surface shaped like a tank tread and rests under its corresponding tank tread. It is a separate RigidBody from the tank, but is kinematic and follows the tank around as described below.
(D) Every substep, before the integration part, you transform each tread to lie directly below its corresponding tread. You give each conveyor the correct linear velocity according to its tread's speed.
(E) During the integration part of the simulation the contacts between the conveyors and the tank will push the tank forward as if it were on tracks. This will move the tank off of the conveyor, but only a little bit and the conveyor will follow the tank before the next substep.

In short, use kinematic conveyors that follow the tanks around like private Jacob's ladders.

One gotcha with this method is that you can't actually reposition the conveyors based on nothing but the tank's transform. Floating point error and recursive transform calculations will cause drift and the conveyors will eventually push the tanks into the air or worse (NaN). However, if you know how high the conveyors should be (that is, you know the height of the ground under the tank) then you could clamp their transforms such that their top surface is just above the ground. The tanks will "fall" onto the conveyors and the recursive transform drift problem will be solved.
Post Reply