Bagaimana masalah terkunci gimbal diselesaikan menggunakan transformasi matriks akumulatif

12

Saya membaca buku "Learning Modern 3D Graphics Programming" online oleh Jason L. McKesson

Sampai sekarang, saya siap dengan masalah kunci gimbal dan bagaimana menyelesaikannya menggunakan angka empat.

Namun di sini, di halaman Quaternions .

Sebagian dari masalahnya adalah bahwa kami mencoba untuk menyimpan orientasi sebagai serangkaian 3 rotasi aksial terakumulasi. Orientasi adalah orientasi, bukan rotasi. Dan orientasi tentu saja bukan serangkaian rotasi. Jadi kita perlu memperlakukan orientasi kapal sebagai orientasi, sebagai kuantitas tertentu.

Saya kira ini adalah tempat pertama saya mulai bingung, alasannya adalah karena saya tidak melihat perbedaan dramatis antara orientasi dan rotasi. Saya juga tidak mengerti mengapa orientasi tidak dapat diwakili oleh serangkaian rotasi ...

Juga:

Pikiran pertama menuju tujuan ini adalah untuk menjaga orientasi sebagai matriks. Ketika tiba saatnya untuk mengubah orientasi, kita cukup menerapkan transformasi ke matriks ini, menyimpan hasilnya sebagai orientasi saat ini yang baru.

Ini berarti bahwa setiap yaw, pitch, dan roll yang diterapkan pada orientasi saat ini akan relatif terhadap orientasi saat ini. Itulah tepatnya yang kita butuhkan. Jika pengguna menerapkan yaw positif, Anda ingin yaw memutarnya relatif ke tempat mereka menunjuk saat ini, bukan relatif terhadap beberapa sistem koordinat tetap.

Konsepnya, saya mengerti, namun saya tidak mengerti bagaimana jika akumulasi transformasi matriks adalah solusi untuk masalah ini, bagaimana kode yang diberikan pada halaman sebelumnya bukan hanya itu.

Berikut kodenya:

void display()
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glutil::MatrixStack currMatrix;
    currMatrix.Translate(glm::vec3(0.0f, 0.0f, -200.0f));
    currMatrix.RotateX(g_angles.fAngleX);
    DrawGimbal(currMatrix, GIMBAL_X_AXIS, glm::vec4(0.4f, 0.4f, 1.0f, 1.0f));
    currMatrix.RotateY(g_angles.fAngleY);
    DrawGimbal(currMatrix, GIMBAL_Y_AXIS, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f));
    currMatrix.RotateZ(g_angles.fAngleZ);
    DrawGimbal(currMatrix, GIMBAL_Z_AXIS, glm::vec4(1.0f, 0.3f, 0.3f, 1.0f));

    glUseProgram(theProgram);
    currMatrix.Scale(3.0, 3.0, 3.0);
    currMatrix.RotateX(-90);
    //Set the base color for this object.
    glUniform4f(baseColorUnif, 1.0, 1.0, 1.0, 1.0);
    glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(currMatrix.Top()));

    g_pObject->Render("tint");

    glUseProgram(0);

    glutSwapBuffers();
}

Menurut pemahaman saya, bukan apa yang dia lakukan (memodifikasi matriks pada tumpukan) dianggap mengakumulasi matriks, karena penulis menggabungkan semua transformasi rotasi individu menjadi satu matriks yang disimpan di bagian atas tumpukan.

Pemahaman saya tentang matriks adalah bahwa mereka digunakan untuk mengambil titik yang relatif terhadap asal (katakanlah ... model), dan membuatnya relatif terhadap asal lain (kamera). Saya cukup yakin ini adalah definisi yang aman, namun saya merasa ada sesuatu yang hilang yang menghalangi saya untuk memahami masalah kunci gimbal ini.

Satu hal yang tidak masuk akal bagi saya adalah: Jika sebuah matriks menentukan perbedaan relatif antara dua "ruang," bagaimana bisa rotasi di sekitar sumbu Y untuk, katakanlah, roll, tidak menempatkan titik dalam "ruang roll "yang kemudian dapat ditransformasikan sekali lagi sehubungan dengan gulungan ini ... Dengan kata lain tidak boleh ada transformasi lebih lanjut ke titik ini sehubungan dengan" ruang gulungan "baru ini dan karenanya tidak memiliki rotasi relatif terhadap yang sebelumnya" ruang model "yang menyebabkan kunci gimbal.

Itu sebabnya kunci gimbal terjadi kan? Itu karena kita memutar objek di sekitar set X, Y, dan sumbu Z daripada memutar objek di sekitar itu sendiri, sumbu relatif . Atau saya salah?

Karena tampaknya kode yang saya tautkan ini bukan merupakan akumulasi transformasi matriks, tolong beri contoh solusi menggunakan metode ini.

