Week 3 Computer Lab

Modeling Motion
Due: January 27

In this lab we will try to establish the relationship between the angle an object is thrown and the distance it will travel under the influence of gravity before hitting the ground. Assume the object is always thrown with the same speed but a varying angle with respect to the ground. This is a 2-dimensional problem so we'll need to get our programs to work in the 2D case. Looking only at the vertical direction will establish how long it will take for the object to reach the ground. Using that value for time, we can use an expression for the distance traveled along the ground in that time since we know there is no acceleration in the x direction. We can view the displacement in the x direction as simple uniform motion (acceleration in x direction=0).

Each step in the lab asks you to add new capability to the same program. Turn in your final program and a table of values computed as described in the final step. If you are unable to get the program working properly, turn in what you have so far on the due date so we can figure out where you need help.

  1. Lets start with the solution to one of last week's problems--the program which uses the analytical solution to the uniform acceleration problem to plot displacement over a period of time.

    from visual.graph import *
    
    x0 =  0   # starting position
    v0 =  5   # v is velocity in m/s
    a  = -1   # a is the acceleration in m/s/s
    t  =  0   # starting time in seconds
    dt =  1   # delta t, the change in time
    
    def displacement(t):
        return x0 + v0*t + a*t*t/2.0
    
    graph = gdisplay()
    curve = gcurve()
    
    # For a slightly fancier graph replace the above lines with these:
    #graph = gdisplay(title="Uniform Acceleration", xtitle="displacement", ytitle="time")
    #curve = gcurve(color=(1,1,0))
    
    while t<=20 :
          x = displacement(t)
          print t,x
          curve.plot(pos=(t,x))
          t = t+dt
    
    

    First modify this program so the loop will continue for as much time as necessary until the particle reaches the ground (displacement=0). To make things a bit clearer, change x to y since we are initially interested in the displacement in the y direction. Lets use a smaller Δt for better accuracy. Choosing .125 (which is 1/8) will prevent the strange round off errors in our time variable since 1/8 can be represented exactly in binary as .0012. Still we will only be able to estimate the time our particle hit the ground to the nearest 1/8th of a second.

      Question
    1. According to this simulation What time (to the nearest 1/8th seconds) does a particle with the given initial position, velocity and acceleration hit the ground if the particle is launched at t=0?
    2. What should the exact time be? (compute this analytically on paper)
  2. Now we need to make the program work for 2-dimensional problems. Well represent 2D vectors like 2i+3j as 2-element lists like this: [2,3]. So initial position, x0, should become an initial position vector: p0 = [0,0]. Similarly, the initial velocity and the constant acceleration due to gravity become vector quantities. Now the displacement() function should return a vector as well. See this vector normalize function as an example of a function which takes a vector as an argument and returns a vector. Verify that the program still computes the same result after the new changes.

  3. To see the relationship between angle and distance traveled, we need to be able to specify the initial velocity of our particle in terms of speed and angle with respect to horizontal (of a ball leaving the hand, a cannonball leaving the barrel, etc.) Since we are trying to find the relationship between the distance traveled and the angle the particle leaves the ground, we want to keep speed constant and sweep the angle through a number of evenly spaced values. We need another function called polar2rect() that will use trigonometry to take speed and an angle as inputs and return a vector. Try giving a particle an initial speed of 50m/s thrown at an angle of 45° up from horizontal and with gravity set to standard 9.8m/s2 downwards. If your code is working right, it should print out a distance of 256.33m in 7.25 seconds.

  4. Add code to graph the trajectory of the particle in a gdisplay window. Don't plot displacement versus time, plot the position vector x versus y.

  5. Now put a for loop around the simulation to rerun the experiment for a range of initial angles from 0 to 180 degrees in 5 degree steps. Plot each new trajectory with a new gcurve() on the graph and print out a table of values showing the final displacement and the time aloft.

  6. Finally, make a second plot window which shows a graph with the angle the object was thrown on the x axis and the distance attained on the y axis. What is the shape of the graph? Do you recognize the function?

Solution

This solution color codes each trajectory curve so that the corresponding segment in the angle vs. displacement curve is the same color. The math library's radian() function was used to convert angles from degrees to radians.

from visual.graph import *

speed=50      # initial speed
p0 = [0,0]    # initial position
a  = [0,-9.8] # acceleration due to gravity

dt=.125       # time increment


def displacement(t,x0=[0,0],v0=[0,0],a=[0,0]):
    'compute 2D vector displacement of a particle undergoing uniform acceleration'
    x = x0[0] + v0[0]*t + 0.5*a[0]*t*t
    y = x0[1] + v0[1]*t + 0.5*a[1]*t*t
    return [x,y]


def polar2rect(r,theta):
    'convert a polar vector to rectangular representation'
    return [r*cos(theta), r*sin(theta)]

#graph of the path particles with different initial angles
pathgraph = gdisplay(title="Trajectory",xmin=-260,xmax=260,ymax=130)

#graph of the angle versus distance final displacement
distgraph = gdisplay(title="Angle vs Distance",xtitle="theta",ytitle="distance",
                     xmax=180,ymin=-260,ymax=260)

distcurve = gcurve(gdisplay=distgraph)

print "angle (degrees) | disp (m) | time (s)" #print heading of table of data

for angle in range(0,185,5):
    theta = radians(angle) # compute angle in radians, call it theta

    #plot curves with gratuitous colors to impress management
    red   = max(0,cos(theta))
    green = sin(theta)
    blue  = max(0,cos(pi+theta))
    curve = gcurve(gdisplay=pathgraph, color=(red,green,blue))

    # reset variables to initial values
    p  = p0
    v0 = polar2rect(speed,theta)
    t  = 0
    curve.plot(pos=p) # plot starting position

    # run simulation for one angle
    while p[1]>=0:
        t+=dt
        p=displacement(t,p0,v0,a)
        curve.plot(pos=p)

    # plot final final position versus angle and print it
    distcurve.plot(pos=(angle,p[0]),color=(red,green,blue))
    print "   %3d          | %8.2f | %7.3f" % (angle,p[0],t)