Mengapa berintegrasi dengan akumulasi?


14

Saya mulai belajar bagaimana fisika DIY, dan saya punya pertanyaan tentang menerapkan integrasi pada tingkat paling dasar (yaitu ini bukan pertanyaan Euler vs RK4).

Hampir setiap contoh yang saya temui memiliki beberapa integrate()fungsi yang mendapat catatan waktu sejak pembaruan terakhir, dan memperbarui percepatan (dan / atau kecepatan dan / atau posisi) sejak pembaruan terakhir.

Dalam bentuk yang paling sederhana: position += velocity * deltaTime

Namun, saya tidak mengerti mengapa itu terakumulasi seperti ini ketika bisa dengan mudah didapat dengan mengubah suatu fungsi . Misalnya: getPosition = makeNewFunction()yang dapat mengembalikan sesuatu yang memiliki tanda tangan Time -> Position, dan cara kerja fungsi tersebut dihasilkan melalui rumus matematika yang sesuai.

Dengan begitu, tidak ada akumulasi ... kapan pun posisi perlu didapatkan, ia memanggil fungsi itu dengan waktu saat ini.

Pemahaman pemula saya adalah bahwa ini juga akan menghindari kesalahan yang berasal dari akumulasi ... jadi mengapa ini tidak berhasil, apa yang saya lewatkan?

