Monday, March 29, 2010

Matteo's Visual Python Project

Ball Bouncing Down Ramp

Video: http://www.youtube.com/watch?v=O54XjZGRnxU

Description: This program simulates a ball bouncing down an angled ramp. Each time the ball bounces it obeys the law of reflection. Included within the program are two graphs which display the ball's total, potential, and kinetic energy. It is easy to see from the graphs that energy is conserved and when potential energy decreases, kinetic energy increases. This simulation ignores friction and air resistance.

Code:
from __future__ import division
from visual import*
from visual.graph import*

ramp = box(pos=(0,6.8,0), axis=(-2,1,0), length=30, width=7, height=.1)
stand1 = cylinder(pos=(-10.5,.3,2.5), length=11.5, axis=(0,1,0), radius=.6)
stand2 = cylinder(pos=(-10.5,.3,-2.5), length=11.5, axis=(0,1,0), radius=.6)
stand3 = cylinder(pos=(-10.5,.3,0), length=11.5, axis=(0,1,0), radius=.6)
floor = box(pos=(10,.1,0), length=50, width=20, height=.2, color=color.green)
ball = sphere(pos=(-12.5,19.8,0), radius=.4, color=color.red)
ball.velocity=vector(0,0,0) #ball's initial velocity
ball.trail=curve(color=ball.color)
m = 1 #ball's mass
g = 9.8 #gravitational acceleration
time = 0 #time
dt = .01 #time step
U = m*g*(ball.pos.y - ball.radius) #gravitational potential energy measured from floor.pos.y = zero potential
E = U #total energy equals U since the initial velocity is zero
K = E-U #kinetic energy equals the total energy minus potential energy
graph1 = gdisplay(x=675, y=0, width=600, height=400, title='Potential Energy vs. Time',
xtitle='time (s)', ytitle='Total Energy and Potential Energy (J)', xmax=18, xmin=0,
ymax=1.2*U, ymin=0, foreground=color.black, background=color.white)
Ucurve = gcurve(gdisplay = graph1, color=color.black)
Ecurve = gcurve(gdisplay = graph1, color=color.black)
#total energy and gravitational potential energy graph
graph2 = gdisplay(x=675, y=400, width=600, height=400, title='Kinetic Energy vs. Time',
xtitle='time (s)', ytitle='Kinetic Energy (J)', xmax=18, xmin=0,
ymax=1.2*U, ymin=0, foreground=color.black, background=color.white)
Kcurve = gcurve(gdisplay = graph2, color=color.black)
#kinetic energy graph
while true:
rate(50)
time += dt
F_net=vector(0,-m*g,0) #force of gravity
a=F_net/m #Newton's 2nd law
U = m*g*(ball.pos.y - ball.radius)
K = E-U
ball.trail.append(pos=(ball.x,ball.y,ball.z)) #ball's tail
ball.velocity.y = ball.velocity.y - g*dt #turns gravity on
if ball.pos.y <= ramp.pos.y + (-1/2)*ball.pos.x + ramp.height*sin(atan(1/2))+.2:
ball.velocity.y = mag(ball.velocity)*sin(atan(1/2))
ball.velocity.x = mag(ball.velocity)*cos(atan(1/2))
#when the ball hits the ramp it bounces off at the angle obeying the law of reflection
if ball.pos.y <= floor.pos.y + ball.radius:
ball.velocity.y = -ball.velocity.y
ball.velocity.x = ball.velocity.x
#this ensures the ball won't go through the floor
if ball.pos.x >= floor.pos.x + .5*floor.length:
ball.pos.x = -12.5
ball.pos.y = 19.8
ball.pos.z = 0
ball.velocity.x = 0
ball.velocity.y = 0
ball.velocity.z = 0
ball.trail.append(pos=(ball.x,ball.y,ball.z), retain=0)
#once the ball reaches the floor the simulation resets
ball.pos=ball.pos + ball.velocity*dt
if time<= 17:
Ucurve.plot(pos = (time, U))
Kcurve.plot(pos = (time, K))
Ecurve.plot(pos = (time, E))
#instructions for graphing two cycles

Inelastic Collision

Video: http://www.youtube.com/watch?v=SzpEBTUAImk

Description: This simulation recreates inelastic collisions between two carts. Users can change the mass and velocities of either carts in the beginning lines of code; each carts size is directly proportional to its mass. This simulation also displays a graph showing the momentum and kinetic energy of the entire system. The momentum graph is a horizontal line showing that momentum is conserved. The kinetic energy graph is not constant, showing that energy is lost through sound and other forms of energy in the collision.

Code:
from __future__ import division
from visual import*
from visual.graph import*

