I've tried implementing the PGS method in Erin Catto's paper to resolve collisions. Currently I have not implemented warmstarting. Stacking works well when friction is disabled. However, when I add friction, dropping a box from a height causes it to wobble significantly and fall over when hitting the ground.
My algorithm currently adds all constraints for all contact points into a single jacobian (labelled j), and follows this order:
j[0] = contactNormalConstraint [ contactPoint 0]
j[1] = contactFrictionConstraint [ contactPoint 0]
j[2] = contactNormalConstraint [ contactPoint 1]
j[3] = contactFrictionConstraint [ contactPoint 1]
I then feed j into the PGS solver (using the naive initial guess of lambda = 0 for all i). The PairWiseVel and PairWiseMass structs just contain linear and rotational velocities, and mass (inertia) respectively.
void Constraints::solveConstraints(CStructs::PairWiseVel &returnVel,
std::vector<CStructs::Constraint> &j,
CStructs::PairWiseMass &pwm,
std::vector<float> &lambda)
{
std::vector<float> d;
for(int i=0; i<j.size(); ++i)
{
d.push_back(getDenom(j[i], pwm));
}
for(int c=0; c<5; ++c)
{
for(int i=0; i<d.size(); ++i)
{
float dlambda = - (multiply(j[i], returnVel) + j[i].bias)/d[i];
float l0 = lambda[i];
lambda[i] = std::max(j[i].lambdaMin, std::min(l0 + dlambda,
j[i].lambdaMax));
dlambda = lambda[i] - l0;
returnVel.v1 = returnVel.v1 + dlambda * j[i].c1 / pwm.m1;
returnVel.v2 = returnVel.v2 + dlambda * j[i].c2 / pwm.m2;
returnVel.w1 = returnVel.w1 + dlambda * j[i].cw1 / pwm.i1;
returnVel.w2 = returnVel.w2 + dlambda * j[i].cw2 / pwm.i2;
}
}
}
Is it likely that the lack of warmstarting causes this instability? At 50 iterations, a dropped box doesn't fall over when hitting the floor, but a stack of two or more falls immediately. I am just wondering if there's something I've done wrong before implement warmstarting.