Rigid body box stacking

Please don't post Bullet support questions here, use the above forums instead.
c0der
Posts: 74
Joined: Sun Jul 08, 2012 11:32 am

Rigid body box stacking

Post by c0der »

Hi,

I have got my clipping algorithm to work (I zero'd the collision velocities and drew the contact manifold to show this). Now I am having trouble with overshoot. I am using the interpenetration depth of each contact, which should technically be correct. I also have implemented warm starting I tried implementing the bias from Erin Catto's presentations but am still getting overshoot. Please help!

Here is the rest of the code, it doesn't let me paste it here.
http://codepad.org/JJhSuL2p

Code: Select all


void AMG3DRigidBodyCollisionResponder::computeMasses(const AMG3DScalar& dt)
{
	if(m_bSkipCollision)
		return;

	if(dt<=0.0f)
		return;

	const AMG3DScalar k_allowedPenetration = 0.01f;
	AMG3DScalar k_biasFactor = (AMG3DPhysicsWorld::g_AMG3D_bPositionCorrection) ? 0.2f : 0.0f;

	for(int i=0; i<m_cdContactData.iNumContacts; ++i) {
		AMG3DVector4 normal = m_cdContactData.contacts[i].vContactNormal;

		AMG3DVector4 rap = m_cdContactData.contacts[i].vContactPoint - m_pRigidBody1->m_vPosition;
		AMG3DVector4 rbp = m_cdContactData.contacts[i].vContactPoint - m_pRigidBody2->m_vPosition;

		AMG3DVector4 rapcrossn = rap.cross(normal);
		AMG3DVector4 rbpcrossn = rbp.cross(normal);

		// Compute the normal mass
		AMG3DScalar Kn = m_pRigidBody1->m_sInvMass + m_pRigidBody2->m_sInvMass;
		Kn += ( (m_pRigidBody1->m_matInvIWorld*rapcrossn).cross(rap) + (m_pRigidBody2->m_matInvIWorld*rbpcrossn).cross(rbp) ).dot(normal);
		m_cdContactData.contacts[i].massNormal = 1.0f/Kn;

		// Compute the bias (prevents sinking, useful for stacking)
		m_cdContactData.contacts[i].bias = k_biasFactor / dt * 
							AMG3D_MATH_MAX(0.0f, m_cdContactData.contacts[i].sPenetrationDepth - k_allowedPenetration);

		// Calculate the tangent vector. To Do: Research relative velocity tangent vector
		//AMG3DVector4 vabn = normal*(vab.dot(normal));
		//AMG3DVector4 vabt = vab - vabn;
		AMG3DVector4 t1, t2;

		//if(vabt.magnitude()>0) {
		//	vabt.normalize();
		//	t1 = vabt;
		//	AMG3DVector4Cross(&t2, normal, t1);
		//}
		//else {
			normal.buildOrthoBasis(&t1, &t2);
		//}

		AMG3DVector4 rapcrosst1 = rap.cross(t1);
		AMG3DVector4 rbpcrosst1 = rbp.cross(t1);

		// Compute the tangent mass in the first direction
		AMG3DScalar Kt1 = m_pRigidBody1->m_sInvMass + m_pRigidBody2->m_sInvMass;
		Kt1 += ( (m_pRigidBody1->m_matInvIWorld*rapcrosst1).cross(rap) + (m_pRigidBody2->m_matInvIWorld*rbpcrosst1).cross(rbp) ).dot(t1);
		m_cdContactData.contacts[i].massTangent1 = 1.0f/Kt1;

		AMG3DVector4 rapcrosst2 = rap.cross(t2);
		AMG3DVector4 rbpcrosst2 = rbp.cross(t2);

		// Compute the tangent mass in the second direction
		AMG3DScalar Kt2 = m_pRigidBody1->m_sInvMass + m_pRigidBody2->m_sInvMass;
		Kt2 += ( (m_pRigidBody1->m_matInvIWorld*rapcrosst2).cross(rap) + (m_pRigidBody2->m_matInvIWorld*rbpcrosst2).cross(rbp) ).dot(t2);
		m_cdContactData.contacts[i].massTangent2 = 1.0f/Kt2;
	
		if(AMG3DPhysicsWorld::g_AMG3D_bWarmStarting) {
			AMG3DVector4 P = m_cdContactData.contacts[i].Pn*normal + m_cdContactData.contacts[i].Pt1*t1 + m_cdContactData.contacts[i].Pt2*t2;

			m_pRigidBody1->m_vVelocity			+= P*m_pRigidBody1->m_sInvMass;
			m_pRigidBody1->m_vAngularVelocity	+= m_pRigidBody1->m_matInvIWorld*rap.cross(P);
		
			m_pRigidBody2->m_vVelocity			-= P*m_pRigidBody2->m_sInvMass;
			m_pRigidBody2->m_vAngularVelocity	-= m_pRigidBody2->m_matInvIWorld*rbp.cross(P);
		}	
	}
}

Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Rigid body box stacking

Post by Dirk Gregorius »

Difficult to say without debugging this. I would check that all signs are correct. Disable stabilization and see if you get correct stacking with some sinking, but without overshoot. Finally make sure that you get the correct penetration depth. If you use MPR instead of SAT this will be very likely the reason.

In my experience one expects some dramatic mistake when things like this happen, but it is often just some tiny error. Setup the simplest scene that shows the erratic behavior and then step through it.
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Rigid body box stacking

Post by Dirk Gregorius »

Oh, and for warmstarting you need to project the last friction impulses onto the new basis. But this is unrelated to your problem.

Essentially:

Vector Pt = Pt1 + Pt2;
float lambda1 = dot( Pt, t1 );
float lambda2 = dot( Pt, t2 );

Vector new_Pt1 = lambda1 * t1;
Vector new_Pt2 = lambda2 * t2;
Last edited by Dirk Gregorius on Wed Jan 29, 2014 5:58 pm, edited 3 times in total.
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Rigid body box stacking

Post by Dirk Gregorius »

Here is how you compute the relative velocity in the tangent plane:

You know that: v_rel = vn + vt
Here vn is the relative velocity in the direction of the normal and vt is the relative velocity in the tangent plane. Both quantities are vectors. Since we know the contact normal we can build vn = dot( v_rel, n ) * n
Finally you identify vt = v_rel - vt

Now |vt| can be zero and in this case you still need to fall back on your ortho basis.

This seems to be what your were trying to do. So if this is not working there might be some mistake elsewhere.
c0der
Posts: 74
Joined: Sun Jul 08, 2012 11:32 am

Re: Rigid body box stacking

Post by c0der »

Thanks Dirk. I am using SAT and have some snapshots. I am trying 5 boxes now. I zero the collision velocities (EngineZeroCV.png) and the boxes are coming in fairly straight. When I enable impulses and disable position correction (EngineZero.png), I get an uneven effect, but this should be OK as the corrective impulses will handle this. One thing I notice is when I use a minimum penetration depth for all contacts, it's more stable, but I don't think this is correct. I am actually not using constraints but just a regular impulse resolver.
Attachments
EngineZeroCV.png
EngineZeroCV.png (414.08 KiB) Viewed 25249 times
Engine.png
Engine.png (387.77 KiB) Viewed 25249 times
RandyGaul
Posts: 43
Joined: Mon May 20, 2013 8:01 am
Location: Redmond, WA

Re: Rigid body box stacking

Post by RandyGaul »

Dirk Gregorius wrote:Here is how you compute the relative velocity in the tangent plane:

You know that: v_rel = vn + vt
Here vn is the relative velocity in the direction of the normal and vt is the relative velocity in the tangent plane. Both quantities are vectors. Since we know the contact normal we can build vn = dot( v_rel, n ) * n
Finally you identify vt = v_rel - vt

Now |vt| can be zero and in this case you still need to fall back on your ortho basis.

This seems to be what your were trying to do. So if this is not working there might be some mistake elsewhere.
Do you recommend this projection? A lot of students I talk to prefer to keep an arbitrary othonormal basis for friction axes rather than computing friction tangents aligned by the relative motion.

In my own simulation this style is very stable, but I have seen Erwin on these forums state that if an object slides quickly along a plane one of the friction axes can converge before the other causing an arced path of travel. I haven't noticed this artifact myself though.
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Rigid body box stacking

Post by Dirk Gregorius »

Personally I use a totally different friction model so I cannot really recommend something here. If you use the velocity projection you need to make sure to also project the accumulated friction impulses onto the new tangent axes as I have shown above. If you don't project onto the new axes you might get artifacts with warmstarting. This is often overlooked and might be the reason why some students prefer the fixed axes where the direction hardly changes and you will not notice any problems. Aligning with the tangential velocity should be better, but I am not sure if you will notice any difference for stacking. You need to test this in some sliding test cases. The theoretical concerns you mention are true and I have seen these artifacts in practice as well.
Last edited by Dirk Gregorius on Thu Jan 30, 2014 1:02 am, edited 2 times in total.
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Rigid body box stacking

Post by Dirk Gregorius »

@Coder: The problems you are seeing might be due to the variable timestep. You would need to scale the accumulated impulse by the ratio of the last and current timestep for warmstarting. Personally I would not use a varying timestep at all.
c0der
Posts: 74
Joined: Sun Jul 08, 2012 11:32 am

Re: Rigid body box stacking

Post by c0der »

I actually mean by "variable timestep" the one I implemented from gafferongames. I am currently using a fixed timestep and still have the same problem. I disabled position correction and the jitter stopped, I am about to give up, been stuck for a while now. Also, I disabled friction.
c0der
Posts: 74
Joined: Sun Jul 08, 2012 11:32 am

Re: Rigid body box stacking

Post by c0der »

Actually now I realise why I didn't use the relative velocity, it's because I would then have to recompute the tangent masses as each iteration. I think the problem is in building the ortho basis at each frame for each contact, this means that for each contact, the tangent impulses won't be coplanar. With Erin Catto's 2D version, he doesn't use relative velocity, just directly get the tangent vector and computes this and the tangent mass once per frame.

Any tips on porting this to 3D avoiding computing the tangent mass per iteration?
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Rigid body box stacking

Post by Dirk Gregorius »

You only compute the friction basis once before starting to iterate. Either from the relative velocity or just from the normal. The normal doesn't change during the iteration so no need to recompute the basis. Even if you use the relative velocity you just do it once and then stick with this basis.
bone
Posts: 231
Joined: Tue Feb 20, 2007 4:56 pm

Re: Rigid body box stacking

Post by bone »

RandyGaul wrote:In my own simulation this style is very stable, but I have seen Erwin on these forums state that if an object slides quickly along a plane one of the friction axes can converge before the other causing an arced path of travel. I haven't noticed this artifact myself though.
Like Dirk and Erwin, I've seen the "arc" as well when not using relative velocity as one of the orthonormal bases.
c0der
Posts: 74
Joined: Sun Jul 08, 2012 11:32 am

Re: Rigid body box stacking

Post by c0der »

I combined the tangent vectors into 1 for both directions t1+t2. Now I am getting sliding problems, the overshoot is gone. I will deal with the arc later if it comes up, I am using an ortho basis computed from the normal for now
RandyGaul
Posts: 43
Joined: Mon May 20, 2013 8:01 am
Location: Redmond, WA

Re: Rigid body box stacking

Post by RandyGaul »

c0der wrote:I combined the tangent vectors into 1 for both directions t1+t2. Now I am getting sliding problems, the overshoot is gone. I will deal with the arc later if it comes up, I am using an ortho basis computed from the normal for now
It does not make sense to me to model coulomb friction with a single vector as you need a 3D friction plane. If you generate an orthonormal basis (perhaps via cross product) given an input normal you can use the two generated vectors as friction axes. Have you tried this?

As a side note to the arc artifact: I've written simulations used in multiple student projects and done a lot of personal testing and have yet to actually notice any artifacts; I don't really think it's something anyone should worry about until it becomes a priority.
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Rigid body box stacking

Post by Dirk Gregorius »

I have tested this in real production code that actually shipped and trust me it is a real world problem. If you want to push an object from A to B in a game and it moves on an arc rather than a straight line this will be indeed a problem. If objects slide on planes and actually also rotate around the up-axis that is a problem. Sorry student projects and personal testing don't count! :) You also might want to come up with better test cases!
Last edited by Dirk Gregorius on Fri Jan 31, 2014 1:12 am, edited 1 time in total.
Post Reply