btGeneric6DofConstraint motor ineffective at limits
Posted: Thu Feb 28, 2013 9:01 am
I have come across a situation where the btGeneric6DofConstraint gets stuck at its limit, regardless of what motor force I apply in the opposite direction (away from the limit)
Below is an extract from the get_limit_motor_info2 function in btGeneric6DofConstraint.cpp:
The problem line is the condition
Which is where the force from the motor is actually added.
The result is that when the constraint is outside its limit, the only effort to move the constraint back into its limits is the code:
And this ERP is often not sufficient to get the constraint back within its limits, due to external forces applied elsewhere.
Removing the if condition
inside the powered branch seems to resolve the issue. In fact looking at the btHingeConstraint, this is exactly the what the hinge does. getMotorFactor already takes care of limiting the m_constraintError in the direction of the limit, so the extra test should never be necessary.
Is there something I am missing in this regard?
Below is an extract from the get_limit_motor_info2 function in btGeneric6DofConstraint.cpp:
Code: Select all
if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0;
info->m_constraintError[srow] = btScalar(0.f);
if (powered)
{
info->cfm[srow] = limot->m_normalCFM;
if(!limit)
{
btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
btScalar mot_fact = getMotorFactor( limot->m_currentPosition,
limot->m_loLimit,
limot->m_hiLimit,
tag_vel,
info->fps * limot->m_stopERP);
info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
info->m_lowerLimit[srow] = -limot->m_maxMotorForce;
info->m_upperLimit[srow] = limot->m_maxMotorForce;
}
}
if(limit)
{
btScalar k = info->fps * limot->m_stopERP;
if(!rotational)
{
info->m_constraintError[srow] += k * limot->m_currentLimitError;
}
else
{
info->m_constraintError[srow] += -k * limot->m_currentLimitError;
}
info->cfm[srow] = limot->m_stopCFM;
if (limot->m_loLimit == limot->m_hiLimit)
{ // limited low and high simultaneously
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
else
{
if (limit == 1)
{
info->m_lowerLimit[srow] = 0;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
else
{
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = 0;
}
// deal with bounce
if (limot->m_bounce > 0)
{
...
}
}
}
Code: Select all
if (!limit)
{
...
}
The result is that when the constraint is outside its limit, the only effort to move the constraint back into its limits is the code:
Code: Select all
btScalar k = info->fps * limot->m_stopERP;
if(!rotational)
{
info->m_constraintError[srow] += k * limot->m_currentLimitError;
}
else
{
info->m_constraintError[srow] += -k * limot->m_currentLimitError;
}
Removing the if condition
Code: Select all
if (!limit)
Is there something I am missing in this regard?