Jan Bender wrote:
I should take a look at this class. How did you realize the joint limits?
Joint limits (linear+angular) on the Generic 6 DOF constraint are handled exactly the same as contact constraints in Bullet. If an axis has a limited range of motion it becomes a unilateral constraint (positional + velocity).
Note that a fully locked (upper limit == lower limit) axis becomes a bilateral constraint. Please check the codesnippet at the end of this posting, it shows the linear limit solving of one axis, taken from
Bullet/src/BulletDynamics/btGeneric6DofConstraint.cpp
If i understand you correctly, the error is just corrected after it occured by iterating over the time. So if a constraint is not satisfied an impulse is applied and then the time step is made. In this way it can not be guaranteed that all constraints are satisfied but it could speed-up the simulation a lot. I will try this and tell you the result.
In my experience with several physics engines it is not easy to say that an approach can guarantee constraint satisfacton by just taking one concept into account, there are too many details that all interact and matter.
If I understand correctly your approach is still discrete, so it suffers from tunneling: for fast moving objects, the 'predicted' position in the next timestep can totally fail to measure any error/overlap?
This is the discrete mode of Bullet, which uses indeed the very popular 'retroactive determination' by correcting the penetration/constraint drift error afterwards. I recognize there is a difference in your approach, because you seem to try to prevent the error by predicting a future error. However, this prediction itself might be inaccurate due to tunelling/discretization.
However Bullet also has continuous collision detection, which allows time of impact calculation, so you can step up until the time, and avoid generating the penetration error in the first place. This solves the actual problem of tunneling/missing collisions for fast moving object. This can also be applied to constraints, but this isn't implemented in Bullet yet (temporal constraints).
Have you considered predicting and stepping up to the the actual time of the discontinuity? For collisions this discontinuity would be the time of impact and for other joints, it would be the time when the constraint hits the limit.
Thanks,
Erwin
Code: Select all
//velocity error (first order error)
btScalar rel_vel = m_jacLinear[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA,
m_rbB.getLinearVelocity(),angvelB);
//positional error (zeroth order error)
btScalar depth = -(pivotAInW - pivotBInW).dot(normalWorld);
btScalar lo = -1e30f;
btScalar hi = 1e30f;
//handle the limits
if (m_lowerLimit[i] < m_upperLimit[i])
{
{
if (depth > m_upperLimit[i])
{
depth -= m_upperLimit[i];
lo = 0.f;
} else
{
if (depth < m_lowerLimit[i])
{
depth -= m_lowerLimit[i];
hi = 0.f;
} else
{
continue;
}
}
}
}
btScalar normalImpulse= (tau*depth/timeStep - damping*rel_vel) * jacDiagABInv;
float oldNormalImpulse = m_accumulatedImpulse[i];
float sum = oldNormalImpulse + normalImpulse;
m_accumulatedImpulse[i] = sum > hi ? 0.f : sum < lo ? 0.f : sum;
normalImpulse = m_accumulatedImpulse[i] - oldNormalImpulse;
btVector3 impulse_vector = normalWorld * normalImpulse;
m_rbA.applyImpulse( impulse_vector, rel_pos1);
m_rbB.applyImpulse(-impulse_vector, rel_pos2);