Jadi dalam ringkasan:

  • Apa perbedaan antara rotasi dan orientasi?
  • Mengapa kode terkait bukan contoh dari akumulasi transformasi matriks?
  • Apa tujuan sebenarnya dari suatu matriks, jika saya salah?
  • Bagaimana solusi untuk masalah kunci gimbal dapat diimplementasikan menggunakan akumulasi transformasi matriks?
  • Juga, sebagai bonus: Mengapa transformasi setelah rotasi masih relatif terhadap "ruang model?"
  • Bonus lain: Apakah saya salah dengan asumsi bahwa setelah transformasi, transformasi lebih lanjut akan terjadi relatif terhadap arus?

Juga, jika tidak tersirat, saya menggunakan OpenGL, GLSL, C ++, dan GLM, jadi contoh dan penjelasan dalam hal ini sangat dihargai, jika tidak perlu.

Semakin detail semakin baik!

Terima kasih sebelumnya.

Luke San Antonio Bialecki
sumber

Jawaban:

11

Saya tidak yakin cara yang baik untuk mengawali ini, selain saya harap ini akan berhubungan dengan baik pada akhirnya. Karena itu, mari selami:

Rotasi dan orientasi berbeda karena yang pertama menggambarkan transformasi, dan yang kedua menjelaskan keadaan. Rotasi adalah bagaimana suatu benda masuk ke suatu orientasi , dan suatu orientasi adalah ruang yang diputar secara lokal dari objek tersebut . Ini dapat secara langsung terkait dengan bagaimana keduanya direpresentasikan secara matematis: sebuah matriks menyimpan transformasi dari satu ruang koordinat ke yang lain (Anda memang memiliki yang benar), dan angka empat secara langsung menggambarkan suatu orientasi. Matriks, oleh karena itu, hanya dapat menggambarkan bagaimana objek masuk ke orientasi , melalui serangkaian rotasi. Masalahnya adalah Gimbal Lock.

Gimbal lock menunjukkan sulitnya memasukkan objek ke orientasi menggunakan serangkaian rotasi. Masalah terjadi ketika setidaknya dua sumbu rotasi sejajar:

Gambar milik deepmesh3d.com
Pada gambar kiri di atas, sumbu biru dan oranye membuat rotasi yang sama! Ini adalah masalah, karena ini berarti salah satu dari tiga derajat kebebasan telah hilang, dan rotasi tambahan dari titik ini dapat menghasilkan hasil yang tidak terduga. Menggunakan angka empat memecahkan ini karena menerapkan angka empat untuk mengubah orientasi suatu objek akan langsung menempatkan objek dalam orientasi baru (itulah cara terbaik yang bisa saya katakan), daripada memecah transformasi menjadi operasi roll, pitch, dan yaw.

Sekarang, saya sebenarnya skeptis tentang akumulasi matriks menjadi solusi lengkap untuk ini, karena akumulasi matriks (karena itu akumulasi rotasi) adalah persis apa yang dapat menyebabkan masalah Kunci Gimbal di tempat pertama. Cara yang tepat untuk menangani transformasi dengan angka empat adalah dengan melakukan multiplikasi angka empat pada suatu titik:

pTransformed = q * pAsQuaternion * qConjugate

atau dengan mengubah angka empat menjadi matriks dan mengubah titik menggunakan matriks itu.

Rotasi matriks polos (seperti yaw 45 derajat) akan selalu ditentukan di ruang global. Jika Anda ingin menerapkan transformasi dalam ruang lokal, Anda harus mengubah transformasi Anda menjadi objek ruang lokal. Kedengarannya aneh, jadi saya akan menguraikan. Di sinilah pentingnya urutan rotasi. Saya sarankan mengambil buku di sini sehingga Anda dapat mengikuti dengan transformasi.

Mulailah dengan flat buku, sampulnya menghadap ke langit-langit, berorientasi seolah-olah Anda akan membukanya dan mulai membaca. Sekarang miringkan bagian depan buku hingga 45 derajat (sampul depan seharusnya menghadap Anda):

glutil::MatrixStack bookMatrix;
bookMatrix.RotateX(45);

Sekarang, katakanlah Anda ingin menyesuaikan menguap buku 45 derajat (saya pikir saya mengasumsikan sistem koordinat tangan kanan, jadi ini akan berubah menuju ke kiri), dan Anda ingin ini berlaku untuk lokal buku mengoordinasikan ruang, sehingga sampul buku akan tetap menghadap Anda:

bookMatrix.RotateY(45);

Masalahnya adalah, rotasi ini terjadi di ruang koordinat global, sehingga sampul buku akan berakhir menghadap ke bahu kanan Anda. Agar perubahan pos ini terjadi di ruang koordinat lokal, Anda harus menerapkannya terlebih dahulu!

