Aproximating a circle with Bullet

Post Reply
JPB18
Posts: 2
Joined: Tue Jun 28, 2016 3:15 pm

Aproximating a circle with Bullet

Post by JPB18 »

Hey there!

So I've this project where I'm trying to approximate the movement made by a smartwatch by feeding the accelerometer and the gyroscope data into Bullet (accelerations are set using btRigidBody.applyCentreForce and angular velocities by using btRigidBody.setAngularVelocity at its proper time). Yes I know there's a lot of error in the readings from those sensors, but I'm not exactly there yet. Also, I should note I'm using the version of Bullet included with libGDX.

One of the first tests I made, was to use the 2nd derivative of the circle's parametric equation to feed the acceleration vectors into Bullet. I've a class that stores those vectors and then fetch them according to the current time. I called it a "DataLoader". To feed the DataLoader with the acceleration vectors needed to do a circle, I extended it with the following class:

Code: Select all

public class CircleDataLoader extends DataLoader {

    private boolean gravity;

    public CircleDataLoader(float interval, boolean gravity) {

        this.gravity = gravity;

        final double crads = 2 * Math.PI;
        double rads = 0;
        double time = 0;

        while(rads < crads) {
            Vector3 acc = new Vector3((float) -Math.cos(rads), (float) -Math.sin(rads), 0f); //parametric circle 2nd derivative goes here
            super.data.add(new DataSet(acc, Vector3.Zero, time)); //This stores all relevant data. Rotation isn't being used at the moment, so Vector3.Zero it is
            rads += Math.PI * interval;
            time += interval;
        }

    }


    /**
    * This exists because we're setting Bullets gravity as (0,0,0) and apply it as another force in our rigidbody
    */
    @Override
    public Vector3 getGravity(double time) throws NoMoreElementsException {
        if(!gravity)
            return new Vector3(); //currently not testing with gravity, so this is the gravity vector in all attempts.
        else return new Vector3(0,1,0);
    }
     

    //there's also a find(time) method in the parent class which finds the appropriate acceleration
}

Then in the scene, we use the following to apply the forces (this is inside the game loop):

Code: Select all

        double miliTime = TimeUtils.millis();
        double time = (miliTime-startTime)/1000;  //time is stored in seconds btw
        float dt = Gdx.graphics.getDeltaTime();

        if(loader != null && playing) try {
            DataSet curr = loader.find(time);   //this is our DataLoader, fed from someplace else
            Quaternion orientation = sphereInstance.body.getOrientation(); //just a note: sphereInstance.body is a btRigidBody type
            Vector3 gravity = loader.getGravity(time).mul(orientation).scl(9.8f); //we fetch the gravity vector, rotate it to orientation and then scale it from gs to m/s^2
            sphereInstance.body.applyCentralForce(gravity);   //we apply the gravity here
            sphereInstance.body.applyCentralForce(               //and here we apply the velocity vector and do the same treatment as we did with gravity
                    curr.acceleration.cpy()
                            .mul(orientation).scl(9.8f));
            sphereInstance.body.setAngularVelocity(curr.rotation); //and we set the angular velocity, which isn't important to our example

        } catch (NoMoreElementsException ex) {
            (Not important for our example)
        }

        dynamicsWorld.stepSimulation(dt); //and we update our simulation
So yeah, our problem here is that the simulation only executes half of a circle, and not all of it. However the data being fed is enough to perform an entire circle. Is there any detail of Bullet that is ruining this up for me?

Thanks in advance guys!
Post Reply