(Fwiw saya memang mengumpulkan bukti dasar konsep ide ini - meskipun itu juga menguji beberapa hal lain pada saat yang sama sehingga itu bukan contoh terbersih: https://github.com/dakom/ball-bounce-frp )

EDIT 1: seperti yang disebutkan dalam komentar, mungkin penting untuk menunjukkan bahwa saya belum belajar tentang mengubah akselerasi, atau berurusan dengan brengsek dan hal-hal lain yang memerlukan integrasi tingkat tinggi daripada akselerasi konstan.

EDIT 2: di sini adalah beberapa contoh kode dasar ide, dan pseudo javascript sintaks - catatan yang getKinematicPositionadalah sebagian diterapkan sehingga mengembalikan fungsi baru saja Waktu -> Posisi:

Saya berpegang teguh pada posisi di sini tetapi itu bisa menjadi sesuatu yang lain, seperti getVelocity, saya kira ...

getKinematicPosition = initialVelocity => acceleration => time => 
  ((.5 *acceleration) * (time * time)) + (initialVelocity * time);

getPosition = getKinematicPosition ([0,0,0]) (GRAVITY);

onTick = totalTime => {
   position = getPosition (totalTime);
   onCollision = () => {
     getPosition = changeTheFunction(totalTime);
     //changeTheFunction uses totalTime to base updates from 0
     //it could use getKinematicPosition or something else entirely
   }
}

1
Apa yang akan fungsi Anda lakukan, jika Anda memiliki kecepatan / akselerasi yang tidak konstan?
Linaith

Saya tidak punya ide! : D Jika itu alasannya - misalnya saya belum mengubah akselerasi, saya akan sangat menghargai penjelasan yang lebih lengkap tentang di mana ini akan rusak sebagai jawabannya (jika tidak saya akan pergi ke jalan fungsional ini dan menemui jalan buntu !)
davidkomer

6
Nah jika objek Anda hanya berputar-putar, maka yakinlah ... bagaimana kalau itu kotak yang pemain dorong? Saat Anda memanggil getPosition (sekarang + 100) apakah ini memprediksi masa depan untuk mengetahui kapan pemain akan berhenti mendorongnya? Ketika Anda memanggil getPosition (sekarang-1000) apakah harus mengingat masa lalu?
user253751

Jawaban:


34

... cara kerja fungsi tersebut dihasilkan melalui rumus matematika yang sesuai ...

Ini akan bekerja untuk kelas masalah tertentu, dan frasa kunci untuk mencari adalah solusi bentuk-tertutup . Misalnya, dalam Program Luar Angkasa Kerbal, gerakan pesawat ruang angkasa di orbit dihitung dengan cara ini. Sayangnya, sebagian besar masalah non-sepele (misalnya masuknya kembali atmosfer dari pesawat ruang angkasa tersebut) tidak memiliki solusi bentuk tertutup yang diketahui. Dengan demikian kebutuhan akan pendekatan numerik yang lebih sederhana secara matematis (yaitu integrate()seiring waktu).


Ahh ... luar biasa! Jika Anda punya waktu - apa yang Anda pikirkan tentang tujuan untuk pendekatan fungsional ini, dan kemudian kembali pada akumulasi jika saya tidak tahu bagaimana cara membuatnya bekerja (misalnya jika saya sedang berurusan dengan masalah formulir tidak tertutup atau Saya tidak tahu bagaimana mengubahnya menjadi satu)? Saya suka ide menghasilkan fungsi karena cocok dengan matematika 1: 1 - tetapi jika saya akan selalu menemui jalan buntu pasti tidak akan sia-sia ...
davidkomer

8
@davidkomer Mengapa Anda ingin tetap menghasilkan fungsi? Jika Anda bisa melakukan ini, maka Anda bisa melakukan pra-perhitungan dan merekam seluruh lintasan! Tentu saja, orang sudah melakukan ini: ini disebut animasi , dan memiliki bagian kehalusannya.
Joker_vD

Fungsi berubah berdasarkan dinamika runtime ... lihat FRP ball-bouncing misalnya
davidkomer

Sebenarnya saya harus memperbarui contoh itu menjadi sesuatu yang lebih seperti pong, dengan objek bergerak dikontrol secara acak / oleh pengguna ...
davidkomer

10

Masalah dengan pendekatan Anda adalah, bahwa Anda tidak memiliki riwayat objek Anda. Anda dapat menghitung posisi jika Anda bergerak ke suatu arah, tetapi apa yang terjadi jika Anda menekan sesuatu dan bangkit kembali?
Jika Anda terakumulasi dari posisi terakhir yang diketahui, Anda dapat menangani dampaknya dan melanjutkan dari sana. Jika Anda mencoba menghitungnya dari awal, Anda harus menghitung ulang dampaknya setiap waktu, atau menetapkannya sebagai posisi awal yang baru.

Teladan Anda mengingatkan saya pada sebuah game balapan. (Saya tidak tahu apakah posisi akan dikontrol oleh mesin fisika, tetapi saya pikir itu bekerja dengan baik untuk menjelaskan)
Jika Anda mengemudi dengan mobil Anda, Anda dapat mempercepat dan memperlambat. Anda tidak dapat menghitung posisi Anda tanpa mengetahui bagaimana profil kecepatan mobil Anda terlihat dari awal hingga sekarang. Akumulasi jaraknya jauh lebih mudah daripada menyimpan kecepatan yang Anda miliki di setiap frame dari awal hingga sekarang.

Penafian: Saya belum menulis fisika permainan saat ini, begitulah cara saya melihat masalahnya.

Sunting:
Di diagram ini Anda dapat melihat bagaimana nilai berubah seiring waktu.
merah = akselerasi (dari mulai akselerasi ke sloving down)
hijau = kecepatan (dari mulai berhenti)
biru = cara Anda pergi.

Kecepatan total adalah bagian integral dari akselerasi dari titik awal Anda ke log aktual Anda. (Area antara garis dan sumbu)
Jalan adalah integral dari kecepatan Anda.
Jika Anda tahu nilai untuk akselerasi Anda, Anda bisa menghitung nilai lainnya. Tetapi jika saya tidak salah apakah integral juga dihitung dengan akumulasi pada PC. Dan itu jauh lebih mahal untuk menyimpan semua nilai percepatan.
Plus itu mungkin terlalu banyak untuk dihitung setiap frame.

diagram akselerasi / kecepatan / cara-waktu

Saya tahu, keterampilan melukis saya luar biasa. ;)

Sunting 2:
Contoh ini untuk gerakan linier. Arah canging membuat ini semakin sulit.


"atau atur sebagai posisi awal yang baru." - ya, tapi saya tidak melihat masalah dengan itu :) Re: contoh mobil ... Saya mendapatkan perasaan kuat bahwa saya benar-benar harus mulai bermain dengan sesuatu yang lebih kompleks seperti itu untuk secara intuitif memahami di mana ini gagal .. .
davidkomer

pengaturan posisi baru mungkin bukan masalah. saya mengedit bagian mobil
Linaith

1
Dalam permainan mobil, saya membayangkan akselerasi akan menjadi lebih kompleks. Mungkin akan ada lompatan dan paku, dan itu mungkin tergantung pada kecepatan. (Misalnya, akselerasi berkurang ke 0 saat mobil mendekati kecepatan tertinggi.)
jpmc26

