Advertisement

Friction impulses in sequential solver

Started by March 03, 2024 02:44 PM
11 comments, last by Dirk Gregorius 9 months, 3 weeks ago

I'm creating 3D sequential impulse collision solver in f#. Up to now, normal part of collision response works correctly. Unfortunately i have problem with friction impulses.

Do i need only one pair of tangent vectors for whole contact manifold, or do i need to recalculate them for each contact point? Should they change during each iteration of solver? Same goes with tangent mass, can i calculate it only once for each frame, in the presolve step?

You usually have one pair of friction impulses per contact point. The directions could be shared if the points have a common normal. Neither the directions nor the tangent mass change during iterations since impulses change velocity and not positions. So yes, they can be precomputed. Note that the tangent masses cannot not be shared since there are different offsets from the COM to the contact point which go into the their calculations.

Advertisement

Thanks for answer.

Doesn't each contact point have different velocity before collision? So if I base tangent directions on contact point velocity, all of them will be different for each contact point too, and also will change during iterations (because, as You said - impulses change contact point velocity).

Yes, the velocity changes, but you project it onto a fixed basis. There are two tangent directions! You can align one direction with the relative velocity at the contact point when you set this up, but this is only useful if you use box clamping. Instead you can also do:

lambda_tangent1^2 + lambda_tangent2^2 ≤ (mu * lambda_normal)^2

This is consistent with Coulomb friction. But to be honest, I would not worry about these details much. You will not notice a difference anyways. There are very few use cases where this matters.

I've used two friction axes and reused tangent vectors for all contact points, they are computed correctly. Unfortunately, as soon as my box hits the floor (it is falling due to the gravity, with only z component of speed) it starts spinning around Z axis with increasing speed. Does order of applying impulses matters? I first apply normal impulse, and then two friction impulses. All its is done for each contact point, and then looped for 10 iterations.

It seems you have a bug and yo need to debug it. Apply the friction impulses and then re-compute the relative velocity in the friction plane. It should become zero. Seems like you are adding velocity.

Advertisement

It works now, I had a bug with impulse sign being inverted. It works now, however objects seem to follow slightly curved pattern when pushed. Is this connected to not aligning first tangent with relative velocity? I remember such an explanation made by Erin Catto in some forum topic about his Bullet engine.

Yes, aligning with the relative velocity can help here. But be aware that this can be zero. This is why I personally prefer the circular clamping mentioned earlier. E.g. no special case.

Also, for warm-starting make sure that you project the old friction impulse correctly onto the new axes before the relaxation phase. E.g.

friction_impulse = friction_lambda1 * old_tangent_1 + friction_lambda2 * old_tangent2
friction_lambda1 = dot( friction_impulse, new_tangent1 )
friction_lambda2 = dot( friction_impulse, new_tangent2 )

Also, for reference. The Bullet author is Erwin Coumans. Erin Catto is the author of Box2D

Dirk Gregorius said:

Also, for reference. The Bullet author is Erwin Coumans. Erin Catto is the author of Box2D

Yes, sorry for that.

I haven't implemented warm starting yet, this is not so easy to do in functional way, with immutable state - but definitely doable.

Thanks again for Your interest

This topic is closed to new replies.

Advertisement