PointToPointConstraints at breakneck speeds

Oct 3, 2009 at 8:26 PM

Hello! I ran into an odd issue today. If you have a PointToPointConstraint between two rigid bodies and one of the bodies gets a huge impulse/force/acceleration, the constraint just breaks up and the speedy body flies away, shouting "Arriba! Arriba! Andale! Andale! Yii-hah!". The issue is even more obvious if the other body is static or attached through another constraint to a static body. If the force is big but still not enough to break the constraint up, the bodies will spin wildly, obviously not keeping the constraint, but will at least stay close. I need those huge accelerations because of some very rapid movements in the game, much faster than the ones in the Oops! demo, for example. I looked at the constraint code and noticed that it is resolved by applying an impulse to the bodies so as to keep them in place. So maybe the constraint impulse is not enough to withstand the external force? A rounding error causing this perhaps? What if the two bodies were held in place by an UpdateTransform, instead of an ApplyForceImpulse? What do you think

Regards,

Orlin

Coordinator
Oct 4, 2009 at 1:40 AM

Hi Orlin,  Using the UpdateTransform may not be your bet as it may make you simulation look artificial.  Most of the collision response is based on velocities and just moving objects into position for constraints will remove those velocities.  But that being said,  it may work okay based on the context of your usage.  Give it a try and see how it works.

The PhysicsComponent has a few properties that may help with the constaint resolution - CollisionIterationCount and ContactIterationCount.  Increase those and see if that helps.  Also, I've also recently discovered that my code is not as frame-rate independent as I thought.  You may try setting the Game.IsFixedTimestep to true to see if that helps with your issue.  I'm looking into that right now.  I'll look into making the P-to-P constaint more reliable as well.  If I find a quick fix, I'll post here.  Otherwise, I'll just update the source.

Good luck!

Oct 6, 2009 at 3:48 PM

Hi again! I made a test with Example 6 in the demo game and it still showed the same issue. To replicate, set the screen in Example 6 to only contain 2 balls, so as to see them better. Then change ExampleScreen.ForceFactor to 380000 (100 times more than the original value) so the balls will spin wildly. Press an arrow key in any direction, hold for a second, then press and hold another direction and so on, the constraint will break up almost immediately. I tried setting CollisionIterationCount to 1000 and IsFixedTimestep to true but they didn't seem to have any serious effect. And there is no ContactIterationCount anywhere to be found. It should be easy to debug from this point (regrettably I can't do it - I'm a n00b in math and can't tell the difference between physics and physique).

Regards,

Orlin

Coordinator
Oct 8, 2009 at 3:18 AM

Thanks for the steps to reproduce.  I'm in need of a better p-2-p constraint with the game I'm working on so when I get to that point I'll update the source with any fixes.  It may be a bit though.

 

Coordinator
Oct 9, 2009 at 6:10 AM

Hey Orlin, I found an issue in the PointToPointConstraint that really helps with the issues you are experiencing.  It keeps the bodies intact with the force factor changed to 380000 so it may fix your situation.  The code that needs changed is in the PointToPointConstraint.Solve method.  here's the snippet:

// Apply the impulse to each rigid body.
#if false
	this.rigidBody0.ApplyForceImpulse(ref normalImpulse, ref this.worldPosition);
	normalImpulse = -normalImpulse;
	this.rigidBody1.ApplyForceImpulse(ref normalImpulse, ref this.worldPosition);
#else
	Vector3 temp = this.rigidBody0.Position + this.position0;
	this.rigidBody0.ApplyForceImpulse(ref normalImpulse, ref temp);
	normalImpulse = -normalImpulse;
	temp = this.rigidBody1.Position + this.position1;
	this.rigidBody1.ApplyForceImpulse(ref normalImpulse, ref temp);
#endif

The old code is in the "false" block, new code in the "else" block.  Essentially, I was applying the impulse at the incorrect position for each rigid body.  This code can be optimized further since the "temp" additions occur in the PreStep method as well (see worldPosition0 and worldPosition1) and the worldPosition field is not used anymore.

Let me know if this helps/works for you.  Good luck!

 

Oct 9, 2009 at 9:38 AM

Definitely much better! The bodies don't spin and convulse like crazy any more. They still might get separated if pushed too hard, but at least they return to their correct position after a while.

Cheers,

Orlin