### Non-smooth sliding.

Posted:

**Wed May 31, 2017 2:37 pm**I had observed that friction appeared to be less stable in Bullet than in ODE or PhysX for a given friction coefficient. To convince myself of this I created a simple test case consisting of a 10 degree angled ramp with some small boxes to slide down the ramp. Each box has a mass of 1kg and dimensions 0.4m x 0.4m x 0.4m. There's nothing particularly unusual about this model. The friction coefficients are set to 0.15. The timestep is 1/60 seconds and I am using 10 solver iterations. Below is the result:

There are a few things to notice. First is the flickering of the contact points, indicating that contact points are occasionally dropped despite the contact processing threshold being set to 0.01m and the contact breaking threshold being set to 0.02m. Secondly, we can see that the boxes move at radically different speeds despite the friction coefficients all being set to 0.15.

1) First, I disabled SOLVER_RANDMIZE_ORDER:

The boxes still move about a little, but the boxes now all move at approximately the same speed.

2) Secondly, I set gContactCalcArea3Points to false.

The boxes now slide straight down the ramp as desired. There is still some contact point flickering, although this does not seem to adversely affect the behaviour.

----

After a little investigation, it appears as though the randomised constraint ordering code is adapted from ODE. However, unlike in ODE, the friction constraints are randomly shuffled so that the friction constraints for a given contact point do not correspond to the random ordering of the penetration constraints. To clarify, if I swap two penetration constraints for a pair of contact points then I expect to also swap the friction constraints for the pair of contact points. However, this is not the case. Currently, the penetration constraints are randomly shuffled. Then the friction constraints are randomly shuffled. This appears to have an adverse effect, as shown above.

My solution for this is to rewrite the constraint ordering:

As follows:
Now the behaviour is as if SOLVER_RANDMIZE_ORDER is disabled, as shown above.

----

Does anybody know why the contact points do not seem to persist?

There are a few things to notice. First is the flickering of the contact points, indicating that contact points are occasionally dropped despite the contact processing threshold being set to 0.01m and the contact breaking threshold being set to 0.02m. Secondly, we can see that the boxes move at radically different speeds despite the friction coefficients all being set to 0.15.

1) First, I disabled SOLVER_RANDMIZE_ORDER:

The boxes still move about a little, but the boxes now all move at approximately the same speed.

2) Secondly, I set gContactCalcArea3Points to false.

The boxes now slide straight down the ramp as desired. There is still some contact point flickering, although this does not seem to adversely affect the behaviour.

----

After a little investigation, it appears as though the randomised constraint ordering code is adapted from ODE. However, unlike in ODE, the friction constraints are randomly shuffled so that the friction constraints for a given contact point do not correspond to the random ordering of the penetration constraints. To clarify, if I swap two penetration constraints for a pair of contact points then I expect to also swap the friction constraints for the pair of contact points. However, this is not the case. Currently, the penetration constraints are randomly shuffled. Then the friction constraints are randomly shuffled. This appears to have an adverse effect, as shown above.

My solution for this is to rewrite the constraint ordering:

Code: Select all

```
for (int j = 1; j < numConstraintPool; ++j) {
int tmp = m_orderTmpConstraintPool[j];
int swapi = btRandInt2(j + 1);
m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
m_orderTmpConstraintPool[swapi] = tmp;
}
for (int j = 1; j < numFrictionPool; ++j) {
int tmp = m_orderFrictionConstraintPool[j];
int swapi = btRandInt2(j + 1);
m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
m_orderFrictionConstraintPool[swapi] = tmp;
}
```

Code: Select all

```
int swapi = btRandInt2(j + 1);
{
int tmp = m_orderTmpConstraintPool[j];
m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
m_orderTmpConstraintPool[swapi] = tmp;
}
if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
{
int tmp1 = m_orderFrictionConstraintPool[j * 2];
int tmp2 = m_orderFrictionConstraintPool[j * 2 + 1];
m_orderFrictionConstraintPool[j * 2] = m_orderFrictionConstraintPool[swapi * 2];
m_orderFrictionConstraintPool[swapi * 2] = tmp1;
m_orderFrictionConstraintPool[j * 2 + 1] = m_orderFrictionConstraintPool[swapi * 2 + 1];
m_orderFrictionConstraintPool[swapi * 2 + 1] = tmp2;
}
else
{
int tmp = m_orderFrictionConstraintPool[j];
m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
m_orderFrictionConstraintPool[j] = tmp;
}
```

----

Does anybody know why the contact points do not seem to persist?