Rolling Friction Scaling issues

Post Reply
rolfvdhulst
Posts: 7
Joined: Sun Oct 06, 2019 9:10 pm

Rolling Friction Scaling issues

Post by rolfvdhulst »

I am having some issues with Rolling Friction when scaling my world up.

I am trying to simulate a small sphere that starts with linear velocity and no angular velocity. According to the physics/mathematical model, we should have the ball first sliding with fast deceleration whilst linear velocity decreases heavily but angular velocity increases. When the ball starts rolling, the kinetic friction responsible for sliding no longer has any effect and the ball velocity only decreases because of rolling friction.

So what I want to do; sphere experiences kinetic friction u under sliding and rolling friction u_r when rolling (With the total friction force being u*F_n for both, F_n being the normal force).
Since the sphere and other objects are small I need to scale up the world as recommended by the wiki. However, Rolling friction just is not behaving as I expect it to. When I scale up the world by factor X, the rolling friction seems to decrease by factor 1/X even though I am setting it as constant. Even when the objects are in the 0.5-10 size range as recommended I am still experiencing this. Also; even at scale 1 the rolling friction is off by a huge factor, being much larger (~ 3 to 4 times) than the actual kinetic friction even though it's roughly 1/10th of the value.

Questions:
- How is rolling friction modelled/implemented in bullet?
- Why is the rolling friction larger than my kinetic friction even though the value is smaller at scale 1?
- How is rolling friction dependent on my world scaling? (Am I making a mistake somewhere?)

I am probably doing something wrong with scaling or misunderstanding how friction/rolling friction interact in bullet. Is there an easy to solution to this problem, or do I need to implement rolling friction manually? This is my first time working with Bullet and I only have very light experience with ODE before this, so feel free to point out any problems even if unrelated.

Any help would be greatly appreciated. Below is the relevant code reduced to a small example. I simply call this code from a small and simple main to test.

Code: Select all

//
// Created by rolf on 17-10-19.
//

#ifndef BULLETTEST_SIMULATOR_H
#define BULLETTEST_SIMULATOR_H

#include "btBulletDynamicsCommon.h"

class Simulator {
public:
    Simulator();
    ~Simulator();
    void stepSimulator();
    btVector3 ballPosition() const;
    btVector3 ballVelocity() const;
    btVector3 ballAngVelocity() const;
    void printBallAcc() const;
private:
    btVector3 lastVel=btVector3();

    btDefaultCollisionConfiguration *collisionConfig;
    btCollisionDispatcher *collisionDispatcher;
    btBroadphaseInterface *overlappingPairCache;
    btSequentialImpulseConstraintSolver *solver;
    btDynamicsWorld* world;
    btStaticPlaneShape* plane;
    btCollisionObject* planeBody;
    btSphereShape* ball;
    btRigidBody* ballBody;
    btMotionState* ballMotionState;
};


#endif //BULLETTEST_SIMULATOR_H

Code: Select all

//
// Created by rolf on 17-10-19.
//

#include <iostream>
#include "Simulator.h"
const float GRAVITY=-9.81;//m/s^2
const float BALLRADIUS=0.02133;//m
const float BALLMASS=0.04593;//kg
const float PLANEFRICTION=1.0f;
const float BALLFRICTION=0.35f;
const float BALLROLLINGFRICTION=0.0357f;
const float SCALE=100;
const float SIMULATIONSTEP=1/200.0;
const int SUBSTEPS=100;
const float INTERNALSTEP=1/20000.0;

