自由落下

作者:王一哲
日期:2018/3/19


這次讓物體加上重力的作用,目標是畫出小球從某個高度往下加速落到地板上,並畫出小球的 y-t 圖、 v-t 圖,分為3個不同的狀況:

  1. 小球觸地時停止 (GlowScript 網站動畫連結
  2. 小球觸地時反彈 (GlowScript 網站動畫連結
  3. 小球觸地時反彈, 恢復係數為e (GlowScript 網站動畫連結

成果如下:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
自由落下畫面截圖

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
小球觸地時停止: y-t 圖及 v-t 圖

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
小球觸地時反彈: y-t 圖及 v-t 圖

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
小球觸地時反彈,e = 0.9: y-t 圖及 v-t 圖

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
小球觸地時反彈,e = 0.8: y-t 圖及 v-t 圖

程式 4-1:自由落下 (取得程式碼

""" VPython教學: 4-1.自由落下 Ver. 1: 2018/2/18 Ver. 2: 2019/9/6 作者: 王一哲 """ from vpython import * """ 1. 參數設定, 設定變數及初始值 """ size = 1 # 小球半徑 h = 15 # 小球離地高度 g = 9.8 # 重力加速度 9.8 m/s^2 t = 0 # 時間 dt = 0.001 # 時間間隔 """ 2. 畫面設定 """ scene = canvas(title="Free Fall", width=600, height=600, x=0, y=0, center=vec(0, h/2, 0), background=vec(0, 0.6, 0.6)) floor = box(pos=vec(0, 0, 0), size=vec(40, 0.01, 10), color=color.blue) ball = sphere(pos=vec(0, h, 0), radius=size, color=color.red, v=vec(0, 0, 0), a=vec(0, -g, 0)) gd = graph(title="plot", width=600, height=450, x=0, y=600, xtitle="t(s)", ytitle="blue: y(m), red: v(m/s)") yt = gcurve(graph=gd, color=color.blue) vt = gcurve(graph=gd, color=color.red) """ 3. 物體運動部分, 小球觸地時停止 """ while ball.pos.y - floor.pos.y > size + 0.5*floor.height: rate(1000) ball.v += ball.a*dt ball.pos += ball.v*dt yt.plot(pos=(t, ball.pos.y)) vt.plot(pos=(t, ball.v.y)) t += dt print("t = ", t)

參數設定

在此定義的變數有 size、h、g、t、dt,用途都已經寫在該行的註解中。

畫面設定

sphere

與前一個例子相比,這次新增的函式為 sphere,功能是用來畫出球體。sphere 是英文的球、球體,在 VPython 中用來產生球體,在這個程式中用來產生小球 ball。[3] 在產生物件時通常會調整的選項為:

  • pos: 球心位置,數值為向量,vector(x, y, z),vector 也可以簡化為 vec。
  • radius: 半徑,數值為純量。
  • color: 顏色。

也可以在產生物件後,用

[物件名稱].[選項] =

來調整物件的屬性,例如質量 m、位置 pos、速度 v、加速度 a、動量 p……等等。因此以下兩行程式碼的功能,是將名稱為 ball 的 sphere 物件速度設為 (0, 0, 0)、加速度設為 (0, -g, 0)。

ball.v = vec(0, 0, 0)
ball.a = vec(0, -g, 0)

graph

graph是英文的圖,在 VPython 中用來產生繪圖視窗。[4] ,在這個程式中我將繪圖視窗命名為 gd,並將小球的 y-t 圖和 v-t 圖畫在同一個視窗當中。

物體運動

利用一個 while 迴圈每隔一小段時間 dt 更新一次物體的狀態,由於我希望當小球接觸到地板時程式停止運作,因此在 while 裡設定的條件為

ball.pos.y - floor.pos.y > size + 0.5*floor.height

當條件成立時繼續執行。接下來逐行說明程式碼的用途。

  1. rate(1000) 是指每秒更新動畫1000次。
  2. ball.v += ball.a*dt 用來更新小球的速度,用 ball.v 讀取小球的速度,將讀取到的值加上加速度乘以一小段時間,再重新指定給小球的速度。由於所取的時間長度 dt 很短,可以當成是一小段等加速度運動,因此本式就是
    v=v0+at
  3. ball.pos += ball.v*dt 用來更新小球的位置,用 ball.pos 讀取小球的位置,將讀取到的值加上速度乘以一小段時間,再重新指定給小球的位置。由於所取的時間長度 dt 很短,可以當成是一小段等速度運動,因此本式就是
    s=v×dt
  4. yt.plot(pos = (t, ball.pos.y)) 用來畫小球的 y-t 圖。
  5. vt.plot(pos = (t, ball.v.y)) 用來畫小球的 v-t 圖。
  6. t += dt 用來更新時間。
  7. print("t = ", t) 印出整個運動經過的時間。

程式 4-2:自由落下,小球觸地時反彈 (取得程式碼

""" VPython教學: 4-2.自由落下, 小球觸地時反彈 Ver. 1: 2018/2/18 Ver. 2: 2019/9/6 作者: 王一哲 """ from vpython import * """ 1. 參數設定, 設定變數及初始值 """ size = 1 # 小球半徑 h = 15 # 小球離地高度 g = 9.8 # 重力加速度 9.8 m/s^2 t = 0 # 時間 dt = 0.001 # 時間間隔 """ 2. 畫面設定 """ scene = canvas(title="Free Fall", width=600, height=600, x=0, y=0, center=vec(0, h/2, 0), background=vec(0, 0.6, 0.6)) floor = box(pos=vec(0, 0, 0), size=vec(40, 0.01, 10), color=color.blue) ball = sphere(pos=vec(0, h, 0), radius=size, color=color.red, v=vec(0, 0, 0), a=vec(0, -g, 0)) gd = graph(title="plot", width=600, height=450, x=0, y=600, xtitle="t(s)", ytitle="blue: y(m), red: v(m/s)") yt = gcurve(graph=gd, color=color.blue) vt = gcurve(graph=gd, color=color.red) """ 3. 物體運動部分, 小球觸地時反彈 """ while t < 20: rate(1000) ball.v += ball.a*dt ball.pos += ball.v*dt yt.plot(pos=(t, ball.pos.y)) vt.plot(pos=(t, ball.v.y)) if ball.pos.y - floor.pos.y <= size + 0.5*floor.height and ball.v.y < 0: ball.v.y = -ball.v.y t += dt print("t = ", t)

程式 4-2 與 4-1 幾乎一模一樣,只是為了使小球在接觸地板時反彈,在物體運動部分增加了

if ball.pos.y - floor.pos.y <= size + 0.5*floor.height and ball.v.y < 0:
    ball.v.y = -ball.v.y

若 ball.pos.y - floor.pos.y <= size + 0.5*floor.height 代表小球碰到地板,若 ball.v.y < 0 代表小球速度向下,當兩個條件同時成立時,代表小球正在向下運動並撞到地板,小球反彈後速度由負變為正,因此將 ball.v.y 的乘上負號後再指定回 ball.v.y。

程式 4-3:自由落下,小球觸地時反彈,恢復係數為e (取得程式碼

""" VPython教學: 4-3.自由落下, 小球觸地時反彈, 恢復係數為e Ver. 1: 2018/2/19 Ver. 2: 2019/9/6 作者: 王一哲 """ from vpython import * """ 1. 參數設定, 設定變數及初始值 """ size = 1 # 小球半徑 e = 0.9 # 恢復係數 i = 0 # 小球撞地板次數 N = 20 # 小球撞地板次數上限, 到達上限後停止運作 h = 15 # 小球離地高度 g = 9.8 # 重力加速度 9.8 m/s^2 t = 0 # 時間 dt = 0.001 # 時間間隔 """ 2. 畫面設定 """ scene = canvas(title="Free Fall", width=600, height=600, x=0, y=0, center=vec(0, h/2, 0), background=vec(0, 0.6, 0.6)) floor = box(pos=vec(0, 0, 0), size=vec(40, 0.01, 10), color=color.blue) ball = sphere(pos=vec(0, h, 0), radius=size, color=color.red, v=vec(0, 0, 0), a=vec(0, -g, 0)) gd = graph(title="plot", width=600, height=450, x=0, y=600, xtitle="t(s)", ytitle="blue: y(m), red: v(m/s)") yt = gcurve(graph=gd, color=color.blue) vt = gcurve(graph=gd, color=color.red) """ 3. 物體運動部分, 小球觸地時反彈 """ while i < N: rate(1000) ball.v += ball.a*dt ball.pos += ball.v*dt yt.plot(pos=(t, ball.pos.y)) vt.plot(pos=(t, ball.v.y)) if ball.pos.y - floor.pos.y <= size + 0.5*floor.height and ball.v.y < 0: ball.v.y = -ball.v.y*e i += 1 t += dt print("i = ", i) print("t = ", t)

程式 4-3 與 4-2 幾乎一模一樣,以下只說明不同之處。

  1. 由於小球與地板間不是彈性碰撞,因此定義恢復係數

    e=vv
    其中
    v
    為撞前速度量值、
    v
    為撞後速度量值。發生碰撞時執行的程式碼改為

    ​​​​ball.v.y = -ball.v.y*e
    
  2. 為了計算小球、地板撞擊次數,並在撞擊20次時停止程式,新增變數 i = 0 (小球撞地板次數,預設值為0)、N = 20(小球撞地板次數上限, 到達上限後停止運作),while 迴圈的條件改為 i < N,每次發生碰撞時將 i 的數值 +1。

  3. 為了使小球撞擊地板時的條件更精準需要考慮地板的厚度,因此 if 的條件改為

    ​​​​ ball.pos.y - floor.pos.y <= size + 0.5*floor.height and ball.v.y < 0
    

    上式中 floor.height 是用來讀取物件 floor 的高度值。

結語

其實程式 4-1、4-2 是為了寫出 4-3 的前置作業,先寫出最簡單程式再慢慢把條件加上去,不需要一口氣就寫出很複雜的程式,那樣難度太高了。在程式 4-3 中,可以試著將 e 改成不同的值,觀察反彈高度及運動時間的變化。也可以拿一顆球實際測試看看,如果想要增加實驗的精準度,可以將小球的運動過程錄影,再用影像分析軟體 Tracker 找出小球的 y-t、v-t 圖,同時也把測得的 e 值代入程式 4-3 中,看看理論與實驗值有何差異。

VPython官方說明書

  1. canvas: http://www.glowscript.org/docs/VPythonDocs/canvas.html
  2. box: http://www.glowscript.org/docs/VPythonDocs/box.html
  3. sphere: http://www.glowscript.org/docs/VPythonDocs/sphere.html
  4. graph: http://www.glowscript.org/docs/VPythonDocs/graph.html

tags: VPython