Felipe Almeida | OAPT Conference | May 5, 2023
The advantages of representing physical phenomena in various ways (e.g. motion diagrams, text descriptions, interaction diagrams, energy bar charts, etc) are well established. Should representations using code be included too? Do the benefits justify the efforts? This session will demonstrate how creating code to represent simple and complex physical phenomena (e.g. linear motion, Thorโs Hammer) may be advantageous to the physics learner. No previous coding experience assumed.
A sample scenario:
Some useful representations:
What (trimmed) computer code and accompanying simulation could look like as another representation:
let mass = 10, boxSize = 10;
let posX = 240, vel = -25;
let netForce = 6.8;
let acc = netForce/mass;
โฎ
posX += vel;
vel += acc;
if (vel >= 0)
noLoop();
p5.js is a free and open source javascript library supported by the procesing foundation that is designed to make creative coding more accessible to artists, educators, beginners (and anyone else). Their convenient online editor can be found here . When using p5.js, a computer program is referred to as a 'sketch' whose visual components appear on a 'canvas'.
What follows is a short tutorial for creating and understanding a sketch that 'moves an object horizontally'.
createCanvas(300, 200);background(220);circle(mouseX, mouseY, 30);createCanvas(300, 200);background(220);circle(mouseX, mouseY, 30);let posX = -50;createCanvas(600, 200);background(220);translate(width/2, height/2);square(posX, 0, 10);posX += 1;1; in posX += 1; to several other values (and press 'play'), and observe what happens (*try negative values too!)let posX = -200;let vel = 0;createCanvas(600, 200);background(220);translate(width/2, height/2);square(posX, 0, 10);posX += vel; 1vel += 0.01;0.01; in vel += 1; to several other values, and observe what happens (*try negative values too!)vel += -0.09;:if (posX >= 120)
noLoop();Highlight: Net force (and acceleration) changes every frame just like position and velocity (but proportional to spring displacement x).
function draw() {
โฎ
//motion
posX += vel;
//if touching spring, apply spring force
if(posX < springStartX){
x = springStartX - posX;
springForce = k*x;
acc = springForce/mass;
vel += acc;
}
}
Highlight: An if statement to determine if two objects collide, then an implementation of the law of conservation of momentum.
function draw() {
โฎ
//checking for collision, executing collision
if (abs(m1.posX - m2.posX) < (m1.size/2 + m2.size/2)) {
vf = (m1.mass*m1.vel + m2.mass*m2.vel) / (m1.mass + m2.mass);
m1.vel = vf;
m2.vel = vf;
}
}
Highlight: A changing net force (proportional to the pendulum's angle from vertical, θ) and a collision check and implementation of the law of conservation of momentum.
function draw() {
โฎ
hammer.force = -hammer.mass*g*sin(hammer.theta - PI/2)/hammer.l;
hammer.acc = hammer.force/hammer.mass;
hammer.vel += hammer.acc;
โฎ
//checking for collision, executing collision
if (abs(cart.posX - hammer.posX) < (cart.size/2 + hammer.r) && !collided) {
vf = (cart.mass*cart.vel + hammer.mass*hammer.vel*hammer.l) / (cart.mass + hammer.mass);
cart.vel = -vf;
hammer.vel = vf/hammer.l;
collided = true;
}
hammer.theta += hammer.vel;
}
Quantitative (rather than qualitative) representations are also possible using deltaTime: the amount of time passed since the previous frame (in milliseconds).
Highlights:
let t = 0;
let m = 0.25 //mass, in kilograms
let w = 0.1; //box width, in metres
let d1 = 1.5; //initial position, in metres
let v1 = -4.5; //initial velocity, in m/s
let Fnet = 0.9; //net force, in Newtons
let a = Fnet/m; //acceleration, in m/sยฒ
โฎ
function draw() {
โฎ
t += deltaTime/1000;
d2 = d1 + v1*t + 0.5*a*t**2;
v2 = v1 + a*t;
โฎ
function drawBox() {
โฎ
square(d2*pixelsPerMetre, -w/2*pixelsPerMetre, w*pixelsPerMetre);
}
| Reference | Example | Example Description |
|---|---|---|
| createCanvas(x,y) | createCanvas(400, 250) |
Creates a canvas thatโs 400 pixels wide and 250 pixels tall. |
| background(color) | background('green') |
Colours the entire canvas green. (n.b. Colors can be defined a number of different ways.) |
| translate(x, y) | translate(100, 200) |
Moves the origin to 100 pixels from the left of the canvas and 200 pixels from the top of the canvas. |
| square(x, y, diameter) | rectMode(CENTER)square(10,20,30) |
Draws a square with a 30 pixel diameter 10 pixels to the right of the origin and 20 pixels below the origin ( rectMode(CENTER) draws the square from its center, rather then the default top-left corner). more shapes |
| let | let animalType = "fox"; |
Creates a variable called animalType (and assigns a value of "fox" to it). |
| += (add assign) | |
Adds 2 to the existing value of x (i.e. equivalent to x = x + 1;). |
| if statement | |
If the variable t is greater than 10, the canvas will be painted green. |
1 Technically, what is happening here is posX += vel*nFrames, where vel units are pixels/frame and nFrames = 1. So that the tutorial can be done on day 1 (and assuming neither a physics nor programming background), these details are omitted, as the purpose here is to develop a feeling for velocity and get an object moving on-screen as quickly as possible. This line can be revisited later to establish its adherence to the motion equations and how the units work out. (Thank you to whoever brought attention to this during the presentation!) back ↑