Support btMultiBody soft contact using ERP and CFM. Also support custom relaxation parameter to allow successive over relaxation.

Added demos for rigid and multi body soft (compliant) contact.
Will also add simplified Hertz compliant contact, by dynamically modifying the ERP/CFM to mimic a non-linear spring.
Note that btManifoldPoint is growing too big, we need to implement proper contact constraints derived from btTypedConstraint.
This commit is contained in:
erwin coumans
2016-02-22 18:40:00 -08:00
parent a3154f7a56
commit 6c9bfce975
10 changed files with 435 additions and 19 deletions

View File

@@ -39,6 +39,7 @@ enum btContactPointFlags
{
BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED=1,
BT_CONTACT_FLAG_HAS_CONTACT_CFM=2,
BT_CONTACT_FLAG_HAS_CONTACT_ERP=4,
};
/// ManifoldContactPoint collects and maintains persistent contactpoints.
@@ -55,6 +56,7 @@ class btManifoldPoint
m_contactMotion1(0.f),
m_contactMotion2(0.f),
m_contactCFM(0.f),
m_contactERP(0.f),
m_frictionCFM(0.f),
m_lifeTime(0)
{
@@ -78,6 +80,7 @@ class btManifoldPoint
m_contactMotion1(0.f),
m_contactMotion2(0.f),
m_contactCFM(0.f),
m_contactERP(0.f),
m_frictionCFM(0.f),
m_lifeTime(0)
{
@@ -114,6 +117,8 @@ class btManifoldPoint
btScalar m_contactMotion1;
btScalar m_contactMotion2;
btScalar m_contactCFM;
btScalar m_contactERP;
btScalar m_frictionCFM;
int m_lifeTime;//lifetime of the contactpoint in frames

View File

@@ -780,6 +780,7 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
btScalar cfm = (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM)?cp.m_contactCFM:infoGlobal.m_globalCfm;
cfm *= invTimeStep;
btScalar erp = (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)?cp.m_contactERP:infoGlobal.m_erp2;
btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
@@ -888,12 +889,7 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
btScalar velocityError = restitution - rel_vel;// * damping;
btScalar erp = infoGlobal.m_erp2;
if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
{
erp = infoGlobal.m_erp;
}
if (penetration>0)
{
positionalError = 0;

View File

@@ -221,9 +221,15 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
if (bodyB)
rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
relaxation = 1.f;
relaxation = infoGlobal.m_sor;
btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
btScalar cfm = (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM)?cp.m_contactCFM:infoGlobal.m_globalCfm;
cfm *= invTimeStep;
btScalar erp = (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)?cp.m_contactERP:infoGlobal.m_erp2;
if (multiBodyA)
@@ -366,7 +372,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
btScalar d = denom0+denom1;
btScalar d = denom0+denom1+cfm;
if (d>SIMD_EPSILON)
{
solverConstraint.m_jacDiagABInv = relaxation/(d);
@@ -477,12 +483,6 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
btScalar positionalError = 0.f;
btScalar velocityError = restitution - rel_vel;// * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
btScalar erp = infoGlobal.m_erp2;
if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
{
erp = infoGlobal.m_erp;
}
if (penetration>0)
{
positionalError = 0;
@@ -522,7 +522,10 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
solverConstraint.m_upperLimit = solverConstraint.m_friction;
}
solverConstraint.m_cfm = 0.f; //why not use cfmSlip?
solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv;
}
}