glutil::MatrixStack bookMatrix;
bookMatrix.RotateY(45);
bookMatrix.RotateX(45);

Cobalah! Mulai buku menghadap ke atas lagi di langit-langit. Ubah yaw-nya 45 derajat, lalu turunkan 45 derajat di sepanjang sumbu X global (berjalan dari kiri ke kanan). Ini orientasi yang Anda harapkan dengan nada 45 dan menguap 45 di ruang lokal buku.

Apa artinya ini? Yang benar-benar terjadi adalah bahwa urutan operasi itu penting. Transformasi yang dilakukan terlebih dahulu menjadi transformasi lokal dalam konteks transformasi yang dilakukan sesudahnya. Menjadi banyak untuk membungkus kepala Anda, dan ini adalah bagaimana angka empat menghemat banyak masalah. Lewati semua hal yang tergantung pesanan.

Keuntungan besar lainnya yang diberikan angka empat adalah bahwa mereka memungkinkan untuk interpolasi orientasi. Mencoba untuk menyisipkan antara sudut Euler hampir mustahil karena ketergantungan urutan. Sifat matematika dari angka empat memungkinkan untuk interpolasi linier bola didefinisikan dengan baik di antara mereka.

Untuk menyelesaikan masalah dan menjawab pertanyaan awal Anda: transformasi matriks akumulatif benar-benar tidak akan menyelesaikan masalah kunci Gimbal, kecuali jika transformasi dipilih dan diterapkan secara hati-hati dalam urutan yang tepat. Oleh karena itu, selalu gunakan angka empat, dan terapkan angka empat pada poin menggunakan perkalian angka empat.

Semoga ini membantu :)

kevintodisco
sumber
4
hanya sebagai catatan, angka empat masih dapat memperkenalkan kunci gimbal jika dijelaskan melalui sudut Euler; karena Anda akan melakukan perhitungan yang sama dengan cara yang berbeda (angka empat daripada matriks)
concept3d
1
@ concept3d - selamat untuk menyebutkan ini! Penting untuk memahami apa yang membuat mekanisme gimbal rawan kehilangan tingkat kebebasan: itu seperti sebuah sendi robot yang secara inheren menggambarkan sistem persamaan yang terlalu ditentukan. Jika Anda membangun mekanisme ini dengan angka empat, matriks atau sihir, Anda masih berakhir dengan ambiguitas - itu memahaminya dan tidak menggunakannya di tempat pertama itu solusi nyata (kecuali jika Anda diharuskan menggunakannya untuk tujuan demonstratif atau teknis) .
teodron
angka empat sulit untuk membayangkan, cara saya selalu berpikir tentang hal itu adalah bahwa mereka (unit angka empat) mewakili ruang 3-Sphere, maka dapat mewakili orientasi apa pun, sementara saya mengerti sudut Euler masing-masing mewakili lingkaran / turo, maka bukan bola lengkap ini bukan cara yang sangat akurat untuk mewakili orientasi (3 lingkaran / torus tidak dapat benar-benar menghasilkan setiap orientasi yang mungkin kecuali mereka berputar secara independen yang tidak mungkin dalam kasus sudut euler), tidak yakin apakah saya menjelaskan dengan akurat :)
concept3d
1

Akumulasi matriks sebenarnya dapat memecahkan kunci Gimbal. Dengan mengakumulasi rotasi, Anda menambahkan gimbal, memungkinkan rotasi sembarang. Diagram yang disediakan ktodisco menunjukkan kunci gimbal di diagram kiri. Matriks untuk orientasi ini dapat didefinisikan sebagai:

glutil::MatrixStack bookMatrix;
bookMatrix.RotateX(90);
bookMatrix.RotateY(90);
bookMatrix.RotateZ(90);

Karena rotasi gimbal y, gimbal X dan Z sekarang terkunci, jadi kami kehilangan satu derajat gerakan. Pada titik ini kita tidak memiliki menguap (lokal y, global z) menggunakan ketiga gimbal ini. Tetapi dengan menambahkan gimbal lain, saya dapat memutar secara lokal di sekitar y:

glutil::MatrixStack bookMatrix;
bookMatrix.RotateX(90);
bookMatrix.RotateY(90);
bookMatrix.RotateZ(90);
bookMatrix.RotateY(90);

Untuk setiap roll, pitch, dan yaw baru, tambahkan saja gimbal lain, AKUMULASI mereka menjadi satu matriks. Jadi setiap kali rotasi lokal lain diperlukan, rotasi dibuat dan dikalikan dengan matriks akumulasi. Seperti yang disebutkan dalam bab ini, masih ada masalah, tetapi kunci gimbal bukan salah satunya.

Justin Ehrlich
sumber