m_1 = 2 #red cart's mass
v_1 = 20 #red cart's velocity
m_2 = 4 #blue cart's mass
v_2 = -5 #blue cart's velocity
floor = box(pos=(0,0,0), length=60, width=6, height=.9, color=color.green)
cart1 = box(pos=(-24,1.4+(.5)*(.3)*(m_1),0), length=5, width=3, height=(.3)*(m_1), color=color.red)
ball1 = sphere(pos=(-25.75,.95,-.7), radius = .7, color=color.black)
ball2 = sphere(pos=(-25.75,.95,.7), radius = .7, color=ball1.color)
ball3 = sphere(pos=(-22.25,.95,-.7), radius = .7, color=ball1.color)
ball4 = sphere(pos=(-22.25,.95,.7), radius = .7, color=ball1.color)
cart2 = box(pos=(24,1.4+(.5)*(.3)*(m_2),0), length=5, width=3, height=(.3)*(m_2), color=color.blue)
ball5 = sphere(pos=(25.75,.95,-.7), radius = .7, color=ball1.color)
ball6 = sphere(pos=(25.75,.95,.7), radius = .7, color=ball1.color)
ball7 = sphere(pos=(22.25,.95,-.7), radius = .7, color=ball1.color)
ball8 = sphere(pos=(22.25,.95,.7), radius = .7, color=ball1.color)
wall1 = box(pos=(29.5,2.5,0), length=1, width=6, height=5, color=color.green)
wall2 = box(pos=(-29.5,2.5,0), length=1, width=6, height=5, color=color.green)
cart1.velocity = vector(v_1,0,0)
ball1.velocity = vector(cart1.velocity.x,0,0)
ball2.velocity = vector(cart1.velocity.x,0,0)
ball3.velocity = vector(cart1.velocity.x,0,0)
ball4.velocity = vector(cart1.velocity.x,0,0)
cart2.velocity = vector(v_2,0,0)
ball5.velocity = vector(cart2.velocity.x,0,0)
ball6.velocity = vector(cart2.velocity.x,0,0)
ball7.velocity = vector(cart2.velocity.x,0,0)
ball8.velocity = vector(cart2.velocity.x,0,0) #ensures wheels stay attached to carts
time =0 #time
dt = .001 #time step
p = ((m_2)*(cart2.velocity.x)+(cart1.velocity.x)*(m_1)) #total momentum
k = .5*(m_1)*(pow(ball1.velocity.x,2) + pow(ball1.velocity.y,2) + .5*(m_2)*(pow(ball2.velocity.x,2) + pow(ball2.velocity.y,2)))
#kinetic energy
graph1 = gdisplay(x=650, y=0, width=600, height=400, title='Momentum vs. Time',
xtitle='time (s)', ytitle='Momentum (kg*m/s)', xmax=20, xmin=0,
ymax=1.2*p, ymin=-1.2*p, foreground=color.black, background=color.white)
pcurve = gcurve(gdisplay = graph1, color=color.black)
#momentum graph
graph2 = gdisplay(x=650, y=400, width=600, height=400, title='Kinetic Energy vs. Time',
xtitle='time (s)', ytitle='Kinetic Energy (J)', xmax=20, xmin=0,
ymax=1.2*k, ymin=0, foreground=color.black, background=color.white)
kcurve = gcurve(gdisplay = graph2, color=color.black)
#kinetic energy graph
while true:
rate(1000)
time += dt
cart1.pos = cart1.pos + cart1.velocity*dt
cart2.pos = cart2.pos + cart2.velocity*dt
ball1.pos = ball1.pos + ball1.velocity*dt
ball2.pos = ball2.pos + ball2.velocity*dt
ball3.pos = ball3.pos + ball3.velocity*dt
ball4.pos = ball4.pos + ball4.velocity*dt
ball5.pos = ball5.pos + ball5.velocity*dt
ball6.pos = ball6.pos + ball6.velocity*dt
ball7.pos = ball7.pos + ball7.velocity*dt
ball8.pos = ball8.pos + ball8.velocity*dt
if cart1.pos.x >= cart2.pos.x - (.5)*cart2.length - (.5)*cart1.length:
cart1.velocity.x = ((m_2)*(cart2.velocity.x)+(cart1.velocity.x)*(m_1))/((m_1)+(m_2))
ball1.velocity.x = cart1.velocity.x
ball2.velocity.x = cart1.velocity.x
ball3.velocity.x = cart1.velocity.x
ball4.velocity.x = cart1.velocity.x
cart2.velocity.x = cart1.velocity.x
ball5.velocity.x = cart1.velocity.x
ball6.velocity.x = cart1.velocity.x
ball7.velocity.x = cart1.velocity.x
ball8.velocity.x = cart1.velocity.x
#after the two carts collide, they each have the same velocity and momentum is conserved (but not kinetic energy)
if cart2.pos.x >= wall1.pos.x - (.5)*cart2.length - (.5)*wall2.length:
cart1.velocity = -cart1.velocity
ball2.velocity = -ball2.velocity
ball3.velocity = -ball3.velocity
ball4.velocity = -ball4.velocity
cart2.velocity = -cart2.velocity
ball5.velocity = -ball5.velocity
ball6.velocity = -ball6.velocity
ball7.velocity = -ball7.velocity
ball8.velocity = -ball8.velocity
#this ensures the carts rebound off the right wall
if cart1.pos.x <= wall2.pos.x + (.5)*cart1.length + (.5)*wall1.length:
cart1.velocity = -cart1.velocity
ball2.velocity = -ball2.velocity
ball3.velocity = -ball3.velocity
ball4.velocity = -ball4.velocity
cart2.velocity = -cart2.velocity
ball5.velocity = -ball5.velocity
ball6.velocity = -ball6.velocity
ball7.velocity = -ball7.velocity
ball8.velocity = -ball8.velocity
#this ensures the carts rebound off the left wall
p = ((m_2)*(cart2.velocity.x)+(cart1.velocity.x)*(m_1))
k = .5*(m_1)*(pow(ball1.velocity.x,2) + pow(ball1.velocity.y,2) + .5*(m_2)*(pow(ball2.velocity.x,2) + pow(ball2.velocity.y,2)))
if time<= 20:
pcurve.plot(pos = (time,p))
kcurve.plot(pos = (time,k))

