Dec 16 2010

Physics 101 Part 1 of N : Acceleration

Category: MobileJoel Ivory Johnson @ 04:10

Physic 101: Acceleration

When I was in college since I was going after a B.S. of Computer Science I was required to take the calculus based physics classes (those going after a B.A. of Computer Science could take the Algebra based versions instead). Because of some conversion complications with the school changing from the quarter system to the semester system I had to take a full year of physics classes to ensure I didn't loose credits. Since then I've used the math I've learned there for reasons of personal curiousity (though I must admit I've not had the frequent desire to do any calculations around accelerating electrons or mass/energy conversion).

It didn't occur to me until a few weeks ago that I should share this knowledge. I'll stick with talking about mechanics and leave the thermodynamics and quantum physics out of the discussion for now, and all of my code examples will run on WP7 (though they may also work on the Xbox 360 and PC). Let's start with talking about Acceleration.

A word about measurement units. I live in the USA and here we use English units such as inch, foot, mile, pound, and ton. These units don't seem to have much to do with each other and tend to complicate the math that involves these units. The SI units work out much nicer. For those that live in much of the rest of the world this may conform to the way you already do things. For those living in the USA I hope you don't mind conforming to this different way of doing things. But I just plan to avoid using the English system of metrics all together (imagine if the engineers at Lockheed Martin had done the same thing!).

Acceleration

Let's say I told you to create a Windows Phone project that will accelerate a red dot on the screen. Using your rendering technology of choice you position the red dot on the screen and start moving it at a constant rate in some direction. While that works, it doesn't look natural. Acceleration in the real world is usually gradual. An object that accelerated from 0 km/h to 60 km/h also traveled at intermidiate speeds between 0km and 60km. Let's take a look at how acceleration works and then use that to implement a more natural looking program.

Exactly what is acceleration? Accceleration is a change in velocity. Velocity is a combination speed and direction. If you are travelling on a straight road at 60 km/h that information alone doesn't describe your velocity. It only describes your speed. If you are said to be travelling at 60 km/h on a straight road heading north then your velocity has been described (at least within a 2 dimensional sense. I'm ignoring changes in elevation). If you change either your speed or your direction your velocity is changing. Speeding up, slowing down, or turning the steering wheel will cause your vehicle to experience acceleration.

If you increase your speed from 60 km/h to 80 km/h in 5 seconds without changing direction you've changed your speed by 20 km/h. Assuming your changed your speed at a constant rate during that 5 seconds you accelerated by 4 km/h per second.

An astute observer may have noticed that there are two units of time expressed above: the hour and the second. For the sake of consistency we can convert the change in speed from km/h to m/s. Our change in 20 km/h is equal to a change of 55.4 m/s (feel free to check my math here and or anywhere else in this article and inform me if I make any mistakes). So we can now say the rate of accelerate was 11.1 m/s per second (also expressable as 11.1 m/s^2). Technically there's a direction component to the acceleration. When one doesn't state the direction component then it is assumed to be in the same direction in which the object is already travelling. If the acceleration is negative then it is assumed to be in a direction opposing to that in which the object is travelling.

With the above I've discussed enough for some one to model acceleration. In making use of the existing XNA classes I could use a Vector3 to represent the position of an object in three dimensional space. To represent its velocity I can also use a Vector3. The X, Y, and Z values on the Vector3 will indicate how many units the body moves along the X, Y, and Z axis in a second. The rate of acceleration along the X, Y, and Z are once again representable with a Vector3.

public class Body
{
    public Vector3 Position;
    public Vector3 Velocity;
    public Vector3 Acceleration;

    public void ApplyVelocity(float seconds)
    {
        Position += seconds*Velocity;
    }

    public void ApplyAcceleration(float seconds)
    {
        Velocity += seconds*Acceleration;
    }
}

If you've ever taken any courses in calculus then you may recognize velocity as being a first order derivitive of position with respect to time. Acceleration is a first order derivitive of velocity with respect to time, or a second order derivitive of position. It's possible to have a third order element to describe changes in acceleration (I can think of some scenarios involving propulsion engines to which this would apply) but I won't go that far in any of these example.

It is clear in the above code that I am using seconds as my units of time. You can interpret the units of distance to be what ever you want (meters, feet, pixels, yards, whatever). However one decides to map the numbers to the physical world is of no impact to the meaning of the examples. With the above code if I give an object a position, a velocity, and acceleration we can then simulate it's movement by letting the velocity get adjusted by the acceleration (ApplyAcceleration) and then applying the velocity to the position (ApplyVelocity). Rather than manipulate my bodies independently I'll create a world in which to put them and will manipulate them all at once through this world. Since my world will be a collection of bodies I find it appropriate to derrive my world class from a List base.

public class World: List<Body>
{
    public float Width { get; set;  }
    public float Height { get; set;  }

    public World()
    {   
    }

    public void Step(float seconds)
    {
        foreach (var b in this)
        {
            b.ApplyAcceleration(seconds);
        }
        foreach (var ball in this)
        {
            ball.ApplyVelocity(seconds);
        }
    }
}