3
@davidkomer bahkan tidak peduli dengan mobil (kecuali jika Anda mau), platformer dasar akan melakukannya. Bagaimana cara mario.getPosition (Time) bekerja di Super Mario Bros?
user253751

8

Namun, saya tidak mengerti mengapa itu terakumulasi seperti ini ketika bisa dengan mudah didapat dengan mengubah suatu fungsi. Misalnya: getPosition = makeNewFunction () yang dapat mengembalikan sesuatu yang memiliki tanda tangan Waktu -> Posisi, dan cara kerja bagian dalam dari fungsi tersebut dihasilkan melalui rumus matematika yang sesuai.

Kamu bisa!

Ini disebut menggunakan solusi bentuk analitis atau tertutup . Ini memiliki manfaat yang lebih akurat, karena kesalahan pembulatan yang menumpuk dari waktu ke waktu tidak ada.

Namun, ini berfungsi jika dan hanya jika Anda tahu formulir tertutup sebelumnya. Untuk permainan, ini cukup sering tidak terjadi.

Gerakan pemain tidak menentu dan tidak bisa dimasukkan ke dalam beberapa fungsi yang sudah dihitung sebelumnya. Pemain dapat dan akan mengubah kecepatan dan orientasinya dengan cukup sering.

NPC berpotensi memanfaatkan solusi bentuk tertutup, dan pada kenyataannya kadang-kadang mereka melakukannya. Namun ini memiliki beberapa kelemahan lainnya. Pikirkan tentang game balap sederhana. Setiap kali kendaraan Anda bertabrakan dengan kendaraan lain, Anda harus mengubah fungsi Anda. Mungkin mobil bergerak lebih cepat tergantung dari bawah tanah. Maka menemukan solusi bentuk tertutup seperti itu akan sangat sulit. Bahkan, ada kemungkinan lebih banyak kasus di mana menemukan bentuk tertutup seperti itu tidak mungkin atau sangat rumit sehingga sama sekali tidak layak.

Contoh yang bagus untuk menggunakan solusi bentuk tertutup adalah Program Luar Angkasa Kerbal. Begitu roket Anda berada di orbit dan tidak didorong, KSP dapat meletakkannya "di atas rel". Orbits sudah ditentukan sebelumnya dalam sistem dua tubuh, dan bersifat periodik. Selama roket tidak lagi menggunakan gaya dorong, Anda sudah tahu di mana roket akan berada, dan Anda bisa memanggilnya getPositionAtTime(t)(tidak disebutkan persis seperti itu, tetapi Anda mendapatkan ide).

Namun dalam praktiknya, hanya menggunakan integrasi langkah demi langkah seringkali jauh lebih praktis. Tetapi ketika Anda melihat situasi di mana solusi bentuk tertutup ada dan mudah untuk dihitung, lakukan! Tidak ada alasan untuk tidak menggunakannya.

Misalnya, jika karakter Anda mengarahkan meriam, Anda dapat dengan mudah menunjukkan titik tumbukan bola meriam yang diprediksi menggunakan solusi bentuk-tertutup. Dan, jika gim Anda tidak memungkinkan untuk mengubah arah bola meriam (tidak ada angin misalnya), Anda bahkan dapat menggunakannya untuk memindahkan bola meriam. Perhatikan bahwa Anda perlu berhati-hati terhadap rintangan yang bergerak ke jalur bola meriam Anda.

Ada banyak situasi serupa. Jika Anda membuat game berbasis bulat, maka ada kemungkinan akan ada solusi bentuk tertutup yang jauh lebih banyak daripada saat membangun game RTS, karena Anda tahu semua parameter sebelumnya dan dapat mengatakan dengan pasti bahwa itu tidak berubah (tidak ada yang bergerak tiba-tiba ke jalan itu, misalnya).

Perhatikan bahwa ada teknik untuk memerangi ketidakakuratan numerik dari integrasi bertahap. Misalnya, Anda dapat melacak akumulasi kesalahan dan menerapkan istilah korektif untuk menjaga kesalahan dalam pemeriksaan, misalnya Penjumlahan Kahan


8

Dalam kasus bola memantul sederhana, datang dengan solusi bentuk tertutup mudah. Namun, sistem yang lebih kompleks cenderung membutuhkan penyelesaian Persamaan Diferensial Biasa (ODE). Pemecah angka diperlukan untuk menangani semua kasus kecuali yang paling sederhana.

