SImulating Springs with the btgeneric6dofspringconstraint

Post Reply
randomlogic78
Posts: 3
Joined: Wed Feb 15, 2012 10:29 pm

SImulating Springs with the btgeneric6dofspringconstraint

Post by randomlogic78 » Wed Feb 15, 2012 10:53 pm

I am working to develop a simulation of a system of sensors. The model for these sensors utilizes springs as a base for a larger model. I am attempting to use the btgeneric6dofspringconstraint to simulate the springs in the sensors. When the "springs" weren't behaving the way I expected I reduced my simulation down to a single mass attched to a static mass connected by a btgeneric6dofspringconstraint. I then compared the motion of the dynamic mass from bullet, with the motion of the mass in a Simulink (MATLAB) model. They don't match... So, how do I implement a bullet btgeneric6dofspringconstraint object so that I get behavior that one would expect from a SHO?

MATLAB:
SpringMATLAB.png
SpringMATLAB.png (202.58 KiB) Viewed 2454 times
Bullet:
spring.png
spring.png (3.57 KiB) Viewed 2454 times
The following is my implementation file for my spring class:

Code: Select all

#include "spring.h"

spring::spring( )
{
    setDynamicMass( (new btScalar(1.0f)) );
    setDirectionOfMotion( 0 );
    setSpringConstant( (new btScalar(30.0f)) );
    setDampingConstant( (new btScalar(0.01f)) );
    setSpringTravel( (new btScalar(10.0f)), (new btScalar(7.0f)) );
    offsetFromEqualibrium = new btScalar( -5.0f );
    initializeStaticBody( );
    initializeDynamicBody( );
    initializeSpringConstraint( );
}

spring::spring( btScalar* springConstant, btScalar* dampingConstant,
                btScalar* restLength, btScalar* maxDisplacement, 
                btScalar* dynamicMass, int directionOfMotion )
{
    setDynamicMass( dynamicMass );
    setDirectionOfMotion( directionOfMotion );
    setSpringConstant( springConstant );
    setDampingConstant( dampingConstant );
    setSpringTravel( restLength, maxDisplacement );
    initializeStaticBody( );
    initializeDynamicBody( );
    initializeSpringConstraint( );
}

spring::~spring( )
{
    delete staticBaseShape;
    delete translationalMassShape;
    delete staticBaseMotionState;
    delete translationalMassMotionState;
    delete staticBaseBody;
    delete translationalMassBody;
    delete springConstraint;
    delete frameInA;
    delete frameInB;
    delete springConstant;
    delete dampingConstant;
    delete restLength;
    delete maxDisplacement;
    delete dynamicMass;

}

void spring::initializeStaticBody( )
{
    frameInA = new btTransform( btTransform::getIdentity() );
    staticBaseShape = new btBoxShape( btVector3(0.5f, 0.5f, 0.5f) );
    staticBaseMotionState = new btDefaultMotionState( btTransform( 
                                    btQuaternion( 0, 0, 0, 1 ), 
                                    btVector3( 0.0f, 1.0f, 0.0f ) ) );
    btRigidBody::btRigidBodyConstructionInfo staticBodyCI( 0, 
                                    staticBaseMotionState, staticBaseShape,
                                    btVector3( 0, 0, 0 ) );
    staticBaseBody = new btRigidBody( staticBodyCI );
    staticBaseBody->setActivationState( DISABLE_DEACTIVATION );
    staticBaseBody->getMotionState( )->getWorldTransform( *frameInA );
}