The Width and Height members on my world have no impact on the logic but are only there for scaling the world on a display (elements that move outside of the world's height or width are not gauranteed to be displayable on the screen, but those within the area of the world will always be rendered).

With this simple implementation it's possible to simulate acceleration. Let's take a look at the XNA source in which I host my two classes.  In addition to the declarations that one get's in an XNA project I've added a few more to the Game1 class.

private World _myWorld;         //For manipulating the elements of my world
private float _worldScale;      //for scaling the world up/down to fit on the screen
private Vector2 _worldOffset;   //for centering the world on the screen
private Texture2D _ballTexture; //an image of a ball to represent the body

In the constructor for the game I need to instantiate my world and add some bodies to it. I'm adding bodies with three types of movement. The first body will have a velocity but zero acceleration. So it will move at a constant speed. The second body will accelerate in the same direction as its initial velocity. So it will speed up. The third object will have a velocity causing it to move up and to the right but it will accelerate in a downward direction. The path that this body follows will conform to what many know as projectile motion.

_myWorld = new World(){Width = 320, Height = 240};
//Constant Motion Body
_myWorld.Add(new Body(){
        Position = new Vector3(10, 70, 0),
        Velocity = new Vector3(0,0,0),
        Acceleration=new Vector3(3.0f,0f,0)
    });

//Body accelerating in same direction as movement
_myWorld.Add(new Body() { 
        Position = new Vector3(10, 140, 0), 
        Velocity = new Vector3(20.0f, 0f, 0), 
        Acceleration = new Vector3(0,0,0)
    });

//Body accelerating in direction not parallel to initial velocity.
// will follow a projectile path.
_myWorld.Add(new Body() { 
        Position = new Vector3(0, 0, 0), 
        Velocity = new Vector3(45.0f, 60f, 0), 
        Acceleration = new Vector3(-1, -9, 0) 
    });

While loading the texture I also calculate a scale factor and offset so that the world will be centered on the screen. With the code written this way it is less dependent on the physical resolution of the device on which it is run. I could achieve more resolution independence if I used a vector image of a ball instead of the bitmap. But for this example the effort to do that isn't outweight by the benefit for my immediate purposes.

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    float width = GraphicsDevice.Viewport.Width;
    float height = GraphicsDevice.Viewport.Height;

    var widthScale = width/_myWorld.Width;
    var heightScale = height/_myWorld.Height;
    if(heightScale<widthScale)
    {
        _worldScale = heightScale;
        _worldOffset = new Vector2((width-((int)(_myWorld.Width*heightScale)))/2 ,0);
    }
    else
    {
        _worldScale = widthScale;
        _worldOffset = new Vector2(0, (height- ((int)(_myWorld.Height * widthScale))) / 2);
    }


    
    _ballTexture = Content.Load<Texture2D>("canonBall");

}

In the Update method only contains a single new line beyond what is already present in a new project. The line that I have added makes a call so that the World instance will update the bodies' velocities and positions.

protected override void Update(GameTime gameTime)
{
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();

    _myWorld.Step((float)gameTime.ElapsedGameTime.TotalSeconds);

    base.Update(gameTime);
}

Lastly I need to render the world to the screen. I've made a function to map the coordinates within my world to the coordinates to the screen coordinates based on the scale factor and offset calculated earlier. It is used within the Draw method when rendering the bodies.

Vector2 MapPosition(Vector3 source)
{
    Vector2 retVal = new Vector2();
    retVal.X =  source.X*_worldScale + _worldOffset.X;
    retVal.Y = (_myWorld.Height - source.Y*_worldScale) + _worldOffset.Y;
    return retVal;
}

protected override void Draw(GameTime gameTime)
{
    
    GraphicsDevice.Clear(Color.Black);
    spriteBatch.Begin();
    foreach (var body in _myWorld)
    {
        var newCoord = MapPosition(body.Position);
        spriteBatch.Draw(_ballTexture,newCoord, Color.White);
    }
    spriteBatch.End();
    base.Draw(gameTime);
}

It is easier to see the program running then it is to infer how it operates from static images. So I've recorded the program in action and have uploaded it to YouTube. And motivated by the "because I can!" justification I've also created the solutions so that the example program will run on the PC and the Xbox 360 in addition to running on Windows Phone.

No talk of acceleration would be complete without talking of Newton's second law of motion. The second law of motion describes the relationship between an objects mass, the force applied to that mass, and the object's change in motion. The mathimatic expression for this relationship is F=ma. F is the force applied to the mass. Like velocity and acceleration Force also has a direction component. Even without placing real units of force or mass in the equation there's a few things that can be infered from this relationship. If we rearrange the expression to F/m=a (which is just a different expression for the same relationship) then we can see the difference that the same amount of force would have on objects of two different masses. If we had one object that weighed 12 kilograms and another that weighed 6 kilograms and applied the same amount of force to both we would find the 6 kilogram object would accelerate at twice the rate as the 12 kilogram object. I see this concept employed most often in games in which the player can customize a vehicle and change parts that have various impacts on the vehicle's mass or the engine's strength (force).

The SI unit of force is the Newton (guess who that is named after). A Newton is defined as the amount of force needed to accelerate one kilogram of mass at a rate of a meter/second^2. If you held a kilogram of mass in your hands under the influence of gravity it would exert a force of about 9.81 Newtons downwards. Now let's say you take a coin and apply force to it to slide it across your desk. Once it is no longer under the influence of you pushing it the coin will begin to slow down. This is because of friction. There are usually several different types of friction applied to a moving body. That is a discussion that is deserving of a post on its own. So for now I will bring this post to a close and in the next one I'll continue with either Friction of Gravity.

Tags: , ,

Comments

1.
pingback topsy.com says:

Pingback from topsy.com

Twitter Trackbacks for
        
        Physics 101 Part 1 of N : Acceleration
        [j2i.net]
        on Topsy.com