[关闭]
@LiuYongJie 2016-10-23T10:21:59.000000Z 字数 11693 阅读 406

Ex_ 05 - The Trajectory of a Cannon Shell (2.9)

author: Liu Yongjie 2014301020094


Abstract

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

Background

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:

²

and the ......... term dominates for most objects at any reasonable velocity. So we can use the fact that an object must push air in front it out of the way to move through the atmosphere.
²

C is the drag coefficient, ρ is air density, A is the front area of the object.
Another important piece of physics we should consider is air density
.
where is the sea level temperature, and the exponent α≈2.9 for air.
With density correction:

where and ³is the density at sea level.
This isothermal model of atmosphere is perhaps not realistic, since we know that the air temperature can vary quitea bit over altitude changes of a few kilometers. This leads to the second simplest model adiabatic model:

where a≈ for air. Here is the sea level temperature (in K)≈300K.
Since the drag force due to air resistance is proportional to the density, so for both models we have

Now we can get for isothermal ideal gas, the equations of motion become


Also, for adiabatic approximation, the equations of motion become


On top of that, we can use several numerical approaches including the simple Euler method and the Runge-Kutta method to yield the numerical solutions to these problems.

content

code:

  1. import math
  2. import matplotlib.pyplot as plt
  3. # import modules
  4. g=9.8
  5. B2m=0.00004
  6. y_zero=10000
  7. a=0.0065
  8. T0=300
  9. alpha=2.5
  10. # set constants
  11. class cannon0:
  12. "the simplest model with no air drag, no air density variance, no probability distribution"
  13. # initialize variables
  14. def __init__(self,v0,theta,yFinal=0):
  15. self.x0=0
  16. self.y0=0
  17. self.yFinal=yFinal
  18. self.v0=v0
  19. self.Theta=theta
  20. self.theta=theta*math.pi/180
  21. self.vx0=self.v0*math.cos(self.theta)
  22. self.vy0=self.v0*math.sin(self.theta)
  23. self.dt=0.01
  24. return None
  25. # external force other than gravity, no force in simplest case
  26. def F(self,vx,vy,y=1):
  27. return 0,0
  28. # calculate the flying trajactory
  29. def fly(self):
  30. self.X=[self.x0]
  31. self.Y=[self.y0]
  32. self.Vx=[self.vx0]
  33. self.Vy=[self.vy0]
  34. self.T=[0]
  35. while not (self.Y[-1]<self.yFinal and self.Vy[-1]<0):
  36. newVx=self.Vx[-1]+self.F(vx=self.Vx[-1],vy=self.Vy[-1],y=self.Y[-1])[0]*self.dt
  37. newVy=self.Vy[-1]-g*self.dt+self.F(self.Vx[-1],self.Vy[-1])[1]*self.dt
  38. self.Vx.append(newVx)
  39. self.Vy.append(newVy)
  40. meanVx=0.5*(self.Vx[-1]+self.Vx[-2])
  41. meanVy=0.5*(self.Vy[-1]+self.Vy[-2])
  42. # meanV=math.sqrt(meanVx**2+meanVy**2) # not used in Cannon0 because there is no air drag
  43. newX=self.X[-1]+meanVx*self.dt
  44. newY=self.Y[-1]+meanVy*self.dt
  45. self.X.append(newX)
  46. self.Y.append(newY)
  47. # fix the final landing coordinate
  48. # r=-self.Y[-2]/self.Y[-1]
  49. 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])
  50. self.Y[-1]=self.yFinal
  51. return 0
  52. # get the final distance shells can reach
  53. def distance(self):
  54. return self.X[-1]
  55. def height(self):
  56. return max(self.Y)
  57. # represent trajectory
  58. def plot(self, color):
  59. plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, no air drag"%(self.v0,self.Theta))
  60. return 0
  61. class cannon1(cannon0):
  62. "the second simplest model with no air drag under constant air density, no probability distribution"
  63. # external force other than gravity
  64. def F(self,vx,vy,y=1):
  65. vl=math.sqrt(vx**2+vy**2)
  66. self.Fx=-B2m*vx*vl
  67. self.Fy=-B2m*vy*vl
  68. return self.Fx,self.Fy
  69. def plot(self, color):
  70. plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, uniform air drag"%(self.v0,self.Theta))
  71. return 0
  72. class cannon2(cannon0):
  73. "the model concerning ISOTHERMAL air density variance but no probability distribution"
  74. def F(self,vx,vy,x=1,y=1):
  75. vl=math.sqrt(vx**2+vy**2)
  76. self.Fx=-B2m*vx*vl*math.exp(-y/y_zero)
  77. self.Fy=-B2m*vy*vl*math.exp(-y/y_zero)
  78. return self.Fx,self.Fy
  79. def plot(self, color):
  80. plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, isothermal air drag"%(self.v0,self.Theta))
  81. return 0
  82. class cannon3(cannon0):
  83. "the model concerning ADIABATIC air density variance but no probability distribution"
  84. def F(self,vx,vy,y=1):
  85. vl=math.sqrt(vx**2+vy**2)
  86. self.Fx=-B2m*vx*vl*(1-a*y/T0)**alpha
  87. self.Fy=-B2m*vy*vl*(1-a*y/T0)**alpha
  88. return self.Fx,self.Fy
  89. def plot(self, color):
  90. plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, adiabatic air drag"%(self.v0,self.Theta))
  91. return 0
  92. # select the angle casting the largest distance
  93. Distance=[]
  94. for i in range(90):
  95. A=cannon1(600,i)
  96. A.fly()
  97. newDistance=A.distance()
  98. Distance.append(newDistance)
  99. maxDistance=max(Distance)
  100. maxAngle=Distance.index(maxDistance)
  101. print maxAngle
  102. sub1=plt.subplot(221)
  103. A=cannon0(600,45)
  104. A.fly()
  105. sub1.plot(A.X,A.Y,'r-',label='$45\degree$')
  106. A1=cannon0(600,35)
  107. A1.fly()
  108. sub1.plot(A1.X,A1.Y,'r--',label='$35\degree$')
  109. A2=cannon0(600,55)
  110. A2.fly()
  111. sub1.plot(A2.X,A2.Y,'r:',label='$55\degree$')
  112. sub1.set_title('No air drag')
  113. sub1.legend(loc="upper right",frameon=False)
  114. plt.xlabel("Distance [m]")
  115. plt.ylabel("Hieght [m]")
  116. sub2=plt.subplot(222)
  117. B=cannon1(600,40)
  118. B.fly()
  119. sub2.plot(B.X,B.Y,'g-',label='$40\degree$')
  120. B1=cannon1(600,30)
  121. B1.fly()
  122. sub2.plot(B1.X,B1.Y,'g--',label='$30\degree$')
  123. B2=cannon1(600,50)
  124. B2.fly()
  125. sub2.plot(B2.X,B2.Y,'g:',label='$50\degree$')
  126. sub2.set_title('Uniform Air Drag')
  127. sub2.legend(loc="upper right",frameon=False)
  128. plt.xlabel("Distance [m]")
  129. plt.ylabel("Hieght [m]")
  130. sub3=plt.subplot(223)
  131. C=cannon2(600,45)
  132. C.fly()
  133. sub3.plot(C.X,C.Y,'b-',label='$45\degree$')
  134. C1=cannon2(600,35)
  135. C1.fly()
  136. sub3.plot(C1.X,C1.Y,'b--',label='$35\degree$')
  137. C2=cannon2(600,55)
  138. C2.fly()
  139. sub3.plot(C2.X,C2.Y,'b:',label='$55\degree$')
  140. sub3.set_title('Isothermal Air Drag')
  141. sub3.legend(loc="upper right",frameon=False)
  142. plt.xlabel("Distance [m]")
  143. plt.ylabel("Hieght [m]")
  144. sub4=plt.subplot(224)
  145. D=cannon3(600,42)
  146. D.fly()
  147. sub4.plot(D.X,D.Y,'y-',label='$42\degree$')
  148. D1=cannon3(600,32)
  149. D1.fly()
  150. sub4.plot(D1.X,D1.Y,'y--',label='$32\degree$')
  151. D2=cannon3(600,52)
  152. D2.fly()
  153. sub4.plot(D2.X,D2.Y,'y:',label='$52\degree$')
  154. sub4.set_title('Adiabatic Air Drag')
  155. sub4.legend(loc="upper right",frameon=False)
  156. plt.xlabel("Distance [m]")
  157. plt.ylabel("Hieght [m]")
  158. plt.show()
  159. #print A.distance()
  160. #print B.distance()
  161. #print C.distance()
  162. #print D.distance()