void spring::initializeDynamicBody( )
{
    frameInB = new btTransform( btTransform::getIdentity() );
    translationalMassShape = new btBoxShape( btVector3(0.5f, 0.5f, 0.5f) );
    translationalMassMotionState = new btDefaultMotionState( btTransform( 
                                    btQuaternion( 0, 0, 0, 1 ), 
                                    btVector3( *restLength - 
                                    *offsetFromEqualibrium, 1.0f, 0.0f ) ) );
    btRigidBody::btRigidBodyConstructionInfo translationalMassBodyCI( 
                                    *dynamicMass, translationalMassMotionState,
                                    translationalMassShape, 
                                    btVector3( 0, 0, 0 ) );
    translationalMassBody = new btRigidBody( translationalMassBodyCI );
    translationalMassBody->setActivationState( DISABLE_DEACTIVATION );
    translationalMassBody->getMotionState( )->getWorldTransform( *frameInB );
}

void spring::initializeSpringConstraint( )
{
    springConstraint = new btGeneric6DofSpringConstraint( *staticBaseBody,
                                    *translationalMassBody, *frameInA, 
                                    *frameInB, true );
    springConstraint->setLinearUpperLimit( btVector3( *restLength + *maxDisplacement, 0., 0.) );
    springConstraint->setLinearLowerLimit( btVector3( *restLength - *maxDisplacement, 0., 0. ) );
    springConstraint->setAngularLowerLimit( btVector3( 0.f, 0.f, 0.f ) );
    springConstraint->setAngularUpperLimit( btVector3( 0.f, 0.f, 0.f ) );    
    springConstraint->enableSpring( 0, true );
    // period 1 sec for !kG body
    springConstraint->setStiffness( 0, *springConstant );
    // add some damping
    springConstraint->setDamping( 0, *dampingConstant );
    // constraint force mixing prevents "locking" on limits, might be bad
    springConstraint->setParam( BT_CONSTRAINT_STOP_CFM, 1.0e-5f, 5 ); 
    // Set the cfm so the spring behaves... doesn't have any effect (seemingly)
    //springConstraint->setParam( BT_CONSTRAINT_CFM, 1.0/((1/60.)*(*springConstant)+(*dampingConstant)),0 );
    // set current position as equilibrium point
    springConstraint->setEquilibriumPoint( ); 
}

void spring::setDynamicMass( btScalar* dynamicMass )
{
    this->dynamicMass = dynamicMass;
}

void spring::setSpringConstant( btScalar* springConstant )
{
    this->springConstant = springConstant;
}

void spring::setDampingConstant( btScalar* dampingConstant )
{
    this->dampingConstant = dampingConstant;
}

void spring::setSpringTravel( btScalar* restLength, 
                              btScalar* maxDisplacement )
{
    this->maxDisplacement = maxDisplacement;
    this->restLength = restLength;
}
        
void spring::setDynamicBodyOffset( btScalar* offsetFromEqualibrium )
{
    this->offsetFromEqualibrium = offsetFromEqualibrium;
}

void spring::setDirectionOfMotion( int directionOfMotion )
{
    this->directionOfMotion = directionOfMotion;
}

btRigidBody* spring::getDynamicBody( )
{
    return translationalMassBody;
}

btMotionState* spring::getDynamicBodyMotionState( )
{
    return translationalMassMotionState;
}

void spring::addToWorld( btDynamicsWorld* world )
{
    try
    {
        world->addRigidBody( translationalMassBody ); 
        world->addRigidBody( staticBaseBody ); 
        world->addConstraint( springConstraint, true ); 
    }
    catch( std::exception& e )
    {
        std::cout << "Could not add the contraint to the world: "
                  << e.what( ) << std::endl;
    }
}
And my main implmenting it:

Code: Select all

#include <stdio.h>
#include <iostream>
#include <btBulletDynamicsCommon.h>
#include "world.h"
#include "spring.h"

using namespace std;

