我正在编写一个程序来查找一个子弹以20度的角度射击多远,各种参数有无阻力。出于某种原因,我的程序立即计算出子弹的y值低于零,我认为这可能与我使用的物理方程有关。我没有最强大的物理背景,所以在努力弄清楚我哪里出错之后,我想我会寻求帮助。在下图中,我试图显示与不同时间步长相关的不同距离。
import math
import matplotlib.pyplot as plt
rho = 1.2754
Af = math.pi*(16*0.0254)**2/4
g = -9.8 #m/s^2
V = 250.0 #m/s
#equation of motion
def update(r,V,a,dt):
return r+V*dt +.5*a*dt*dt, V + a*dt
#drag force from velocity vector return x and y
def drag(Vx,Vy):
Vmag = math.sqrt(Vx**2+Vy**2)
Ff = .5*Cd*rho*Af*Vmag**2
return -Ff * Vx/Vmag, -Ff *Vy/Vmag
def getTrajectory(dt, th):
#initialize problem [time,x,y,Vx,Vy]
state = [[0.0,0.0,0.0, V*math.cos(th), V*math.sin(th)]]
while state[-1][2] >= 0 : # while y > 0
time = state[-1][0] + dt
Fd = drag(state[-1][3],state[-1][4]) # Vx,Vy
ax = Fd[0]/m # new x acceleration
ay = (Fd[1]/m) +g # new y acceleration
nextX, nextVx = update(state[-1][1], state[-1][3],ax,dt) #x,Vx,acceleration x, dt
nextY, nextVy = update(state[-1][2], state[-1][4],ay,dt) #y,Vy, acceleration y, dt
state.append([time,nextX,nextY,nextVx,nextVy])
# linear interpolation
dtf = -state[-1][2]*(state[-2][0]-state[-1][0])/(state[-2][2]-state[-1][2])
xf,vxf = update(state[-1][1],state[-1][3], ax, dtf)
print(xf,vxf)
yf,vyf = update(state[-1][2],state[-1][4], ay, dtf)
print(yf,vyf)
state[-1] = [time+dtf,xf,yf,vxf,vyf]
return state
delt = 0.01 #timestep
th = 20.0 * math.pi/180.0 #changing to radians
m = 2400 #kg
Cd = 1.0
tsteps = [0.001,0.01,0.1,1.0,3.0] # trying different timesteps to find the optimal one
xdistance = [getTrajectory(tstep,th)[-1][1] for tstep in tsteps]
plt.plot(tsteps,xdistance)
plt.show()
状态变量的打印,包含一个时间步后的所有时间值x,y,Vx和Vy,得到: [[0.0,0.0,0.0,234.9231551964771,85.50503583141717] ,[0.0,0.0,-9.540979117872439e-18,234.9231551964771,85.50503583141717]] 第一个数组是初始条件,Vx和Vy分解为由20度角计算的矢量。第二个阵列的子弹应该以正x和y飞行,但由于某种原因,y值被计算为-9.54e-18,它退出了getTrajectory方法,因为它只能继续,而y> 0
为了简化我的问题,我认为专门研究我的更新功能可能会有所帮助。
def update(initial,V,a,dt): #current x or y, Velocity in the x or y direction, acceleration in x or y, timestep
return initial+V*dt +.5*a*dt*dt, V + a*dt
此函数应该返回更新的x,Vx或更新的y,Vy,具体取决于传递的内容。我认为这可能是物理方程中的问题,但我并不完全确定。
答案 0 :(得分:0)
我想我知道发生了什么:在你的while循环中,你首先做一个前进时间步骤来计算t = 0.001
的{{1}}的运动变量,然后你将t = 0
设置为负值,然后设置一个向后时间步,以便根据您在dtf
(或其他)计算的值计算t = 0
处的新值。我不确定你为什么这样做,但无论如何你的t = 0.001
函数正在使用数字不稳定的Euler method - 当你采取越来越多的步骤时,它往往越来越偏离以某种不可预测的方式提供真正的解决方案。在这种情况下,它会变为负y位置,而不是像你期望的那样将其设置为0。
没有任何数值积分方法可以为您提供完美的结果,因此您总是可以期待一点点不准确,这可能是正面的或负面的。只是因为某些事情有点消极并不是必然引起关注。 (但这可能是,取决于具体情况。)话虽如此,通过使用更强大的整合方法,如Runge-Kutta 4阶(a.k.a. RK4)或辛积分器,您可以获得更好的结果。但这些都是一些先进的技术,所以我现在不会太担心它们。
至于手头的问题,我想知道你的方程中某处是否有符号错误,可能在设置update()
的行中。我不能肯定地说,因为我真的不明白dtf
应该如何运作。
答案 1 :(得分:0)
这似乎是一个缩进错误。从线性插值开始确定y
零交叉位置的部分肯定不是集成循环的一部分,尤其不是return
语句。修复此缩进级别会产生输出
(3745.3646817336303, 205.84399509886356)
(6.278677479133594e-07, -81.7511764639779)
(3745.2091465034314, 205.8432621147464)
(8.637877372419503e-05, -81.75094436152747)
(3743.6311931495325, 205.83605594288176)
(0.01056407140434586, -81.74756057157798)
(3727.977248738945, 205.75827166721402)
(0.1316764390634169, -81.72155620161116)
(3669.3437231150106, 205.73704583954634)
(10.273469073526238, -80.52193274789204)