How to get acceleration of a moving object?

Topics: User Forum
Feb 8, 2013 at 1:46 AM
Hi everyone!.

I am comming up with a planetary orbiter (satellite) kinda simulation. I am currently using the below code on the LoadContent() method to generate the gravity towards a planet body.
        FarseerPhysics.Controllers.GravityController gravityCont = new FarseerPhysics.Controllers.GravityController(9.81f, 50, 0.1f);
        gravityCont.World = this.World;
        gravityCont.AddDisabledCategory(Category.Cat2);
        gravityCont.AddBody(planet.Body);
What I need now is to draw an "acceleration vector arrow" experienced by the satellite. I can get the linear velocity vector and draw it, but I dont see any way to get the acceleration vector. The alternative would be to do a differentiation of the velocity vectors with respect to time and that would be too much of math (alot of timing and dt involved). Is there somthing I am missing.

oh by the way...... its been just a month into XNA now.

Any help would be much appreciated.

Thanks.
Feb 17, 2013 at 5:53 AM
wow.........!

No reply so far!......... Did I ask a way too simple question? or am I missing an obvious property or method from the Body object?

Guys..... come on..... !
Feb 17, 2013 at 5:06 PM
I've not used the GravityController before, but looking at the code it appears to simply add forces to the bodies it controls. Body.Force is internal, so you'd need to make it public or add a public GetForce() method or property. Then, it looks like by default the forces are cleared each time step. To avoid this, you'll need to set World.AutoClearForces to false after you create the world and manually do World.ClearForces(). This way you should be able to get the current force on a Body after World.Step(). Where you call World.ClearForces() is important - it should be done before you apply any forces yourself but after you've checked all the body forces for drawing the acceleration.

Alternatively, you could add a public float LastForce to Body that gets set to Body.Force in ClearForces(). This is probably simpler.

Yet another possible approach: if you are applying other forces to the bodies and you want to separate out the gravity controller force, I'd probably modify GravityController to store the last applied forces in a Dictionary<Body, float>.

Whichever way you go, it looks like you won't get away without modifying Farseer :)

Aranda
Developer
Feb 17, 2013 at 5:29 PM
The alternative would be to do a differentiation of the velocity vectors with respect to time and that would be too much of math (alot of timing and dt involved). Is there somthing I am missing.
Probably. Cause in my book subtracting 2 vectors from each other and dividing the result by one float is not "too much of math".
The acceleration is dv/dt, e.g. the change of velocity over time. Your time step should be fixed anyway so dt for subsequent frames should be something like 0,01s (if you do 100 physics steps per second). Just store the velocity of your satellite on each update (Vector2 oldVelocity = myBody.LinearVelocity).

Now your acceleration for the next update is:

(myBody.LinearVelocity - oldVelocity) / 0,01 [your time step]

Modifying the engine for such a simple calculation is a bit overkill i think ;)
Feb 17, 2013 at 6:39 PM
Good point Elsch. Although, an easy way to get the forces acting on a body would be a useful feature IMO.
Developer
Feb 17, 2013 at 6:41 PM
Edited Feb 17, 2013 at 6:44 PM
You can get some properties like the impulse about to be applied to a body in the PreSolve events.
Feb 18, 2013 at 8:27 AM
Modifying Farseer is heavy for me now, and I will have to edit and recompile everytime a new version is out...... So I implemented a timer instead so that 'dt' is taken care of.
    double timer = 0.01;
    Vector2 previousVelocityVector = Vector2.Zero;

    public void UpdateAcceleration(double ElapsedGameTimeInSeconds)
    {
        previousVelocityVector = Body.LinearVelocity;

        double elapsed = ElapsedGameTimeInSeconds;
        timer -= elapsed;
        if (timer < 0)
        {
            //Timer expired, execute action
            previousVelocityVector = Body.LinearVelocity;

            timer = 0.01;  //Reset Timer
        }
    }

    public Vector2 AccelerationVector
    {
        get
        {
            Vector2 acc = (previousVelocityVector - Body.LinearVelocity) / (float)timer;
            return acc;
        }
    }
and called the UpdateAcceleration() method in the Update() method of the PhysicsGameScreen. The 'dt' is timer duration. This was stable and gave better reults compared to matching the 'dt' value to that of the Update()'s frequency of execution.

but I do agree that having an array of vectors for the various forces acting on a body would be usefull, because now we only have the resultant acceleration.

Thanks for the help people!........
Developer
Feb 18, 2013 at 11:12 AM
Just to clear things up: Your dt should match the time step you pass to world.step(). After stepping you can calculate your acceleration and after that set the oldVelocity to the current one.

And again you can also access "vectors for various forces" at different points of the simulation. That's what Pre-, PostSolve, OnCollision, AfterCollision are for. Farseer basically just exposes everything you need to "draw" the simulation. Everything else is probably very game specific and would decrease the performance of the simulation.