Memutar vektor3 dengan angka empat

25

Saya mencoba untuk memutar vektor3 dengan angka empat yang diberikan.

Saya tahu ini benar

v=qvq-1

Saya tahu bahwa adalah kebalikan yang hanya , tetapi bagaimana cara saya memetakan multiplikasi vektor ke angka empat untuk mendapatkan kembali vektor?q-1-qmSebuahgnsayatkamude(q)

Saya telah menemukan bahwa Anda dapat memperlakukan sebagai matriks, dan mengubah dan menjadi matriks, dan kemudian mengubah dari matriks ke vektor, tetapi ini tampaknya sedikit di atas hanya untuk mendapatkan vektor. Apakah ada implementasi bersih yang bisa saya gunakan?vqqv

gardian06
sumber

Jawaban:

36

Sebagaimana Nathan Reed dan teodron terpapar, resep untuk memutar vektor v oleh q angka empat satuan panjang adalah:

1) Buat p angka empat murni dari v . Ini berarti menambahkan koordinat keempat dari 0:

hal=(vx,vy,vz,0)hal=(v,0)

2) Pra-gandakan dengan q dan gandakan dengan konjugat q * :

hal=q×hal×q

3) Ini akan menghasilkan angka empat murni lain yang dapat dikembalikan ke vektor:

v=(halx,haly,halz)

Vektor ini adalah diputar oleh .vvq


Ini bekerja tetapi jauh dari optimal . Penggandaan Quaternion berarti berton-ton operasi. Saya ingin tahu tentang berbagai implementasi seperti ini , dan memutuskan untuk mencari dari mana mereka datang. Inilah temuan saya.

Kami juga bisa menggambarkan q sebagai kombinasi dari vektor 3-dimensi u dan skalar s :

q=(kamux,kamuy,kamuz,s)q=(kamu,s)

Dengan aturan perkalian angka empat , dan sebagai konjugasi dari angka empat satuan hanya kebalikannya, kita mendapatkan:

p=qpq=(u,s)(v,0)(u,s)=(sv+u×v,uv)(u,s)=((uv)(u)+s(sv+u× v)+(sv+u×v)×(u),)=((uv)u+s2v+s(u×v)+sv×(u)+(u×v)×(u),)

Bagian skalar (elips) menghasilkan nol, seperti yang dijelaskan di sini . Yang menarik adalah bagian vektor, AKA vektor diputar kami v ' . Ini dapat disederhanakan menggunakan beberapa identitas vektor dasar :

v=(uv)u+s2v+s(u×v)+s(u×v)+u×(kamu×v)=(kamuv)kamu+s2v+2s(kamu×v)+(kamuv)kamu-(kamukamu)v=2(kamuv)kamu+(s2-kamukamu)v+2s(kamu×v)

Ini sekarang jauh lebih optimal ; produk dua titik, produk silang dan beberapa tambahan: sekitar setengah operasi. Yang akan memberikan sesuatu seperti itu dalam kode sumber (dengan asumsi beberapa perpustakaan matematika vektor generik):

void rotate_vector_by_quaternion(const Vector3& v, const Quaternion& q, Vector3& vprime)
{
    // Extract the vector part of the quaternion
    Vector3 u(q.x, q.y, q.z);

    // Extract the scalar part of the quaternion
    float s = q.w;

    // Do the math
    vprime = 2.0f * dot(u, v) * u
          + (s*s - dot(u, u)) * v
          + 2.0f * s * cross(u, v);
}
Laurent Couvidou
sumber
Tutup untuk tanggapan tertulis yang lebih baik . Dan mengingat bahwa kebanyakan orang aneh kinerja cenderung menggunakan intrinsik untuk melakukan operasi vektor, Anda mendapatkan kecepatan yang cukup (bahkan untuk perkalian angka empat, terutama pada arsitektur intel).
teodron
Hasil akhirnya terlihat mirip dengan rumus rotasi Rodrigues - itu memiliki vektor basis yang sama, toh; Saya harus menggali beberapa identitas trigonometri untuk melihat apakah koefisiennya cocok.
Nathan Reed
@NathanReed Ini sepertinya cara lain untuk mencapai hasil yang sama. Saya juga ingin tahu apakah ini cocok. Terima kasih telah menunjukkan itu!
Laurent Couvidou
1
Saya sedang memeriksa implementasi GLM tentang ini dan tampaknya diimplementasikan sedikit berbeda, yaitu seperti berikut: vprime = v + ((cross(u, v) * s) + cross(u, cross(u, v)) * 2.0fApakah ini optimasi yang sama? Itu terlihat agak mirip, tetapi tidak sama - hanya menggunakan produk silang, tidak ada produk titik. Kode sumber asli dapat ditemukan di berkas type_quat.inl resmi GLM repositori dalam operator*yang membutuhkan angka empat dan vektor ( vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v))
j00hi
7