Memang ada dua kelas pemecah ODE numerik: eksplisit dan implisit. Pemecah eksplisit memberikan perkiraan bentuk tertutup untuk keadaan Anda berikutnya, sementara pemecah implisit membutuhkan penyelesaian persamaan untuk melakukannya. Apa yang Anda gambarkan untuk bola memantul Anda sebenarnya adalah pemecah ODE implisit, terlepas Anda mengetahuinya atau tidak!

Pemecah implisit memiliki keuntungan karena dapat menggunakan langkah waktu yang jauh lebih besar. Untuk algoritme bola pantul Anda, tanda waktu Anda dapat setidaknya sebesar durasi hingga tabrakan berikutnya (yang akan mengubah fungsi Anda). Ini dapat membuat program Anda berjalan lebih cepat. Namun, secara umum, kami tidak selalu dapat menemukan solusi implisit yang baik untuk ODE yang kami minati. Ketika kami tidak bisa, kami kembali ke integrasi eksplisit.

Keuntungan besar yang saya lihat dengan integrasi eksplisit adalah bahwa gotcha sudah terkenal. Anda dapat membuka buku teks apa pun dari tahun 60-an dan membaca semua yang perlu Anda ketahui tentang keanehan kecil yang muncul dengan teknik integrasi tertentu. Dengan demikian, pengembang mempelajari keterampilan ini sekali, dan mereka tidak perlu mempelajarinya lagi. Jika Anda melakukan integrasi implisit, setiap use case sedikit berbeda, dengan gotcha yang sedikit berbeda. Agak sulit untuk menerapkan apa yang Anda pelajari dari satu tugas ke yang berikutnya.


1

pos (t) = v (t) * t

hanya berfungsi jika pos (0) = 0 dan v (t) = k

Anda tidak dapat menghubungkan posisi ke waktu tanpa mengetahui kondisi awal dan seluruh fungsi kecepatan, sehingga persamaannya adalah sebagai perkiraan dari integral

pos (t) = integral dari v (t) dt dari 0 hingga t

EDIT _________

Inilah sedikit bukti per komentar (dengan asumsi pos (0) = 0)

biarkan v (t) = 4

eqn 1: pos (t) = 4 * t (benar)

eqn 2: pos (t) = c + 4 * t dari 0 hingga t = 4 * t (benar)

biarkan v (t) = 2 * t

eqn 1: pos (t) = 2 * t ^ 2 (salah)

eqn 2: pos (t) = c + t ^ 2 dari 0 hingga t = t ^ 2 (benar)

Saya harus menambahkan bahwa persamaan Anda sudah menjadi faktor dalam percepatan konstan (yaitu persamaan Anda adalah eqn 2 di mana v (t) = v0 + a * t dan batas integrasi adalah t0 dan t), sehingga persamaan Anda harus berfungsi selama Anda memperbarui posisi awal, kecepatan awal, dan akselerasi tetap konstan.

EDIT2 ________

Saya juga harus menambahkan bahwa Anda juga dapat menghitung posisi dengan posisi awal, kecepatan awal, percepatan awal, dan sentakan konstan. Dengan kata lain, Anda dapat membuat fungsi berdasarkan persamaan 2 yang mewakili posisi vs waktu dengan memisahkannya menjadi turunannya yaitu kecepatan, brengsek, apa pun yang terjadi selanjutnya, dll, dll, dll, tetapi Anda hanya akan akurat dalam persamaan Anda jika v (t) dapat dimodelkan seperti itu. Jika v (t) tidak dapat dimodelkan hanya dengan kecepatan, akselerasi, brengsek konstan, dll, maka Anda perlu kembali ke perkiraan eqn 2, yang cenderung terjadi ketika Anda memiliki sesuatu yang memantul, hambatan udara, angin, dll. .


sebuah konstanta. itu hanya berarti v (t) tidak boleh berbeda dari waktu ke waktu
Kyy13

Saya harus duduk dengan ini dan mencari tahu mengapa itu benar ... upvoting untuk sekarang :) Saya memposting sampel kode dalam pertanyaan jika itu mengubah hal
davidkomer

tidak masalah, diperbarui lagi dengan kata-kata yang lebih baik :)
Kyy13
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.