Forces
Back to The Nature of Code
Examples
download zipped archive of all examples
Related
Newton’s Laws
Note an object that has a mass of one kilogram on earth would have a mass of one kilogram on the moon. However, it would weigh only one-sixth as much.
First Law:
An object at rest stays at rest unless an external force acts on the object. An object in motion stays in motion (at a constant velocity), again, unless an external force is applied.
Second Law:
Force = Mass * Acceleration (this is the formula for an object with a constant mass.) For our purposes, we will know the mass and the force, but want to calculate an object’s acceleration (which is proportional to the force and inversely proportional to the mass, i.e. Acceleration = Force / Mass)
Third Law:
All forces occur in pairs, and these two forces are equal in magnitude and opposite in direction.
Forces acting on an object
For our purposes, the most important law will be #2. Take the following example:
Consider a body with the following properties:
class Thing {
// Instance variables for the class
PVector loc;
PVector vel;
PVector acc;
float mass;
float max_vel;
float bounce = 1.0; // How "elastic" is the object
// Constructor
Thing(PVector a, PVector v, PVector l, float m_) {
acc = a.get();
vel = v.get();
loc = l.get();
mass = m_;
}
Motion will work the same way it did in last week’s examples. For each cycle of the program, for any given object, we will do the following (with one addition from last week):
void update() {
vel.add(acc);
loc.add(vel);
acc.mult(0); // new!
}
We reset the acceleration to 0 here because with each cycle of the program, before updating an object’s location, we will calculate all the forces acting upon that object. Note how multiplying a vector by 0 sets all of the components to 0 (x*0=0, y*0=0, etc).
For each force we will use Newton’s Second Law to calculate acceleration, acculmulating all forces together for a total acceleration of the object. Consider the following:
Here is our algorithm (remember F = M*A, so A = F / M):
FOR ANY GIVEN TIME T:
ACCELERATION CAUSED BY WIND = WIND / MASS = (5,0) / 5 = (1,0)
ACCELERATION CAUSED BY GRAV = GRAV / MASS = (0,10) / 5 = (0,2)
TOTAL ACCELERATION = (1,0) + (0,2) = (1,2)
VELOCITY = VELOCITY + ACCELERATION = (-3,2) + (1,2) = (-2,4)
LOCATION = LOCATION + VELOCITY = (10,20) + (-2,4) = (8,24)
In terms of coding our object, for any given force applied to it, we need a function to receive that force as a parameter and calculate the object’s acceleration according to that force:
void applyForce(PVector force) {
force.div(mass); // Newton's second law
acc.add(force); // Accumulate acceleration
}
It should be noted that the inclusion of mass as a property for our body is to demonstrate Newton’s Laws with some small amount of accuracy. However, for the purposes of creating an interesting visual simulation, it is not entirely necessary (especially in the case of an example only having one object) and we could simplify our code (as we might in later examples) by excluding mass and making Acceleration = Force.
The above example assumes we have already figured out how to calculate forces (like wind, friction, gravity, etc.) Here are some examples of forces we will examine:
“Dissipative” Force
A dissipative force is one where the total energy of a system decreases when an object is in motion. For example, an object traveling through a liquid (viscosity) or sliding along a surface (friction). A true model of friction would include separate cases for static friction (for a body at rest against a surface) and kinetic friction (for a body in motion against a surface), but we will consider just one case. Friction is calculated independently of an object’s speed in the opposite direction of the object’s motion, i.e.:
Friction Force = -c * (velocity unit vector)
where c is the “coefficient of friction”
Drag through a liquid, however, though similar to friction, is directly related to the speed of an object. The faster an object moves, the more drag force is applied to it, i.e.:
Viscous Force = -c * (velocity vector)
Assume an object “t” of type Thing from our example above. If it were traveling through a liquid with a coefficient of friction of -0.02, our code to calculate and apply the force would be:
float c = -0.03; // Drag coefficient PVector thingVel = t.getVel(); // Velocity of our thing PVector force = PVector.mult(thingVel,c); // Following the formula above t.applyForce(force); // Adding the force to our object, which will ultimately affect its acceleration
Gravitational Force
The gravitational pull of the earth can be treated as a special case because the distance d is approximately a constant (i.e. the radius of the earth) and for any given location, we can approximate the earth’s surface as flat (the direction of gravity is therefore the normal to the earth’s plane.)
(G * M) / (D * D) is therefore approximately a constant –> 9.8 meters / seconds squared, the acceleration due to gravity on earth.
Two bodies will attract each other with a force of equal magnitude (but in opposite direction — i.e. Newton’s Third Law). To calculate the force, we need:
Gravitational Force Magnitude = (G * M1 * M2) / (D * D)
To calculate the direction of the force, we can simply examine the unit vector difference between the two points, i.e.
Gravitational Force Direction (for Object #1) = (L2 – L1) / ||L2 – L1||
In order to create code for gravitational force, we can add another function to our Thing class, which takes another Thing object as its parameter and calculates its own gravitational pull towards that object, i.e.
PVector calcGravForce(Thing t) {
PVector dir = PVector.sub(loc,t.getLoc()); // Calculate direction of force
float d = dir.mag(); // Distance between objects
dir.normalize(); // Normalize vector (distance doesn't matter, we just want direction)
float force = (G * mass * t.getMass()) / (d * d); // Calculate gravitional force magnitude
dir.mult(force); // Get force vector --> magnitude * direction
return dir;
}
Now, in our main program, assume we have an array of Things:
final int MAX = 5; Thing[] t = new Thing[MAX];
Our next step is to do the following inside the main loop:
void draw() {
for (int i = 0; i < t.length; i++) { // For every Thing t[i]
for (int j = 0; j < t.length; j++) { // For every Thing t[j]
if (i != j) { // Make sure we are not calculating gravtional pull on oneself
PVector f = t[i].calcGravForce(t[j]); // Use the function we wrote above
t[i].applyForce(f); // Add the force to the object to affect its acceleration
}
}
t[i].go(); // Implement the rest of the object's functionality
}
}
The Real World vs. Our Digital World
It is important to note here that “ideal world scenarios” often have serious problems when working with a visual computer simulation. Take the following example where we have two objects:
Thing T1: LOC = (10.2,10.0), MASS = 5
Thing T2: LOC = (10.3,9.9), MASS = 5
G = 1.0
DIST = SQRT((10.2-10.3)*(10.2-10.3)+(10.0-9.9)*(10.0-9.9)) = SQRT(0.01 + 0.01) = ~0.14
GRAVFORCEMAG = (1.0 * 5 * 5) / (0.14 * 0.14) = 1250.0
This force of 1250 “units” is going to be much too large when thinking about moving an object a certain number of pixels along the screen. To create nice smooth-looking visualizations, therefore, we often need to develop clever ways of limiting factors within the system (having a maximum velocity, a minimum distance, etc.). In the examples below, you’ll see some strategies implemented for “faking it”. This issue is one that you will need to consider as you develop your own projects.
Examine this version of the gravitational force calculation function:
PVector calcGravForce(Thing t) {
PVector dir = PVector.sub(loc,t.getLoc()); // Calculate direction of force
float d = dir.mag(); // Distance between objects
d = constrain(d,5.0,25.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
dir.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
float force = (G * mass * t.getMass()) / (d * d); // Calculate gravitional force magnitude
dir.mult(force); // Get force vector --> magnitude * direction
return dir;
}




Think there is a small type error in this code:
Thing(Vector3D a, Vector3D, v, Vector3D l, float m_) {
should this not be:
Thing(Vector3D a, Vector3D v, Vector3D l, float m_) {
thanks and I am learning a lot from here.
Oops, thanks for catching the error!
hi, there is a minor calculation error in the description:
ACCELERATION CAUSED BY GRAV = GRAV / MASS = (0,10) / 5 = (0,2)
should be
ACCELERATION CAUSED BY GRAV = GRAV / MASS = (0,10) / 5 = (0,02)
thanks for making those great learning resources available for everyone!