In this lab we will simulate the behavior of a simple pendulum (i.e. with no forces other than gravity and the pendulum arm's tension acting on it). The differential equation describing the motion of a pendulum shown below can be easily derived from Newton's Laws, but has no closed form solution. Therefore a simplifying assumption is often made that the displacement angle of the pendulum (how wide it swings up from vertical) is very small which allows a reasonable approximation to be made by simplifying the equation. With this simplifying assumption the equation becomes that of a simple harmonic oscillator and is easily solvable with a cosine function as the solution.
d2θ/dt2 -(g/L)sin(θ) = 0
Where g is acceleration due to gravity, L is the length of the pendulum's arm and θ is the angular displacement from vertical.
But real pendulums have much more interesting behavior. With a computer program it becomes possible to explore this behavior by numerically solving the of the equation with Euler's method and simulating the result.
A pendulum can be started by displacing it and either dropping it or giving it a push to make it go higher. If it is pushed hard enough, it can actually loop around in a complete circle. If it has a stiff rod for an arm, and if it is pushed pushed just the right amount, it could theoretically be made to balance exactly straight over its pivot point. Our ultimate goal in this lab is to find within 3 decimal places what starting velocity we need to release our simulated pendulum to get it to balance on top. Chances are you will not be able to find an exact value for that critical velocity, but you can find two numbers, one a little too fast and one a little to slow, that only differ in the fourth decimal place.
You only need to turn in a listing of your final program or as much as you were able to get working. Please turn something in even if you got stuck so we can help you get unstuck. The more you can write about what you were having trouble with or what lame Python error message you couldn't get past the better
This version starts out with a binary search to find the closest possible approximation to the critical initial ω to balance the pendulum at the top. Once it has computed this, it runs a simulation showing the pendulum and a graph of θ versus time. The simulation runs long enough to see that the approximation still is not exact and the pendulum eventually goes over the top. Not that because of this sensitivity, chosing different dt will result in slightly different answers for the critical ω.
from visual.graph import *
graphics=False # turn graphing code on or off
armlength=2
g = 9.8 # acceleration due to gravity
t=0
#draw the pendulum graphics
def make_pendulum():
global pendulum
top=vector(0,20,0)
basesize=vector(.2,.1,.2)
base = box(size=basesize, pos=top+vector(0,basesize.y/2.0,0))
pendulum = frame(pos=top,axis=(0,-1,0))
arm = cylinder(frame=pendulum, length=armlength, radius=0.01)
bob = sphere(frame=pendulum, pos=(armlength,0,0), color=color.red, radius=.1)
scene.center = (0,top.y-armlength/2.0,0)
scene.range = armlength
#this function causes the graphics windows to appear
def enable_graphics():
global graphics, thetagraph, frame_rate
graphics=True
thetagraph=gdisplay(title="Theta")
make_pendulum()
frame_rate=24
#theta is angle relative to straight down
def setPendulumAngle(pendulum,theta):
x=armlength*sin(theta)
y=-armlength*cos(theta)
pendulum.axis=(x,y,0)
#Run a complete simulation and return the final theta
def simulate(theta,w,time_limit=4,dt=1.0/128):
t=0
theta_max=0 # maximum value of theta reached so far
if graphics: thetacurve=gcurve(gdisplay=thetagraph)
while t<=time_limit:
#Euler's method
a = (-g/armlength)*sin(theta)
w += a*dt
theta += w*dt
t += dt
if theta>theta_max: theta_max=theta
if graphics:
if t % (1.0/frame_rate) < dt:
setPendulumAngle(pendulum,theta)
thetacurve.plot(pos=(t,theta))
rate(frame_rate)
return theta_max
dt=1.0/256
upper=5
lower = w_estimate = 3 # starting guess
count=0
last_estimate=0
while last_estimate != w_estimate:
last_estimate = w_estimate
theta_max = simulate(0,w_estimate,time_limit=30,dt=dt)
#do a binary search looking to see if pendulum went over the top
# or swung back
if theta_max > 2*pi:
upper = w_estimate
print "Overshot"
else:
lower = w_estimate
print "Undershot"
w_estimate = (upper+lower)/2.0
count += 1
print "trial:",count,"estimated w:", w_estimate
enable_graphics()
simulate(0,w_estimate,time_limit=30,dt=dt)
import sys
sys.exit(0)