1

我正在尝试编写一个代码,该代码将绘制从高度 h 落下的球的模拟,并使用运动学方程 y = y_0 绘制随时间变化的位置图我的代码是这样的:

from matplotlib.pylab import show, xlabel, ylabel, scatter, plot from numpy import empty

def drop():

    """
    This function calculates and creates arrays for the velocity at eac time interval as well as the position and plots it. Assuming no drag. 
    """
    #Define the constants in the problem
    h_0 = 10
    g = -9.8 #gravitational constant N
    dt = 0.1 #timestep

    #Now need to create arrays to hold the positins, time, and velocities
    vel = empty(1000,float)
    time = empty(1000,float)
    y = empty(1000,float)

    time[0] = 0
    vel[0] = 0
    y[0] = h_0

    #code for the kinematic equations for the calculation of time, velocity and position
    for i in range of (1000-1):
        time[i+1] = time[i] + dt
        vel[i+1] = vel[i] + (g * dt)
        y[i+1] = time[i] + (vel[i+1] * dt)

        if y[i] > 0:
        #ensures that the graph will not keep going when the ball hits the ground
            break


    plot(time,y, '.')
    xlabel("Time(s)")
    ylabel("Position")
    show()

然而,当我的图表应该看起来像一条曲线时,我的图表在图表的每个角落绘制三个点,并且我的图表每次都会发生变化,因为没有任何变量发生变化

4

1 回答 1

1

好的,让我们把语法错误排除在外。for i in range of (1000-1)实际上是for i in range(1000-1),但我认为这是您的错字,因为您可以运行代码。

现在,你的运动方程是错误的。

y[i+1] = time[i] + (vel[i+1] * dt)

# should be
y[i+1] = y[i] + (vel[i] * dt)

您退出模拟的条件也存在缺陷。

if y[i] > 0:

# you have to stop when the height becomes until negative
if y[i+1] < 0:

到目前为止,您的错误意味着您将在一次迭代后退出循环,实际上并没有改变您的y数组。最后一个问题出现在这里。numpy.empty()创建一个数组而不初始化值。这意味着原始值将是此时驻留在内存中的任何值。如果您y在中断循环后打印,您可能会注意到大多数值为 0,而有些值非常小,但不接近 0,例如 3.18377034e-308。由于它们是数组中的最高值,因此它们会将您的绘图缩放到它们的范围。但由于它们是任意值,每次运行代码时,都会产生不同的数字。

您有两种选择来解决此问题。要么使用numpy.zeros(),要么只绘制第一个y[:i]值,这是您因落地而中断的循环中的点。


由于我们为您的问题中的方程提供了解析解,因此您可以取消循环并使用数组对所有内容进行矢量化。我们可以求解关于 t(二次)的位移方程,以找出我们何时会撞到地面。然后我们初始化时间数组并用它来计算位移(速度是可选的)。

import numpy as np
import matplotlib.pyplot as plt

def time_to_hit_ground(y0, v0, a):
    discriminant = np.sqrt(v0**2 - 2*a*y0)
    t1 = (-v0 - discriminant) / a
    t2 = (-v0 + discriminant) / a
    if t1 >=0:
        return t1
    return t2

def drop(y0, v0=0.0, dt=0.1, g=-9.8):
    if y0 < 0:
        print('Object is underground.')
        return
    # if you also allow the user to change `dt` and `g` from the arguments,
    # you want to check they have the correct sign.

    t_ground = time_to_hit_ground(y0, v0, g)

    t = np.arange(0, t_ground+dt, dt)
    v = v0 + g * t
    y = y0 + v0 * t + g * t**2 / 2.

    plt.plot(t, y, '.')
    plt.axvline(t_ground, color='g')
    plt.axhline(0, color='g')
    plt.xlabel('Time (s)')
    plt.ylabel('Height (m)')
    plt.show()
于 2016-01-08T06:48:24.837 回答