紙蜻蜓的受風面積與紙蜻蜓落地時間的關係 #2 [可視化使用VPython]
作品的網址在這裡:(https://www.glowscript.org/#/user/DCtime/folder/MyPrograms/program/MyFirstVPython)
一開始,我是使用 Python + Matplotlib 畫出有空氣阻力落體的x-t圖和v-t圖。( Python + Matplotlib 設計流程請看 https://dctimelearninghowtocode.blogspot.com/2021/01/python-matplotlib.html )老師看完我的專案後,提議可以使用VPython將得到的數據用3D模型"直接看到"東西在移動,不只以圖表呈現。因此我就開始製作這個專案。
一、學習VPython
學習國英數,課本、習作、講義、學校授課配合政策很輕易的成為我們學生的學習資源,但學校沒有自動提供VPython的學習資源,因此學習VPython的第一步,就是尋找可使用的學習資源。老師在推薦VPython,有提到可以去Google搜尋 "VPython石明豐教授" 關鍵字。沿著這個線索,找到了一個NTU做的網站(https://tcjd71.wixsite.com/vpython),裡面有許多教學文章提供下載。再搭配一些Youtube的資源,和先前學的一些Python的知識,不到一天就把我需要的知識全部學完了。
VPython是一個數據可視化的一個工具,簡單來說,就是一個3D動畫製作工具,而非一個物理模擬工具。VPython只提供圖形渲染的工具,移動只能透過直接設定位置的方式,而不是製造環境去使物件動起來。
二、製作物理動畫
正式使用VPython前,要先設定VPython的開發環境。我試著用終端機下載VPython,但她總是跳出一些奇怪的錯誤訊息,可能是因為我的設備太老舊,導致有不相容的問題。為了解決這個問題,我將錯誤碼貼上Google,希望可以找到解決方法。就在此時,我找到了GlowScript,一個可在線上開發的VPython編輯器。雖然沒有像Pycharm那麼好用,但至少解決環境的問題。
接下來,就是產生出物體有空氣阻力之落體之相關數據(速度與位移)。在上一篇的文章,我們已經完成這個步驟,Ctrl+C + Ctrl+V,這步驟就完成了。( Python + Matplotlib 設計流程請看 https://dctimelearninghowtocode.blogspot.com/2021/01/python-matplotlib.html )
有了數據,接著使用VPython將冷冰冰的數據轉化成3D動畫。在此模擬中,我做兩個長方體,一個受風面積大,另一個受風面積小。這樣就可以比較兩者的掉落情形。
另外,為了確定兩個物體的運動方式是正確的,在此再製作一個圓球,代表自由落體,照理來講,如果有空氣阻力的物體掉落的速度比自由落體快,那就代表此程式有問題,需要修正。
從這個動畫可以看到,受風面積越大,最終掉落速度越小,掉落的距離越短。而且有受到空氣阻力的物體,最後會呈現一個趨近等速的狀態,自由落體則是以等加速度落下。
以下為此專案的程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | GlowScript 3.0 VPython # ---animation settings--- time_for_a_loop = 1.0 / 30.0; max_frame = 10000; time = 0 # ---environment settings--- drag_coefficient = 0.4 air_density = 1.225 gravity = 9.8 # ---box1 status--- length_1 = 2 width_1 = 2 height_1 = 1 mass_1 = 10 speed_1 = 0 position_1 = vector(0, 0, 0) # ---box2 status--- length_2 = 1 width_2 = 1 height_2 = 1 mass_2 = 10 speed_2 = 0 position_2 = vector(5, 0, 0) # ---free-fall ball status--- mass_3 = 10 speed_3 = 0 position_3 =vector(10, 0, 0) # --- small def--- def drag_force(current_speed, affected_area, drag_coefficient = 0.4, air_density = 1.225): '''cal the air drag force''' #print("drag_force:", drag_coefficient * air_density * affected_area * current_speed * current_speed / 2) try: return drag_coefficient * air_density * affected_area * current_speed * current_speed / 2 except ZeroDivisionError: return 0 def gravity_force(mass, gravity = 9.8): '''cal the gravity affected on the item''' #print("gravity_force:", mass * gravity) return mass * gravity def final_acceleration(gravity_force, drag_force, mass): '''cal the acceleration with g force and drag force and mass effected''' #print("final_acceleration:", (gravity_force - drag_force) / mass) return (gravity_force - drag_force) / mass def delta_time_move(acceleration, min_time, current_speed): '''cal the delta time movement''' #print("delta_time_move:", current_speed * min_time + acceleration * min_time * min_time / 2) return current_speed * min_time + acceleration * min_time * min_time / 2 def delta_time_speed(acceleration, min_time, current_speed): '''cal the delta time speed (final speed)''' #print("delta_time_speed:", current_speed + acceleration * min_time) return current_speed + acceleration * min_time # --- main def --- def cal_speed(mass, gravity, current_speed, affected_area, drag_coefficient, air_density, min_time): return delta_time_speed(final_acceleration(gravity_force(mass, gravity), drag_force(current_speed, affected_area, drag_coefficient, air_density), mass), min_time, current_speed) def cal_position(now_position, mass, gravity, current_speed, affected_area, drag_coefficient, air_density, min_time): change_vector = vector(0, -1 * delta_time_move(final_acceleration(gravity_force(mass, gravity), drag_force(current_speed, affected_area, drag_coefficient, air_density), mass), min_time, current_speed), 0) return now_position + change_vector # make boxes box1 = box(pos=position_1, length=length_1, width=width_1, height=height_1, make_trail=True, trail_type="points", color=color.red) box2 = box(pos=position_2, length=length_2, width=width_2, height=height_2, make_trail=True, trail_type="points", color=color.blue) sphere3 = sphere(pos=position_3, color=color.yellow, make_trail=True, trail_type="points", color=color.yellow) # make speed graph window speed_graph = graph(xtitle="Time", ytitle="speed") speed_curve_1 = gcurve(color=color.red, label="Area = " + str(width_1 * length_1)) speed_curve_2 = gcurve(color=color.blue, label="Area = " + str(width_2 * length_2)) speed_curve_3 = gcurve(color=color.yellow, label="Free-fall") # make position graph window pos_graph = graph(xtitle="Time", ytitle="position") pos_curve_1 = gcurve(color=color.red, label="Area = " + str(width_1 * length_1)) pos_curve_2 = gcurve(color=color.blue, label="Area = " + str(width_2 * length_2)) pos_curve_3 = gcurve(color=color.yellow, label="Free-fall") for i in range(max_frame): rate(1.0 / time_for_a_loop) # cal time time = time + time_for_a_loop # cal speed speed_1 = cal_speed(mass_1, gravity, speed_1, length_1 * width_1, drag_coefficient, air_density, time_for_a_loop) speed_2 = cal_speed(mass_2, gravity, speed_2, length_2 * width_2, drag_coefficient, air_density, time_for_a_loop) speed_3 = cal_speed(mass_3, gravity, speed_3, 0, drag_coefficient, air_density, time_for_a_loop) speed_curve_1.plot(time, speed_1) speed_curve_2.plot(time, speed_2) speed_curve_3.plot(time, speed_3) # cal pos box1.pos = cal_position(box1.pos, mass_1, gravity, speed_1, length_1 * width_1, drag_coefficient, air_density, time_for_a_loop) box2.pos = cal_position(box2.pos, mass_2, gravity, speed_2, length_2 * width_2, drag_coefficient, air_density, time_for_a_loop) sphere3.pos = cal_position(sphere3.pos, mass_3, gravity, speed_3, 0, drag_coefficient, air_density, time_for_a_loop) pos_curve_1.plot(time, box1.pos.y * -1.0) pos_curve_2.plot(time, box2.pos.y * -1.0) pos_curve_3.plot(time, sphere3.pos.y * -1.0) |
三、用途
回到最初做得那受風面積與落地時間之關係的實驗:我們預測受風面積越大,落地時間越久,並從數據得知紙蜻蜓的受風面積與落地時間呈現正相關,但不是正比或一次函數的關係,此數據符合我們之預測。但我們試著去使用公式去解釋為何他會有此行為時,因數學程度不足,所以使用此程式去模擬此公式的現象:用VPython去吸引同學目光,藉由程式模擬,在不使用高深數學的狀況下使同學信服。最後,因為一些原因,並沒有將此專案搬上講臺,有些可惜。
四、製作的過程,我學到...
(一)電腦是計算機
小時候接觸電腦時,我一直認為電腦只是個遊樂器材,一個無限遊戲的儲藏庫。但隨著我電腦知識的累積,知道電腦的歷史,開始了解電腦是一個高級計算機,一個可以用撰寫程式或圖形介面使其計算出我要的答案。玩遊戲也是藉由其快速的計算達成我們的目的(螢幕投射出來,使我們獲得成就感和使我們開心的畫面)。
(二)電腦可應用在科學研究裡
最近所上的探究與實作課程,使我們可以體驗和學習科學研究的方法。電腦可以在提出預測時使用,也可以用來分析數據,彙整成圖表,更可以在實驗完成,建立模型後,利用程式去跑,比對預測是否符合。
留言
張貼留言