Pertama-tama, q ^ (- 1) bukan -q / magnitude (q); itu q * / (magnitude (q)) ^ 2 (q * adalah konjugat; yang meniadakan semua komponen kecuali yang asli). Tentu saja, Anda dapat meninggalkan divisi dengan besarnya jika semua angka empat Anda sudah dinormalisasi, yang biasanya akan berada dalam sistem rotasi.

Sedangkan untuk perkalian dengan vektor, Anda hanya perlu memperpanjang vektor ke angka empat dengan mengatur komponen real quat menjadi nol dan komponen ijk ke xyz vektor. Kemudian Anda melakukan perkalian angka empat untuk mendapatkan v ', dan kemudian ekstrak komponen ijk lagi. (Bagian nyata dari v 'harus selalu keluar nol, plus atau minus beberapa kesalahan floating-point.)

Nathan Reed
sumber
5

Pengamatan pertama: Kebalikan dari qtidak -q/magnitude(q), itu sepenuhnya salah. Rotasi dengan angka empat menyiratkan bahwa bilangan setara 4D kompleks ini memiliki norma kesatuan, karenanya terletak pada bidang unit S3 dalam ruang 4D itu. Fakta bahwa quat adalah kesatuan berarti norma itu adalah norm(q)^2=q*conjugate(q)=1dan itu berarti bahwa kebalikan quat adalah konjugatnya.

Jika unit angka empat ditulis sebagai q=(w,x,y,z)= (cos (t), sin (t) v ), maka konjugatnya adalah conjugate(q)=(w,-x,-y,-z)= (cos (t), - sin (t) v ), di mana t adalah setengah dari sudut rotasi dan v adalah sumbu rotasi (sebagai vektor satuan, tentu saja).

Ketika pria Hamilton itu memutuskan untuk bermain-main dengan angka-angka ekuivalen kompleks dalam dimensi yang lebih tinggi, ia juga menemukan beberapa properti bagus. Misalnya, jika Anda mempekerjakan angka empat benar-benar murni q=(0,x,y,z)(tidak ada bagian skalar w !), Anda dapat mempertimbangkan omong kosong bahwa sebagai vektor (itu sebenarnya quat pada apa yang orang sebut ekuator lingkup S3, yang merupakan lingkup S2! ! - keberatan membengkokkan barang jika kita mempertimbangkan bagaimana gangguan teknis orang-orang di abad ke-19 tampaknya bagi kita koboi EyePhone saat ini). Maka Hamilton mengambil vektor itu dalam bentuk quat-nya: v=(0,x,y,z)dan melakukan serangkaian eksperimen dengan mempertimbangkan sifat-sifat geometris quat .. Singkatnya:

INPUT: _v=(x,y,z)_ a random 3D vector to rotate about an __u__ unit axis by an angle of _theta_

OUTPUT: q*(0,_v_)*conjugate(q)

dimana

 q = (cos(theta/2), sin(theta/2)*u)
 conjugate(q) = inverse(q) = (cos(theta/2), -sin(theta/2)*u)
 norm(q)=magnitude(q)=|q|=1

