Loading [MathJax]/extensions/MathZoom.js

Friday, 18 July 2014

Physics with Python

Today I am going to built a class in Python to simulate a famous kind of motion: projectile motion!

I said a "Class" because while trying to find something to build a class on, I noticed that a projectile could fit perfectly. In fact, a projectile, or any other object which when launched, moves along a curved path under the action of gravity only, has some characteristics: speed, mass, etc...
Displaying all these characteristics through a class can be at the same time both fun and useful for practicing with classes.

The basic assumptions of this kind of motion are the following:
- There is no air friction
- The only significant force which acts on the projectile is gravity

Additional assumptions:
- Projectile starts at y = 0 (from ground)


If you'd like to gather more information on this kind of motion, check out wikipedia:
http://en.wikipedia.org/wiki/Projectile_motion


import math
import numpy as np
import matplotlib.pyplot as plt
import pylab
import os
# this is optional, if you want to save pictures of the trajectory
# later, then choose a folder where to save images
os.chdir("path")
# Acceleration of gravity = 9.80665 m/s**2
class Projectile_motion(object):
# s0 is horizontal starting space, we assume that the projectile starts at y = 0
# v0 is the initial velocity
# theta is the launch angle in radiants
# v0x is the horizontal component of velocity
# v0y is the vertical component of velocity
def __init__(self,s0,v0,theta):
self.s0 = s0
self.v0 = v0
self.theta = theta
self.v0x = v0*math.cos(theta)
self.v0y = v0*math.sin(theta)
# The representation of an instance of this class
def __repr__(self):
return ("The projectile starts at %s with an initial velocity of %s meters per second") %(round(self.s0,2),round(self.v0,2))
# The maximum range of the instance
def range_(self):
space = (2* (self.v0)**2 * math.sin(self.theta) * math.cos(self.theta))/(9.81)
space_km = space/1000
return "The range is %s m, that's to say: %s km." %(space,space_km)
# The maximum achievable height
def max_height(self):
height = ((self.v0)**2 * math.sin(self.theta)**2)/(a*2)
height_km = height/1000
return "Maximum achievable height is %s m, that's to say: %s km." %(height,height_km)
# For how long does the projectile stay up in the air?
def time_in_air(self):
time = (2*self.v0*math.sin(self.theta))/a
return time
# This function gives the speed at each time t
def speed(self,t):
if t > self.time_in_air():
return "Projectile has already landed, please reduce t. Projectile landed at %s" %(self.time_in_air())
y = self.v0y - a*t
x = self.v0x
vel = math.sqrt(x**2 + y**2)
if y > 0:
return "At %s seconds: horizontal speed (constant): %s m/s. Vertical speed %sm/s upwards. Combined speed: %sm/s" %(round(t,0),round(x,0),round(y,2),round(vel,2))
elif y == 0:
return "At %s seconds: horizontal speed (constant): %s m/s. Vertical speed 0. Combined speed: %sm/s" %(round(t,0),round(x,0),round(y,2),round(vel,2))
else:
return "At %s seconds: horizontal speed (constant): %s m/s. Vertical speed %sm/s downwards. Combined speed: %sm/s" %(round(t,0),round(x,0),round(y,2),round(vel,2))
# How far can it travel?
def how_far(self,t):
if t > self.time_in_air():
return "Projectile has already landed, please reduce t. Projectile landed at %s" %(self.time_in_air())
x = self.v0x*t - self.s0
x_km = x/1000
return "Horizontal space travelled in %s seconds is equal to %s m or, %s km" %(t,x,x_km)
# This function returns the position at every time t
def position(self,t):
if t > self.time_in_air():
return "Projectile has already landed, please reduce t. Projectile landed at %s" %(self.time_in_air())
x = self.s0 + self.v0x*t
y = self.s0 + self.v0y*t - 0.5*a*t**2
position_t = []
position_t.append(x)
position_t.append(y)
return position_t
# This is the most interesting function, it returns the graph of the trajectory
# Optionally you can save it or save a copy of each stage of graphing
def show_trajectory(self):
i = 0
x = []
y = []
while i <= self.time_in_air():
x.append(self.position(i)[0])
y.append(self.position(i)[1])
i += 1
plot = plt.plot(x,y,"ro")
# If you decide to print out a copy of the graph at each stage then remove
# "#"from the next line of code. This will save for each i a .png picture in the path specified above with os.chdir()
#pylab.savefig("hey"+"_%s_"%i+".png")
plt.xlabel("X")
plt.ylabel("Y")
plt.show()p = Projectile_motion(0,600,np.pi/3)
view raw physics_py.py hosted with ❤ by GitHub

Here are the results:



Here is a video I made with the instance p and the last method:




It would be fun to implement air friction and then compare the data.

If you find incorrect physics terms please let me know or comment, I might not fully remember my physics classes!! :)

3 comments:

  1. Thanks for the code. My professor has assigned me to plot the projectile projected from height(h) = 5m at an angle of 30(deg) to the horizontal with initial velocity 5m/s. I don't know when I will finish that .. :(

    ReplyDelete
  2. Dear Mic, your code is useful for us, and i thanks to you for make and posted them here.

    but i have trouble when run this code with anaconda(python3.6) even python 3.2, the annot is same
    "
    File "", line 84
    plt.show() = Projectile_motion(0,600,np.pi/3)
    ^
    SyntaxError: can't assign to function call
    "

    may you can help me to tell the problem ?

    ReplyDelete
  3. I was wondering what the "a" meant in your code? it's found first on line 38 stating (a*2).

    Thank you

    ReplyDelete