Page 1 of 1

Baumgarte and Softness for 2D Joints

Posted: Fri Aug 10, 2007 6:25 pm
by crashlander
On Erin's blog, in a comment is the following statement:

"Relaxation is an indirect way to soften the joints. In the GDC07 version of the bridge I directly use softness and the Baumgarte parameter to achieve a specified joint stiffness and damping. Unlike a true spring and damper, the SI algorithm can handle large stiffness and damping values."

What is the relationship between the Baumgarte Factor/Softness and Spring Constant/Dampning Constant.

Also, what is the general method for adding "softness" to other constraints. I have a 2D pin joint (keeps the anchors of two bodies at a constant distance) and a 2D slider joint that I'd like to add softness to.

-Jeff

Posted: Fri Aug 10, 2007 6:51 pm
by Erin Catto
You can find a reference for this technique here:

http://ode.org/ode-0.5-userguide.html#sec_3_8_2

I have implemented this in the current version of Box2D:

http://www.gphysics.com/files/Box2D_Lite.zip

In particular, look at the suspension bridge demo.

You should be able to use the same technique for any joint. Coming up with stiffness and damping coefficients for rotational constraints may be a little tricky. You'll need to consider the length scale of your objects.

Posted: Thu Aug 16, 2007 11:12 am
by crashlander
I'm still trying to get my head around the implementation of softeness.

In particular, I have a 2D Angle Joint with upper and lower limits. I used Erin's description here http://www.continuousphysics.com/Bullet ... .php?t=517 to create the joint. The joint works fine and I mostly understand the physics behind it.

However, now I'm trying to add a softness parameter to soften the joint correction at the limits.

I read the description in the ODE paper and I've looked at the softness implementation in Box2D_Lite, but I still can't seem to translate that into something that works for my angle limits.

In the Box2D_Lite, you apply the softness in the PreStep by adding it to a couple elements of the big K matrix:

K.col1.x += softness;
K.col2.y += softness;
I assume this is related to the following statment in the ode paper: "Thus CFM simply adds to the diagonal of the original system matrix"

And you apply the softness further in the ApplyImpulse by subtracting softness*P from the dv:

impulse = M * (bias - dv - softness * P);

I assume this is due to the function from the ODE docs: J * v = c + CFM * lambda

I'm just not sure how to apply it to my Angle joint. There is still just a little to much Math-Fog in the way.

Anybody care to break the math down a little bit more for me.

Posted: Thu Aug 16, 2007 11:30 am
by Dirk Gregorius
You basically want to weaken the constraint force:

The usual formulation is:

J*W*JT*lambda = = K * lambda = -0.1 * C / dt - J * v

-> lambda = - (ERP * C / dt - J * v ) / K

If we now add CFM to K lambda get smaller while if we would subtract from K lambda would get stronger. So if I remember correctly you should do:

lambda = - (ERP * C / dt - J * v ) / ( K + CFM )

So I suggest you try someting like ERP = 0.001 and CFM = 0.005 (or vice versa - I don't remember). If you want to use ODE values I mean to remember that you need to scale or divide by dt...


HTH,
-Dirk

Posted: Thu Aug 16, 2007 1:54 pm
by crashlander
Thanks Dirk.

I'm not really concerned with the values of ERP and CFM (BiasFactor and Softness)

I'm just interested in implementing softness into my angle joint class. (I'll worry about good values later)

What you show helps me alot. My only question now I guess is the specifics of how to apply this in practice given my pre-step and iteration steps.

In my pre-step I calculate a K and the biasVelocity

In my iteration step (ApplyImpulses) I calculate my impulse, accumulate impulses, then apply the clamped impulse.

Do I simply need to modify my K calculation in the pre-step to include the CFM (softness) factor?

Going from memory (as I'm at work) I think my mass factor (Inv K?) is:

massFactor = 1/(invI1 + InvI2) //calculated in the pre-step

and my impulse calc is:

impulse = (-biasVelocty - angularVelocity1 + angularVelocity2)*massFactor //might not have remembered all the signs correctly

do i just need to make massFactor;

massFactor = 1/(invI1 + InvI2 + CFM)

Posted: Thu Aug 16, 2007 5:58 pm
by Erin Catto
You really should go through the entire derivation if you really want to understand softness.

We start with:

Newton's Law:
M * (v2 - v1) = JT * lambda

Velocity constraint with softness and Baumgarte:
J * v2 + softness * lambda + bias = 0

where bias = biasFactor * C / dt

We know everything except v2 and lambda.

First solve Newton's law for v2 in terms of lambda:

v2 = v1 + invM * JT * lambda

Substitute this expression into the velocity constraint:

J * (v1 + invM * JT * lambda) + softness * lambda + bias = 0

Now collect coefficients of lambda:

(J * invM * JT + softness) * lambda = - J * v1 - bias

Now we define:

K = J * invM * JT + softness

and Meff = invK is the effective mass.

Now keep in mind that v1 contains the velocities for both bodies:

v1 = column_vector(vb1, omegab1, vb2, omegab2)

Now here is where things get a bit hairy. Each iteration we are not computing the whole impulse, we are computing an increment to the impulse and we are updating the velocity. Also, as we solve each constraint we get a perfect v2, but then some other constraint will come along and mess it up. So we want to patch up the constraint while acknowledging the accumulated impulse and the damaged velocity. To help with that we use P for the accumulated impulse and dP as the update. Mathematically we have:

M * (v2new - v2damaged) = JT * dP
J * v2new + softness * (P + dP) + bias = 0

If we solve this we get:

v2new = v2damaged + invM * JT * dP
J * (v2damaged + invM * JT * dP) + softness * P + softness * dP + bias = 0

(J * invM * JT + softness) * dP = -(J * v2damaged + softness * P + bias)

Note how the accumulated impulse comes into the righthand side. We can solve this for dP and then accumulate and clamp the impulse.

So you can see that understanding softness is a bit tricky. I recommend going over this with a 1D test case and implementing it and making sure you understand it. Try a 1D particle that can only move up and down. Then try to constrain the motion completely with a soft constraint.

Posted: Thu Aug 16, 2007 6:33 pm
by crashlander
Thanks a million for that Erin. At first glance, I think I follow. I'll chew on it for a while and see where I get.