@LiuYongJie
2016-10-23T10:21:59.000000Z
字数 11693
阅读 406
In this homework several problems involving the motion of objects through the atmosphere are considered. Still, the problems are all described by ordinary differential equations in which initial values are given and can be solved using Euler method. This report solved cannon trajectory problem, in which air drag and reduced air density at high altitudes are considered.
Key Words: Projectile Motion; Euler Method; Air Drag; Air Density; Cannon Shell
In realistic projectile motion1, we will fail to to obtain a realistic description if we do not include Air resistance must be included if we are to obtain a realistic description of the problem.
In general, air resistance can be written in the fairly form:
code:
import mathimport matplotlib.pyplot as plt# import modulesg=9.8B2m=0.00004y_zero=10000a=0.0065T0=300alpha=2.5# set constantsclass cannon0:"the simplest model with no air drag, no air density variance, no probability distribution"# initialize variablesdef __init__(self,v0,theta,yFinal=0):self.x0=0self.y0=0self.yFinal=yFinalself.v0=v0self.Theta=thetaself.theta=theta*math.pi/180self.vx0=self.v0*math.cos(self.theta)self.vy0=self.v0*math.sin(self.theta)self.dt=0.01return None# external force other than gravity, no force in simplest casedef F(self,vx,vy,y=1):return 0,0# calculate the flying trajactorydef fly(self):self.X=[self.x0]self.Y=[self.y0]self.Vx=[self.vx0]self.Vy=[self.vy0]self.T=[0]while not (self.Y[-1]<self.yFinal and self.Vy[-1]<0):newVx=self.Vx[-1]+self.F(vx=self.Vx[-1],vy=self.Vy[-1],y=self.Y[-1])[0]*self.dtnewVy=self.Vy[-1]-g*self.dt+self.F(self.Vx[-1],self.Vy[-1])[1]*self.dtself.Vx.append(newVx)self.Vy.append(newVy)meanVx=0.5*(self.Vx[-1]+self.Vx[-2])meanVy=0.5*(self.Vy[-1]+self.Vy[-2])# meanV=math.sqrt(meanVx**2+meanVy**2) # not used in Cannon0 because there is no air dragnewX=self.X[-1]+meanVx*self.dtnewY=self.Y[-1]+meanVy*self.dtself.X.append(newX)self.Y.append(newY)# fix the final landing coordinate# r=-self.Y[-2]/self.Y[-1]self.X[-1]=((self.Y[-2]-self.yFinal)*self.X[-1]+(self.yFinal-self.Y[-1])*self.X[-2])/(self.Y[-2]-self.Y[-1])self.Y[-1]=self.yFinalreturn 0# get the final distance shells can reachdef distance(self):return self.X[-1]def height(self):return max(self.Y)# represent trajectorydef plot(self, color):plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, no air drag"%(self.v0,self.Theta))return 0class cannon1(cannon0):"the second simplest model with no air drag under constant air density, no probability distribution"# external force other than gravitydef F(self,vx,vy,y=1):vl=math.sqrt(vx**2+vy**2)self.Fx=-B2m*vx*vlself.Fy=-B2m*vy*vlreturn self.Fx,self.Fydef plot(self, color):plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, uniform air drag"%(self.v0,self.Theta))return 0class cannon2(cannon0):"the model concerning ISOTHERMAL air density variance but no probability distribution"def F(self,vx,vy,x=1,y=1):vl=math.sqrt(vx**2+vy**2)self.Fx=-B2m*vx*vl*math.exp(-y/y_zero)self.Fy=-B2m*vy*vl*math.exp(-y/y_zero)return self.Fx,self.Fydef plot(self, color):plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, isothermal air drag"%(self.v0,self.Theta))return 0class cannon3(cannon0):"the model concerning ADIABATIC air density variance but no probability distribution"def F(self,vx,vy,y=1):vl=math.sqrt(vx**2+vy**2)self.Fx=-B2m*vx*vl*(1-a*y/T0)**alphaself.Fy=-B2m*vy*vl*(1-a*y/T0)**alphareturn self.Fx,self.Fydef plot(self, color):plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, adiabatic air drag"%(self.v0,self.Theta))return 0# select the angle casting the largest distanceDistance=[]for i in range(90):A=cannon1(600,i)A.fly()newDistance=A.distance()Distance.append(newDistance)maxDistance=max(Distance)maxAngle=Distance.index(maxDistance)print maxAnglesub1=plt.subplot(221)A=cannon0(600,45)A.fly()sub1.plot(A.X,A.Y,'r-',label='$45\degree$')A1=cannon0(600,35)A1.fly()sub1.plot(A1.X,A1.Y,'r--',label='$35\degree$')A2=cannon0(600,55)A2.fly()sub1.plot(A2.X,A2.Y,'r:',label='$55\degree$')sub1.set_title('No air drag')sub1.legend(loc="upper right",frameon=False)plt.xlabel("Distance [m]")plt.ylabel("Hieght [m]")sub2=plt.subplot(222)B=cannon1(600,40)B.fly()sub2.plot(B.X,B.Y,'g-',label='$40\degree$')B1=cannon1(600,30)B1.fly()sub2.plot(B1.X,B1.Y,'g--',label='$30\degree$')B2=cannon1(600,50)B2.fly()sub2.plot(B2.X,B2.Y,'g:',label='$50\degree$')sub2.set_title('Uniform Air Drag')sub2.legend(loc="upper right",frameon=False)plt.xlabel("Distance [m]")plt.ylabel("Hieght [m]")sub3=plt.subplot(223)C=cannon2(600,45)C.fly()sub3.plot(C.X,C.Y,'b-',label='$45\degree$')C1=cannon2(600,35)C1.fly()sub3.plot(C1.X,C1.Y,'b--',label='$35\degree$')C2=cannon2(600,55)C2.fly()sub3.plot(C2.X,C2.Y,'b:',label='$55\degree$')sub3.set_title('Isothermal Air Drag')sub3.legend(loc="upper right",frameon=False)plt.xlabel("Distance [m]")plt.ylabel("Hieght [m]")sub4=plt.subplot(224)D=cannon3(600,42)D.fly()sub4.plot(D.X,D.Y,'y-',label='$42\degree$')D1=cannon3(600,32)D1.fly()sub4.plot(D1.X,D1.Y,'y--',label='$32\degree$')D2=cannon3(600,52)D2.fly()sub4.plot(D2.X,D2.Y,'y:',label='$52\degree$')sub4.set_title('Adiabatic Air Drag')sub4.legend(loc="upper right",frameon=False)plt.xlabel("Distance [m]")plt.ylabel("Hieght [m]")plt.show()#print A.distance()#print B.distance()#print C.distance()#print D.distance()
# -*- coding: utf-8 -*-import mathimport numpy as npfrom matplotlib import pyplot as pltfrom matplotlib import animationg = 9.8b2m = 4e-5r = []X = []Y = []class flight_state:def __init__(self, _x = 0, _y = 0, _vx = 0, _vy = 0, _t = 0):self.x = _xself.y = _yself.vx = _vxself.vy = _vyself.t = _tclass cannon:def __init__(self, _fs = flight_state(0, 0, 0, 0, 0), _dt = 0.01):self.cannon_flight_state = []self.cannon_flight_state.append(_fs)self.dt = _dtdef next_state(self, current_state):global gnext_x = current_state.x + current_state.vx * self.dtnext_vx = current_state.vxnext_y = current_state.y + current_state.vy * self.dtnext_vy = current_state.vy - g * self.dt#print next_x, next_yreturn flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)def shoot(self):while not(self.cannon_flight_state[-1].y < 0):self.cannon_flight_state.append(self.next_state(self.cannon_flight_state[-1]))r = - self.cannon_flight_state[-2].y / self.cannon_flight_state[-1].yself.cannon_flight_state[-1].x = (self.cannon_flight_state[-2].x + r * self.cannon_flight_state[-1].x) / (r + 1)self.cannon_flight_state[-1].y = 0def show_trajectory(self):x = []y = []for fs in self.cannon_flight_state:x.append(fs.x)y.append(fs.y)X.append(x)Y.append(y)# if n == 1:# plt.subplot(111)# line, = plot(x,y, label = labe)# xlabel(r'$x(m)$', fontsize=16)# ylabel(r'$y(m)$', fontsize=16)# text(40767, 14500, 'initial speed: 700m/s\n' + 'firing angle: 45' + r'$^{\circ}$', color='black')# title('Trajectory of cannon shell')## ax = gca()# ax.spines['right'].set_color('none')# ax.spines['top'].set_color('none')# ax.xaxis.set_ticks_position('bottom')# ax.yaxis.set_ticks_position('left')# ax.set_xlim(0, 60000)# ax.set_ylim(0, 18000)# #show()class drag_cannon(cannon):def next_state(self, current_state):global g, b2mv = math.sqrt(current_state.vx * current_state.vx + current_state.vy * current_state.vy)next_x = current_state.x + current_state.vx * self.dtnext_vx = current_state.vx - b2m * v * current_state.vx * self.dtnext_y = current_state.y + current_state.vy * self.dtnext_vy = current_state.vy - g * self.dt - b2m * v * current_state.vy * self.dt#print next_x, next_yreturn flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)class adiabatic_drag_cannon(cannon):def next_state(self, current_state):global g, b2mfactor = (1 - 6.5e-3 * current_state.y / 288.15) ** 2.5v = math.sqrt(current_state.vx * current_state.vx + current_state.vy * current_state.vy)next_x = current_state.x + current_state.vx * self.dtnext_vx = current_state.vx - factor * b2m * v * current_state.vx * self.dtnext_y = current_state.y + current_state.vy * self.dtnext_vy = current_state.vy - g * self.dt - factor * b2m * v * current_state.vy * self.dt#print next_x, next_yreturn flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)class isothermal_drag_cannon(cannon):def next_state(self, current_state):global g, b2mfactor = math.exp(-current_state.y / 1e4)v = math.sqrt(current_state.vx * current_state.vx + current_state.vy * current_state.vy)next_x = current_state.x + current_state.vx * self.dtnext_vx = current_state.vx - factor * b2m * v * current_state.vx * self.dtnext_y = current_state.y + current_state.vy * self.dtnext_vy = current_state.vy - g * self.dt - factor * b2m * v * current_state.vy * self.dt#print next_x, next_yreturn flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)speed = 700theta = np.arange(30., 56., 0.1)v_x = [speed * math.cos(i * math.pi / 180) for i in theta]v_y = [speed * math.sin(i * math.pi / 180) for i in theta]def wahaha():b = []for i in range(len(theta)):b.append(adiabatic_drag_cannon(flight_state(0, 0, v_x[i], v_y[i], 0)))#labe2 = str(theta[i]) + r'$^{\circ}$'b[i].shoot()# xx = [b[i].cannon_flight_state[j].x for j in range(len(b[i].cannon_flight_state))]# yy = [b[i].cannon_flight_state[j].y for j in range(len(b[i].cannon_flight_state))]# X.append(xx)# Y.append(yy)r.append(b[i].cannon_flight_state[-1].x)b[i].show_trajectory()#legend(loc='upper left', frameon=False)wahaha()p = r.index(max(r))print theta[p], max(r),type(max(r))fig = plt.figure()ax = plt.axes(xlim=(0, 40000), ylim=(0, 18000))#labe = str(theta[i]) + r'$^{\circ}$'line, = ax.plot([], [],lw = 2,label = 'adiabatic model' ,color = 'red')angle_text = ax.text(24167, 14400, '')maxrange_text = ax.text(24167, 12400, '')plt.xlabel(r'$x(m)$', fontsize=16)plt.ylabel(r'$y(m)$', fontsize=16)plt.title('Trajectory of cannon shell')plt.legend(loc='upper left', frameon=False)# initialization function: plot the background of each framedef init():line.set_data([], [])angle_text.set_text('')maxrange_text.set_text('')return line, angle_text, maxrange_text# animation function. This is called sequentially# note: i is framenumberdef animate(i):x = X[i]y = Y[i]line.set_data(x, y)pct = float(X[i][-1])/float(max(r))*100angle_text.set_text('initial speed: 700m/s\n' + 'firing angle: %s' % theta[i] + r'$^{\circ}$' + '\nrange: %f %%' % pct)if i > p:maxrange_text.set_text('max range: %s' % max(r))maxrange_text.set_color(color='red')return line, angle_text, maxrange_textfram = len(theta)# call the animator. blit=True means only re-draw the parts that have changed.anim=animation.FuncAnimation(fig, animate, init_func=init, frames=fram, interval=30, blit=True)#anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])plt.show()#show()
Through the first class progrem, We analysed the projectile motion of the cannon shell. We drawed the conclusion:
(1) Object orientation progreming can be more efficient compared to normal progreming.
(2) Big angle shell suffer a more serious influence not only from the airdrag but also from the air density change.
(3) With all the factors considered the angle 42.5 gained the farest diatance.