Race

Video: http://www.youtube.com/watch?v=UPs82IDOwn0

Description: This simulation shows a race of objects with different shapes and therefore rotational inertia. The shapes are from closest to farthest, a hollow sphere, a solid cylinder, a disk, a solid sphere, and a ring. All objects have the same mass and radius, who are you going to put your money on? (All objects roll without slipping in this simulation)

Code:
from __future__ import division
from visual import*

m_1 = 1 #mass of hollow sphere
r_1 = 1 #radius of hollow sphere
m_2 = 1 #mass of cylinder
r_2 = 1 #radius of cylinder
m_3 = 1 #mass of solid sphere
r_3 = 1 #radius of solid sphere
m_4 = 1 #mass of disk
r_4 = 1 #radius of disk
m_5 = 1 #mass of ring
r_5 = 1 #radius of ring
g = 9.8 #gravitational acceleration
u = .2 #coefficient of static friction
dt = .001 #time step
ramp = box(pos=(0,0,0), axis=(-2,1,0), length=70, width=32, height=.1)
stand1 = cylinder(pos=(-23,-15.7,8), length=26, axis=(0,1,0), radius=2)
stand2 = cylinder(pos=(-23,-15.7,-8), length=26, axis=(0,1,0), radius=2)
stand3 = cylinder(pos=(-23,-15.7,0), length=26, axis=(0,1,0), radius=2)
floor = box(pos=(0,-15.7,0), length=90, width=32, height=.2)
wall = box(pos=(45,-8.2,0), length=.2, width=32, height=15)
ball1 = sphere(pos=(-29,15.7,13), radius=(r_1), color=color.orange)
ball2 = sphere(pos=(ball1.pos.x,ball1.pos.y,-8), radius=(r_3), color=color.cyan)
cylinder1 = cylinder(pos=(ball1.pos.x,ball1.pos.y,1), axis=(0,0,5), radius=(r_2), color=color.green)
cylinder2 = cylinder(pos=(ball1.pos.x,ball1.pos.y,-3), axis=(0,0,.1), radius=(r_4), color=color.red)
ring = ring(pos=(ball1.pos.x, ball1.pos.y,-13), axis=(0,0,.1), radius=(r_5), color=color.blue)
ball1.velocity = vector(0,0,0)
ball2.velocity = vector(0,0,0)
cylinder1.velocity = vector(0,0,0)
cylinder2.velocity = vector(0,0,0)
ring.velocity = vector(0,0,0) #all racers start at the same height with the same velocity

