Simulasi gerak peluru menggunakan matplotlib
Kali ini alza akan menyajikan cara membuat simulasi gerak peluru pada berbagai sudut lontar menggunakan matplotlib.
Gerak peluru (projectile motion) dalam ilmu fisika didefinisikan sebagai gerak sebuah benda/proyektil yang dilontarkan di atas permukaan bumi, dan membentuk lintasan berupa lengkungan akibat pengaruh gravitasi bumi.
Karena adanya sudut lontar/tembak, proyektil memiliki komponen pergerakan vertikal dan horizontal sekaligus. Pergerakan vertikal terpengaruh gravitasi bumi sehingga gerak mengalami perlambatan sebesar gravitasi bumi, yang mengakibatkan proyektil berhenti pada ketinggian tertentu kemudian jatuh ke tanah. Pergerakan horizontal memiliki kecepatan tetap (constant), dan berhenti saat proyektil menyentuh tanah akibat pergerakan vertikal.
Rumus yang digunakan
Artikel ini lebih menitikberatkan pada kode program yang digunakan daripada konsep fisikanya, oleh karena itu rumus yang digunakan diperlihatkan langsung dalam bentuk tiga fungsi pada kode berikut ini.
- Rumus untuk menghitung jarak tempuh horizontal (horiz_dist) setelah t detik berdasarkan kecepatan awal v0, dan sudut tembak deg derajat.
- Rumus untuk menghitung ketinggian proyektil (vert_dist) setelah t detik berdasarkan kecepatan awal v0, dan sudut tembak deg derajat.
- Rumus untuk menghitung lama waktu sebuah proyektil berada diudara (sejak ditembakkan hingga jatuh menyentuh tanah), dengan kecepatan awal v0, dan sudut tembak deg derajat.
- Konstanta gravitasi diasumsikan 9.8 meter per detik kuadrat.
GRVTY = 9.8 # gravity constant at 9.8 ms-2 # calculate horizontal distance travelled after t seconds, with initial velocity v0, and deg shoot angle def horiz_dist(v0,t,deg): tmax = ground_t(v0,deg) rad = np.radians(deg) v_horiz = v0 * np.cos(rad) if t <= tmax: dist = v_horiz * t else: dist = v_horiz * tmax return dist # calculate vertical distance to earth after t seconds, with initial velocity v0, and deg shoot angle def vert_dist(v0,t,deg): rad = np.radians(deg) v_vert = v0 * np.sin(rad) h = v_vert * t - (0.5 * GRVTY * t * t) if h >= 0: return h else: return 0 # calculate projectile airtime def ground_t(v0,deg): rad = np.radians(deg) v_vert = v0 * np.sin(rad) t = 2 * v_vert / GRVTY return t
Menyiapkan data untuk simulasi
Data untuk simulasi disiapkan sebagai berikut:
- Kecepatan awal sebesar 25 meter per detik
- Sudut tembakal/lontaran pada 30, 45, dan 60 derajat
- Posisi benda/proyektil, ketinggian dan jarak tempuh horizontal, dicatat untuk tiap 0.1 detik
Kode program untuk menghasilkan data posisi tiap proyektil dengan tiga sudut tembakan berbeda tiap-tiap 0.1 detik hingga tiap proyektil menyentuh tanah dapat dilihat berikut ini.
v0 = 25 degs = [30,45,60] t_grounds = [ground_t(v0,d) for d in degs] # calculate airtime for all angles t_ground = max(t_grounds) time_interval = 0.1 # distance between each point in time used for calculation in seconds t_steps = np.arange(0,t_ground+time_interval,time_interval) # produce list of calculation times based on time_interval # create list of horizontal position in each given time for each angle hls = [[horiz_dist(v0,t,d) for t in t_steps] for d in degs] # create list of vertical position in each given time for each angle vls = [[vert_dist(v0,t,d) for t in t_steps] for d in degs] h_max = max([ max(l) for l in hls]) # find maximum horizontal distance h_max = np.ceil(h_max) v_max = max([ max(l) for l in vls]) # find maximum vertical distance v_max = np.ceil(v_max)
Membuat animasi
Berdasarkan data yang ada kemudian dibuat animasi yang menampilkan ketiga proyektil yang ditembakkan dengan kecepatan awal sama namun sudut tembakan berbeda dengan menggunakan kode di bawah ini.
fig, ax = plt.subplots() plt.gca().set_aspect("equal") # equal scale on x axis and y axis plt.xlabel('Jarak tempuh horizontal (m)') # title for x axis plt.ylabel('Ketinggian (m)') # title for y axis plt.grid(True, which='both') # display grid for better view lines = [ax.plot([],[],label='{} derajat'.format(d))[0] for d in degs] # create plot for each angle ax.axis([0,h_max,0,v_max]) # set plot axis range ax.legend() def update(num,lines): for i in range(len(lines)): l = lines[i] l.set_data(hls[i][:num], vls[i][:num]) tm = np.round(num * time_interval,1) plt.title('Kecepatan awal: {} m/s | Waktu simulasi: {} detik'.format(v0,tm)) return lines ani = animation.FuncAnimation(fig, update, frames=len(t_steps),fargs=[lines],interval=1000*time_interval) ani.save('gifs/projectile-multi.gif', writer='imagemagick', fps=1/time_interval)
Kode lengkap dan hasilnya
Kode lengkap untuk simulasi ini dapat diakses di github pada alamat ini, kode disajikan dalam format .ipynb untuk jupyter notebook. Hasil simulasi dapat dilihat pada awal artikel ini.
Semoga bermanfaat,
Salam.
ka mau tanya, frames di line 20 gimana cara supaya berhenti di waktu pada saat pelurunya udh sampai ke tanah ya?. maksudnya supaya animasi simulasinya kalo udh sampe tanah dia berhenti ngak ngulang-ngulang. terimakasih kak
Oh. Itu sebenarnya berhenti saat proyektil mencapai tanah. Animasi berulang lebih karena format gambarnya yg berekstensi .gif dan secara default selalu diloop oleh browser.
Btw output jg bisa diset ke dalam bentuk video, misalnya .mp4.
Traceback (most recent call last):
File “C:/Users/HP/PROJECT_ACTIVE/GERAK PROYEKTIL COPAS.py”, line 76, in
ani.save(‘gifs/projectile-multi.gif’, writer= ‘fitriyadi’, fps=1 / time_interval)
File “C:\Users\HP\AppData\Local\Programs\Python\Python38\lib\site-packages\matplotlib\animation.py”, line 1102, in save
alt_writer = next(writers, None)
TypeError: ‘MovieWriterRegistry’ object is not an iterator
Process finished with exit code 1
saat saya run tulisannya seperti ini, ini kenapa ya kak ?
Maaf baru lihat, argumen writer diisi dengan plugin yg digunakan untuk membuat animasi. Kebetulan di contoh menggunakan imagemagick.
Terima kasih banyak atas pembahasannya
kak kenapa sudut 45 derajat jaraknya yang lebih panjang?
Ya, pada gerak peluru dengan kecepatan sama, jarak terjauh akan didapatkan saat sudut tembakan 45 derajat.