Pengamatan: q * (0, v) * conj (q) harus quat lain dari bentuk (0, v '). Saya tidak akan membahas semua penjelasan yang kelihatannya rumit tentang mengapa ini terjadi, tetapi jika Anda memutar angka empat imajiner murni (atau vektor dalam kasus kami!) Melalui metode ini, Anda harus mendapatkan jenis objek yang serupa: quat imajiner murni. dan Anda mengambil bagian imajinernya sebagai hasil Anda. Itu dia, dunia rotasi yang indah dengan angka empat dalam cangkang kacang.

CATATAN : kepada siapa pun yang melompat dengan frasa yang terlalu sering digunakan: quat baik karena mereka menghindari 'kunci gimbal .. harus membuka imajinasi mereka terlebih dahulu !! Quat hanyalah alat matematika "elegan" dan dapat dihindari sama sekali dengan menggunakan pendekatan lain, yang saya temukan benar-benar setara secara geometris menjadi pendekatan sudut sumbu.

KODE : pustaka C ++ yang saya suka agak sederhana, tetapi memiliki semua operasi matriks, vektor dan quat yang harus dibutuhkan oleh seorang pencoba grafis 3D tanpa harus menghabiskan lebih dari 15 menit untuk mempelajarinya .. Anda dapat menguji hal-hal yang saya tulis di sini menggunakan itu dalam 15 menit jika Anda bukan seorang pemula C ++. Semoga berhasil!

teko teh
sumber
+1 untuk catatan Anda. Saya yakin kebanyakan orang tidak dapat mencapai kunci gimbal nyata jika mereka mencoba. Ini telah menjadi frase menangkap semua untuk perilaku tak terduga ketika melakukan rotasi.
Steve H
Kebanyakan orang tidak dapat membangun mekanisme gimbal yang tepat dan berpikir bahwa jika mereka rantai bersama 3 matriks rotasi, mereka secara otomatis berakhir dengan representasi "Euler sudut". Gimbal thingie hanyalah salah satu robot-lengan-jenis rotasi yang sederhana. sendi yang dapat mengalami redundansi ketika mencoba melakukan kinematika terbalik (memiliki lebih banyak derajat kebebasan daripada yang sebenarnya diperlukan untuk menghasilkan orientasi yang diinginkan). Oh well, itu topik lain, tapi saya pikir senang menjauh dari gembar-gembor masalah "legendaris" ini telah dihasilkan di antara programmer CG ..
teodron
Nitpickery: sementara sumbu-sudut setara dalam bahwa kedua representasi dapat mewakili semua rotasi dalam SO (3) secara unik (oke, modulo double-cover biasa) dan tentu saja ada transformasi hampir sepele bolak-balik di antara mereka, angka empat memiliki keuntungan menjadi lebih mudah untuk dikomposisikan daripada semua representasi non-matriks lainnya.
Steven Stadnicki
Mereka memiliki keuntungan karena lebih mudah untuk menulis karena perilaku mereka yang baik dalam bahasa pemrograman berorientasi objek apa pun, terutama ketika menggunakan operator yang berlebihan. Saya tidak yakin, tapi mungkin bahkan sifat interpolasi bola mereka tetap untuk sudut sumbu (kecuali untuk SQUAD mungkin ?!).
teodron
2

Berikut adalah cara alternatif untuk mengubah vektor oleh angka empat. Ini adalah cara MS melakukannya dalam kerangka xna. http://pastebin.com/fAFp6NnN

Steve H
sumber
-1

Saya mencoba menyelesaikannya dengan tangan, dan menghasilkan persamaan / metode berikut:

// inside quaterion class
// quaternion defined as (r, i, j, k)
Vector3 rotateVector(const Vector3 & _V)const{
    Vector3 vec();   // any constructor will do
    vec.x = 2*(r*_V.z*j + i*_V.z*k - r*_V.y*k + i*_V.y*j) + _V.x*(r*r + i*i - j*j - k*k);
    vec.y = 2*(r*_V.x*k + i*_V.x*j - r*_V.z*i + j*_V.z*k) + _V.y*(r*r - i*i + j*j - k*k);
    vec.z = 2*(r*_V.y*i - r*_V.x*j + i*_V.x*k + j*_V.y*k) + _V.z*(r*r - i*i - j*j + k*k);
    return vec;
}

Saya akan sangat menghargai jika seseorang akan melihat mt deriviation saya menggunakan http://pastebin.com/8QHQqGbv Saya akan menyarankan untuk menyalin ke editor teks yang mendukung pengguliran samping

dalam notasi saya, saya menggunakan q ^ (- 1) berarti konjugasi, dan bukan invers, dan pengidentifikasi yang berbeda, tapi saya berharap itu bisa diikuti. Saya pikir mayoritas benar terutama ketika membuktikan bagian nyata dari vektor akan hilang.

gardian06
sumber