Bug in slider constraint

mathis
Posts: 16
Joined: Tue Sep 01, 2009 3:49 pm
Location: Germany

Bug in slider constraint

Post by mathis »

I observed a strange behaviour of the slider constraint when free rotation about the slider axis is allowed. The reason seems to be that the formulas for the Jacobian assume that both rigid bodies have the same angular velocity, but this is of course only true if we do not allow rotation about the slider axis.

The two linear constraints are that the translation between frames A and B must be zero in local directions y and z. As time derivative, I get

p * (vA - vB) + ((wB_t - wA_t) x p) * omegaA + ((wB_R * fB_t) x p) * (omegaA - omegaB) = 0

vA, vB, omegaA, omegaB: velocities
p: local direction y/z in world coordinates
wA_t, wB_t: translational part of world transforms
wB_R: rotational part of world transforms
fB_t: translational part of constraint frame (i.e., wB_R * fB_t is the vector from slider origin to rigid body B in world coordinates)

Now the current implementation ignores the last term, which is only possible if omegaA = omegaB, and it replaces omegaA by a weighted sum of omegaA and omegaB (weighted by mass), which again requires omegaA = omegaB.

I replaced this code

Code: Select all

		btVector3 tmp = c.cross(p);
		for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i];
		for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i];
		tmp = c.cross(q);
		for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i];
		for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i];
by this one:

Code: Select all

		btVector3 b = bodyB_trans.getBasis() * m_frameInB.getOrigin();
		btVector3 a = b + c;
		btVector3 tmpa = a.cross(p);
		btVector3 tmpb = b.cross(p);
		for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpa[i];
		for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpb[i];
		tmpa = a.cross(q);
		tmpb = b.cross(q);
		for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpa[i];
		for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpb[i];
and this fixes my problem.

What consideration is behind the use of the weighted mean of omegaA and omegaB? This could be integrated in my fix for the directions perpendicular to the slider axis, but I would like to know why this is better than the straightforward formula.
User avatar
rponomarev
Posts: 56
Joined: Sat Mar 08, 2008 12:37 am

Re: Bug in slider constraint

Post by rponomarev »

Hello,

The existing code does mot mean that angular velocities of BodyA and BodyB are equal.
It uses to vectors p and q perpendicular to the slider axis and assumes that projections of angular velocities to these axes are equal.
Ideally you can choose any "alignment" point on slider axis to set equations for angular velocities. But sometimes small angular difference could give large positional difference and solver may not eliminate it for chosen number of iterations.
The current code "moves" the point of alignment using weighted sum of masses to add stability especially in case when one of the bodies is static. Your code works well when BodyA is static, but has a "springy" behavior when BodyA is dynamic and BodyB is static.
You may check it using the appSliderDemo.

Thanks,
Roman
mathis
Posts: 16
Joined: Tue Sep 01, 2009 3:49 pm
Location: Germany

Re: Bug in slider constraint

Post by mathis »

Thanks for the explanation of the mass weighting.
rponomarev wrote: The existing code does mot mean that angular velocities of BodyA and BodyB are equal.
It uses to vectors p and q perpendicular to the slider axis and assumes that projections of angular velocities to these axes are equal.
Hmm, is this really true? If my formula is right:

p * (vA - vB) + ((wB_t - wA_t) x p) * omegaA + ((wB_R * fB_t) x p) * (omegaA - omegaB) = 0

you do NOT use the projections of the angular velocities to p and q! These would be p * omegaA etc., but in my formula (and also in the current implementation) you compute the dot product of omegaA with vectors which are perpendicular to p, q! These vectors are likely to have a component in the direction of the slider axis.
mathis
Posts: 16
Joined: Tue Sep 01, 2009 3:49 pm
Location: Germany

Re: Bug in slider constraint

Post by mathis »

The second term seems to be OK even if the angular velocities differ. If you take my equation

p * (vA - vB) + ((wB_t - wA_t) x p) * omegaA + ((wB_R * fB_t) x p) * (omegaA - omegaB) = 0

and the corresponding equation seen from B

p * (vA - vB) + ((wB_t - wA_t) x p) * omegaB + ((wA_R * fA_t) x p) * (omegaA - omegaB) = 0

you can compute the mass-weighted sum of both equations, and the second term is in fact what is implemented in Bullet.


But the last term becomes

((alphaA * wB_R * fB_t + alphaB * wB_A * fA_t) x p) * (omegaA - omegaB)

with the weights alphaA, alphaB. Only if (alphaA * wB_R * fB_t + alphaB * wB_A * fA_t) is parallel to the slider axis, the difference of the angular velocities in direction of slider axis is projected away.


There is another thing which I think is a bug: The limit computation multiplies by info->fps, but this should be a division?

Code: Select all

info->m_lowerLimit[srow] += -getMaxLinMotorForce() * info->fps;
info->m_upperLimit[srow] += getMaxLinMotorForce() * info->fps;
...
info->m_lowerLimit[srow] = -getMaxAngMotorForce() * info->fps;
info->m_upperLimit[srow] = getMaxAngMotorForce() * info->fps;
User avatar
rponomarev
Posts: 56
Joined: Sat Mar 08, 2008 12:37 am

Re: Bug in slider constraint

Post by rponomarev »

Yes, looks like you are right.
We should not use

Code: Select all

c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
because this does not work when constraint frame does not coincide with center of mass
We'll come to a better solution in the next release


Definition of MaxLinMotorForce could be confusing, see the thread
http://bulletphysics.com/Bullet/phpBB3/ ... 896#p12896

Thanks,
Roman