while true:
rate(500)
if ball1.pos.y >= floor.pos.y + r_1 + .4:
ball1.velocity.x = ball1.velocity.x + ((r_1)*((u*(m_1)*g*(r_1))/(2/3*(m_1)*(r_1)*(r_1))))*cos(atan(-1/2))*dt
ball1.velocity.y = ball1.velocity.y + ((r_1)*((u*(m_1)*g*(r_1))/(2/3*(m_1)*(r_1)*(r_1))))*sin(atan(-1/2))*dt
#the object's acceleration is equal to its radius times its angular acceleration which equals torque over rotational interia
#the torque is equal to friction times radius (condition of rolling without slipping)
if ball1.pos.y <= floor.pos.y + r_1 + .4:
ball1.velocity.x = pow((pow(ball1.velocity.x,2) + pow(ball1.velocity.y,2)),.5)
ball1.velocity.y = 0
#when the object reaches the floor, the y velocity is zero, but kinetic energy is still conserved
if ball1.pos.x >= wall.pos.x - r_1 - .4:
ball1.velocity.x = 0
ball1.velocity.y = 0
#when the object hits the wall it comes to rest
if ball2.pos.y >= floor.pos.y + r_3 + .4:
ball2.velocity.x = ball2.velocity.x + ((r_3)*((u*(m_3)*g*(r_3))/(2/5*(m_3)*(r_3)*(r_3))))*cos(atan(-1/2))*dt
ball2.velocity.y = ball2.velocity.y + ((r_3)*((u*(m_3)*g*(r_3))/(2/5*(m_3)*(r_3)*(r_3))))*sin(atan(-1/2))*dt
if ball2.pos.y <= floor.pos.y + r_3 + .4:
ball2.velocity.x = pow((pow(ball2.velocity.x,2) + pow(ball2.velocity.y,2)),.5)
ball2.velocity.y = 0
if ball2.pos.x >= wall.pos.x - r_3 - .4:
ball2.velocity.x = 0
ball2.velocity.y = 0
if cylinder1.pos.y >= floor.pos.y + r_2 + .4:
cylinder1.velocity.x = cylinder1.velocity.x + ((r_2)*((u*(m_2)*g*(r_2))/(1/2*(m_2)*(r_2)*(r_2))))*cos(atan(-1/2))*dt
cylinder1.velocity.y = cylinder1.velocity.y + ((r_2)*((u*(m_2)*g*(r_2))/(1/2*(m_2)*(r_2)*(r_2))))*sin(atan(-1/2))*dt
if cylinder1.pos.y <= floor.pos.y + r_2 + .4:
cylinder1.velocity.x = pow((pow(cylinder1.velocity.x,2) + pow(cylinder1.velocity.y,2)),.5)
cylinder1.velocity.y = 0
if cylinder1.pos.x >= wall.pos.x - r_2 - .4:
cylinder1.velocity.x = 0
cylinder1.velocity.y = 0
if cylinder2.pos.y >= floor.pos.y + r_4 + .4:
cylinder2.velocity.x = cylinder2.velocity.x + ((r_4)*((u*(m_4)*g*(r_4))/(1/2*(m_4)*(r_4)*(r_4))))*cos(atan(-1/2))*dt
cylinder2.velocity.y = cylinder2.velocity.y + ((r_4)*((u*(m_4)*g*(r_4))/(1/2*(m_4)*(r_4)*(r_4))))*sin(atan(-1/2))*dt
if cylinder2.pos.y <= floor.pos.y + r_4 + .4:
cylinder2.velocity.x = pow((pow(cylinder2.velocity.x,2) + pow(cylinder2.velocity.y,2)),.5)
cylinder2.velocity.y = 0
if cylinder2.pos.x >= wall.pos.x - r_4 - .4:
cylinder2.velocity.x = 0
cylinder2.velocity.y = 0
if ring.pos.y >= floor.pos.y + r_5 + .4:
ring.velocity.x = ring.velocity.x + ((r_5)*((u*(m_5)*g*(r_5))/((m_5)*(r_5)*(r_5))))*cos(atan(-1/2))*dt
ring.velocity.y = ring.velocity.y + ((r_5)*((u*(m_5)*g*(r_5))/((m_5)*(r_5)*(r_5))))*sin(atan(-1/2))*dt
if ring.pos.y <= floor.pos.y + r_5 + .4:
ring.velocity.x = pow((pow(ring.velocity.x,2) + pow(ring.velocity.y,2)),.5)
ring.velocity.y = 0
if ring.pos.x >= wall.pos.x - r_5 - .4:
ring.velocity.x = 0
ring.velocity.y = 0
ball1.pos.x = ball1.pos.x + ball1.velocity.x*dt
ball1.pos.y = ball1.pos.y + ball1.velocity.y*dt
ball2.pos.x = ball2.pos.x + ball2.velocity.x*dt
ball2.pos.y = ball2.pos.y + ball2.velocity.y*dt
cylinder1.pos.x = cylinder1.pos.x + cylinder1.velocity.x*dt
cylinder1.pos.y = cylinder1.pos.y + cylinder1.velocity.y*dt
cylinder2.pos.x = cylinder2.pos.x + cylinder2.velocity.x*dt
cylinder2.pos.y = cylinder2.pos.y + cylinder2.velocity.y*dt
ring.pos.x = ring.pos.x + ring.velocity.x*dt
ring.pos.y = ring.pos.y + ring.velocity.y*dt