Simulator::Simulator() {

    btVector3 initialPos(0.0f,0.0f,BALLRADIUS*SCALE);
    btVector3 initialVel(2.0f*SCALE,0.0f,0.0f);

    //Contains default setup for memory and how collisions between different types of objects are handled/calculated
    collisionConfig = new btDefaultCollisionConfiguration();

    //uses the default dispatcher. We might want to use the parallel one down the road.
    collisionDispatcher = new btCollisionDispatcher(collisionConfig);

    //btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
    overlappingPairCache = new btDbvtBroadphase();

    //the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
    solver = new btSequentialImpulseConstraintSolver();

    // the world in which all simulation happens
    world= new btDiscreteDynamicsWorld(collisionDispatcher,overlappingPairCache,solver,collisionConfig);
    world->setGravity(btVector3(0.0,0.0,SCALE*GRAVITY));

    //create a static plane
    plane = new btStaticPlaneShape(btVector3(0.0f, 0.0f, 1.0f), 0.0f);
    planeBody= new btCollisionObject();
    planeBody->setCollisionShape(plane);
    btTransform worldPlaneTransform;
    worldPlaneTransform.setIdentity();
    worldPlaneTransform.setOrigin(btVector3(0.0f,0.0f,0.0f));
    planeBody->setWorldTransform(worldPlaneTransform);
    planeBody->setRestitution(0.0);
    planeBody->setFriction(PLANEFRICTION);
    planeBody->setRollingFriction();
    //add it to the world
    world->addCollisionObject(planeBody);
    //create a ball
    ball = new btSphereShape(SCALE*BALLRADIUS);
    btVector3 inertia;
    ball->calculateLocalInertia(BALLMASS,inertia);
    /*
    btVector3 inertia(1.0,1.0,1.0);
    inertia*=0.4*BALLMASS*BALLRADIUS*BALLRADIUS*SCALE*SCALE;
    */
    btTransform worldBallTransform;
    worldBallTransform.setIdentity();
    worldBallTransform.setOrigin(initialPos);
    ballMotionState = new btDefaultMotionState(worldBallTransform);
    //construct the rigid body for collisions
    btRigidBody::btRigidBodyConstructionInfo rbInfo(BALLMASS, ballMotionState, ball, inertia);
    ballBody = new btRigidBody(rbInfo);
    ballBody->setLinearVelocity(initialVel);
    ballBody->setRestitution(0.0f);
    ballBody->setFriction(BALLFRICTION);
    ballBody->setRollingFriction(BALLROLLINGFRICTION);
    ballBody->setSleepingThresholds(0.01*SCALE,0.01/2/M_PI);
    //add the constructed rigid Body to the world
    world->addRigidBody(ballBody);

    std::cout<<"sliding decel: "<<BALLFRICTION*GRAVITY<<std::endl<<"rolling decel: "<<BALLROLLINGFRICTION*GRAVITY<<std::endl;
}
void Simulator::stepSimulator() {
    lastVel=ballVelocity();
    world->stepSimulation(SIMULATIONSTEP,SUBSTEPS,INTERNALSTEP);
}
btVector3 Simulator::ballPosition() const {
    btTransform transform;
    ballMotionState->getWorldTransform(transform);
    return transform.getOrigin()/SCALE;
}
btVector3 Simulator::ballVelocity() const {
    return ballBody->getLinearVelocity()/SCALE;
}
btVector3 Simulator::ballAngVelocity() const {
    return ballBody->getAngularVelocity();
}
void Simulator::printBallAcc() const{
    //print dv/dt
    std::cout<<(ballVelocity()-lastVel).x()/SIMULATIONSTEP<<std::endl;
}
Simulator::~Simulator() {
    delete ballBody;
    delete ballMotionState;
    delete ball;
    delete planeBody;
    delete plane;
    delete world;
    delete solver;
    delete overlappingPairCache;
    delete collisionDispatcher;
    delete collisionConfig;
}
rolfvdhulst
Posts: 7
Joined: Sun Oct 06, 2019 9:10 pm

Re: Rolling Friction Scaling issues

Post by rolfvdhulst »

Turns out there was an error in the modelling of the rolling friction; rolling friction also decreases the torque so I needed to scale my rolling friction since I'm also scaling the ball Radius.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Rolling Friction Scaling issues

Post by drleviathan »

If you have identified a bug in the rolling friction implementation, would you be able to supply a fix and submit a pull request (PR) against the bullet github repository? Alternatively, would you be able to explain the bug/fix so that someone else could make that PR?
rolfvdhulst
Posts: 7
Joined: Sun Oct 06, 2019 9:10 pm

Re: Rolling Friction Scaling issues

Post by rolfvdhulst »

I'm sorry if I was not clear enough; there is no bug with Bullet. I identified a mistake in the way we set up the physics equations so Bullet was not behaving inconsistently, it actually helped us identify a crucial error.

We measured the linear deceleration of a ball but forgot that during the rolling phase the friction on the ball is not just decelerating the linear velocity of the ball, but is also decelerating the angular velocity. Thus our the friction we measured friction was too low by a factor of 7/5* radius of the ball (due to the torque being ball being applied and moments of inertia, if you do the math using euler equations it checks out). Since the ball radius scales with the world scale I observed the above.

Maybe I am misunderstanding how bullet *should* handle angular friction now, but I have definitely found the source of the error in a modelling sense. As far as I understand rolling friction is just simply the friction coefficient times the Normal Force exerted in the opposite direction of travel at the point of contact (and doesn't take into account the object sliding over the surface), so when scaling the world it should be the users' responsibility to also scale rolling friction since the length of the torque axis is also increased.
Post Reply