int main( int argc, char * argv[] )
{

    world* physicsWorld = new world( );
    spring* testSpring = new spring( );

    btVector3* gravity = new btVector3( 0, 0, 0 );
    physicsWorld->setGravity( gravity );
    
    testSpring->addToWorld( physicsWorld->getDynamicsWorld( ) );
        
    btTransform trans;
    //testSpring->getDynamicBody( )->applyForce( btVector3( -1.0f, 0, 0 ),
    //                                           btVector3( 5, 0, 0 ) ); 
    //trans = btTransform::getIdentity( );
    //trans.setOrigin( btVector3( 6.0f, 1.0f, 0.0f ) );
    //testSpring->getDynamicBodyMotionState( )->setWorldTransform( trans );

    std::cout << "#Dynamic mass\n#x location,y location,z location, time" << std::endl; 

    for (int i=0 ; i<300 ; i++) {

        physicsWorld->getDynamicsWorld()->stepSimulation(1/60.f,10); 
 
        testSpring->getDynamicBodyMotionState( )->getWorldTransform(trans);
 
        std::cout << trans.getOrigin().getX() 
                  << "," << trans.getOrigin().getY() 
                  << "," << trans.getOrigin().getZ()
                  << "," << i*1/60.0f 
                  << std::endl;
    }

    delete physicsWorld;
    delete testSpring;

	return 0;
}
Attachments
spring.cpp
(5.53 KiB) Downloaded 81 times

kloplop321
Posts: 55
Joined: Sun Jan 01, 2012 7:37 pm

Re: SImulating Springs with the btgeneric6dofspringconstrain

Post by kloplop321 » Thu Feb 16, 2012 2:36 am

You should probably take a look at the restitution factor, it might be defaulting to something which does not match MATLAB.

Additionally, Bullet is not made for scientific research and it is discouraged to use it for such, as it is only for approximating a simulation within a desirably short simulation computation time.

randomlogic78
Posts: 3
Joined: Wed Feb 15, 2012 10:29 pm

Re: SImulating Springs with the btgeneric6dofspringconstrain

Post by randomlogic78 » Thu Feb 16, 2012 4:39 am

kloplop321 wrote:You should probably take a look at the restitution factor, it might be defaulting to something which does not match MATLAB.
As in the stiffness constant that I set is being reset somewhere in bullet? Where would this be happening? Why?

kloplop321 wrote:Additionally, Bullet is not made for scientific research and it is discouraged to use it for such, as it is only for approximating a simulation within a desirably short simulation computation time.
Do you have any suggestions on better libraries for detecting collisions?

kloplop321
Posts: 55
Joined: Sun Jan 01, 2012 7:37 pm

Re: SImulating Springs with the btgeneric6dofspringconstrain

Post by kloplop321 » Thu Feb 16, 2012 7:23 pm

randomlogic78 wrote:
kloplop321 wrote:You should probably take a look at the restitution factor, it might be defaulting to something which does not match MATLAB.
As in the stiffness constant that I set is being reset somewhere in bullet? Where would this be happening? Why?
I was confused, I was thinking about the SliderConstraint.


randomlogic78 wrote: Do you have any suggestions on better libraries for detecting collisions?
I would be no better than a random person searching for words on google.

If you want to continue to use bullet, and be mathematically accurate, you could modify or create a derived solver with your own algorithm which may be more accurate.

To me it looks like the dampening values are of different scales between MATLAB and bullet, according to your demonstrating charts.

Have you tried to changing your default dampening ratio from 0.01 to 0.001 or 0.0001?
It might be a matter of which units you are in.

randomlogic78
Posts: 3
Joined: Wed Feb 15, 2012 10:29 pm

Re: SImulating Springs with the btgeneric6dofspringconstrain

Post by randomlogic78 » Thu Feb 16, 2012 9:47 pm

kloplop321 wrote:
To me it looks like the dampening values are of different scales between MATLAB and bullet, according to your demonstrating charts.

Have you tried to changing your default dampening ratio from 0.01 to 0.001 or 0.0001?
It might be a matter of which units you are in.
I have tried changing the constants. The two graphs that I put up have matching values for the constants. Interestingly, if you look at the graph from bullet, the dynamic object also appears to be moving through the static object. At a minimum there should be a collision occurring when the dynamic object's center of mass is at x=1.0f. This does not seem to be happening. Any thoughts there?

Post Reply