result

  1. # -*- coding: utf-8 -*-
  2. import math
  3. import numpy as np
  4. from matplotlib import pyplot as plt
  5. from matplotlib import animation
  6. g = 9.8
  7. b2m = 4e-5
  8. r = []
  9. X = []
  10. Y = []
  11. class flight_state:
  12. def __init__(self, _x = 0, _y = 0, _vx = 0, _vy = 0, _t = 0):
  13. self.x = _x
  14. self.y = _y
  15. self.vx = _vx
  16. self.vy = _vy
  17. self.t = _t
  18. class cannon:
  19. def __init__(self, _fs = flight_state(0, 0, 0, 0, 0), _dt = 0.01):
  20. self.cannon_flight_state = []
  21. self.cannon_flight_state.append(_fs)
  22. self.dt = _dt
  23. def next_state(self, current_state):
  24. global g
  25. next_x = current_state.x + current_state.vx * self.dt
  26. next_vx = current_state.vx
  27. next_y = current_state.y + current_state.vy * self.dt
  28. next_vy = current_state.vy - g * self.dt
  29. #print next_x, next_y
  30. return flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)
  31. def shoot(self):
  32. while not(self.cannon_flight_state[-1].y < 0):
  33. self.cannon_flight_state.append(self.next_state(self.cannon_flight_state[-1]))
  34. r = - self.cannon_flight_state[-2].y / self.cannon_flight_state[-1].y
  35. self.cannon_flight_state[-1].x = (self.cannon_flight_state[-2].x + r * self.cannon_flight_state[-1].x) / (r + 1)
  36. self.cannon_flight_state[-1].y = 0
  37. def show_trajectory(self):
  38. x = []
  39. y = []
  40. for fs in self.cannon_flight_state:
  41. x.append(fs.x)
  42. y.append(fs.y)
  43. X.append(x)
  44. Y.append(y)
  45. # if n == 1:
  46. # plt.subplot(111)
  47. # line, = plot(x,y, label = labe)
  48. # xlabel(r'$x(m)$', fontsize=16)
  49. # ylabel(r'$y(m)$', fontsize=16)
  50. # text(40767, 14500, 'initial speed: 700m/s\n' + 'firing angle: 45' + r'$^{\circ}$', color='black')
  51. # title('Trajectory of cannon shell')#
  52. # ax = gca()
  53. # ax.spines['right'].set_color('none')
  54. # ax.spines['top'].set_color('none')
  55. # ax.xaxis.set_ticks_position('bottom')
  56. # ax.yaxis.set_ticks_position('left')
  57. # ax.set_xlim(0, 60000)
  58. # ax.set_ylim(0, 18000)
  59. # #show()
  60. class drag_cannon(cannon):
  61. def next_state(self, current_state):
  62. global g, b2m
  63. v = math.sqrt(current_state.vx * current_state.vx + current_state.vy * current_state.vy)
  64. next_x = current_state.x + current_state.vx * self.dt
  65. next_vx = current_state.vx - b2m * v * current_state.vx * self.dt
  66. next_y = current_state.y + current_state.vy * self.dt
  67. next_vy = current_state.vy - g * self.dt - b2m * v * current_state.vy * self.dt
  68. #print next_x, next_y
  69. return flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)
  70. class adiabatic_drag_cannon(cannon):
  71. def next_state(self, current_state):
  72. global g, b2m
  73. factor = (1 - 6.5e-3 * current_state.y / 288.15) ** 2.5
  74. v = math.sqrt(current_state.vx * current_state.vx + current_state.vy * current_state.vy)
  75. next_x = current_state.x + current_state.vx * self.dt
  76. next_vx = current_state.vx - factor * b2m * v * current_state.vx * self.dt
  77. next_y = current_state.y + current_state.vy * self.dt
  78. next_vy = current_state.vy - g * self.dt - factor * b2m * v * current_state.vy * self.dt
  79. #print next_x, next_y
  80. return flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)
  81. class isothermal_drag_cannon(cannon):
  82. def next_state(self, current_state):
  83. global g, b2m
  84. factor = math.exp(-current_state.y / 1e4)
  85. v = math.sqrt(current_state.vx * current_state.vx + current_state.vy * current_state.vy)
  86. next_x = current_state.x + current_state.vx * self.dt
  87. next_vx = current_state.vx - factor * b2m * v * current_state.vx * self.dt
  88. next_y = current_state.y + current_state.vy * self.dt
  89. next_vy = current_state.vy - g * self.dt - factor * b2m * v * current_state.vy * self.dt
  90. #print next_x, next_y
  91. return flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)
  92. speed = 700
  93. theta = np.arange(30., 56., 0.1)
  94. v_x = [speed * math.cos(i * math.pi / 180) for i in theta]
  95. v_y = [speed * math.sin(i * math.pi / 180) for i in theta]
  96. def wahaha():
  97. b = []
  98. for i in range(len(theta)):
  99. b.append(adiabatic_drag_cannon(flight_state(0, 0, v_x[i], v_y[i], 0)))
  100. #labe2 = str(theta[i]) + r'$^{\circ}$'
  101. b[i].shoot()
  102. # xx = [b[i].cannon_flight_state[j].x for j in range(len(b[i].cannon_flight_state))]
  103. # yy = [b[i].cannon_flight_state[j].y for j in range(len(b[i].cannon_flight_state))]
  104. # X.append(xx)
  105. # Y.append(yy)
  106. r.append(b[i].cannon_flight_state[-1].x)
  107. b[i].show_trajectory()
  108. #legend(loc='upper left', frameon=False)
  109. wahaha()
  110. p = r.index(max(r))
  111. print theta[p], max(r),type(max(r))
  112. fig = plt.figure()
  113. ax = plt.axes(xlim=(0, 40000), ylim=(0, 18000))
  114. #labe = str(theta[i]) + r'$^{\circ}$'
  115. line, = ax.plot([], [],lw = 2,label = 'adiabatic model' ,color = 'red')
  116. angle_text = ax.text(24167, 14400, '')
  117. maxrange_text = ax.text(24167, 12400, '')
  118. plt.xlabel(r'$x(m)$', fontsize=16)
  119. plt.ylabel(r'$y(m)$', fontsize=16)
  120. plt.title('Trajectory of cannon shell')
  121. plt.legend(loc='upper left', frameon=False)
  122. # initialization function: plot the background of each frame
  123. def init():
  124. line.set_data([], [])
  125. angle_text.set_text('')
  126. maxrange_text.set_text('')
  127. return line, angle_text, maxrange_text
  128. # animation function. This is called sequentially
  129. # note: i is framenumber
  130. def animate(i):
  131. x = X[i]
  132. y = Y[i]
  133. line.set_data(x, y)
  134. pct = float(X[i][-1])/float(max(r))*100
  135. angle_text.set_text('initial speed: 700m/s\n' + 'firing angle: %s' % theta[i] + r'$^{\circ}$' + '\nrange: %f %%' % pct)
  136. if i > p:
  137. maxrange_text.set_text('max range: %s' % max(r))
  138. maxrange_text.set_color(color='red')
  139. return line, angle_text, maxrange_text
  140. fram = len(theta)
  141. # call the animator. blit=True means only re-draw the parts that have changed.
  142. anim=animation.FuncAnimation(fig, animate, init_func=init, frames=fram, interval=30, blit=True)
  143. #anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
  144. plt.show()
  145. #show()

result

Conclusion

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.

Thanks to

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注