एक चतुर्धातुक द्वारा वेक्टर 3 को घुमाते हुए


25

मैं दिए गए चतुर्भुज द्वारा एक वेक्टर 3 को घुमाने का प्रयास कर रहा हूं।

मुझे पता है कि यह सच है

v=qvq1

मुझे पता है कि q1 उलटा है जो सिर्फ qmagnitude(q) , लेकिन मैं वेक्टर के गुणन का नक्शा कैसे लाऊं ताकि सदिश वापस पा सकूं?

मैं ने पाया है कि आप का इलाज कर सकते v एक मैट्रिक्स, और परिवर्तित रूप में q और q मैट्रिक्स, और फिर परिवर्तित v एक वेक्टर के लिए एक मैट्रिक्स से है, लेकिन यह शीर्ष पर एक छोटे से सिर्फ एक वेक्टर प्राप्त करने के लिए लगता है। क्या कोई क्लीनर कार्यान्वयन है जो मैं उपयोग कर सकता हूं?

जवाबों:


36

जैसा कि नाथन रीड और टेओड्रॉन ने उजागर किया, एक इकाई-लंबाई चतुर्धातुक q द्वारा वेक्टर v को घुमाने का नुस्खा है:

1) v से शुद्ध paternion p बनाएँ । इसका सीधा सा मतलब है 0 का चौथा समन्वय जोड़ना:

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

2) इसे q के साथ प्री-गुणा करें और कंजुगेट q * से पोस्ट-गुणा करें :

p=q×p×q*

3) इसके परिणामस्वरूप एक और शुद्ध बटेरियन होगा जिसे एक वेक्टर में वापस लाया जा सकता है:

v=(px,py,pz)

यह वेक्टर v हैv तक घुमायाq


यह काम कर रहा है लेकिन इष्टतम से बहुत दूर है । क्वाटरनियन गुणन का मतलब है टन और संचालन के टन। मैं इस तरह के एक के रूप में विभिन्न कार्यान्वयन के बारे में उत्सुक था , और उन लोगों को खोजने का फैसला किया जहां से वे आए थे। यहाँ मेरे निष्कर्ष हैं।

हम q का वर्णन 3-आयामी वेक्टर u और अदिश s के संयोजन के रूप में भी कर सकते हैं :

q=(ux,uy,uz,s)q=(u,s)

चतुर्धातुक गुणा के नियमों द्वारा , और एक इकाई लंबाई चतुर्भुज के संयुग्म के रूप में बस इसका उलटा होता है, हमें मिलता है:

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),)

स्केलर भाग (दीर्घवृत्त) का परिणाम शून्य होता है, जैसा कि यहां विस्तृत है । क्या दिलचस्प है वेक्टर हिस्सा, AKA हमारे घुमाए गए वेक्टर v 'कुछ बुनियादी वेक्टर पहचानों का उपयोग करके इसे सरल बनाया जा सकता है :

v=(uv)u+s2v+s(u×v)+s(u×v)+u×(u×v)=(uv)u+s2v+2s(u×v)+(uv)u(uu)v=2(uv)u+(s2uu)v+2s(u×v)

यह अब बहुत अधिक इष्टतम है ; दो डॉट उत्पाद, एक क्रॉस उत्पाद और कुछ अतिरिक्त: लगभग आधे ऑपरेशन। जो स्रोत कोड में ऐसा कुछ देगा (कुछ सामान्य वेक्टर गणित पुस्तकालय मानकर):

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);
}

एक बेहतर लिखित प्रतिक्रिया के लिए सलाम । और यह देखते हुए कि अधिकांश प्रदर्शन शैतान वेक्टर ऑपरेशन करने के लिए आंतरिक का उपयोग करते हैं, आपको काफी गति मिलती है (यहां तक ​​कि सादे चतुर्भुज गुणन के लिए, विशेष रूप से इंटेल आर्किटेक्चर पर)।
तेओद्रोन

अंतिम परिणाम रोड्रिग्स के रोटेशन फॉर्मूले के समान है - इसमें वैसे ही आधार वैक्टर हैं; मुझे यह देखने के लिए कि क्या गुणांक मेल खाता है, कुछ ट्रिगर पहचान में खुदाई करनी होगी।
नाथन रीड

@NathanReed यह उसी परिणाम पर आने का एक और तरीका है। मैं यह जानना चाहूंगा कि क्या यह मेल खाता है। यह बात बताने के लिए धन्यवाद!
लॉरेंट कौविदो

1
मैं जीएलएम के कार्यान्वयन की जाँच कर रहा था और इसे कुछ अलग तरह से कार्यान्वित किया जा रहा है, अर्थात् निम्न प्रकार: vprime = v + ((cross(u, v) * s) + cross(u, cross(u, v)) * 2.0fक्या यह एक समान अनुकूलन है? यह कुछ हद तक समान दिखता है, लेकिन यह समान नहीं है - यह केवल क्रॉस उत्पादों का उपयोग करता है, कोई डॉट उत्पाद नहीं। मूल स्रोत कोड आधिकारिक GLM रिपॉजिटरी के type_quat.inl फ़ाइल में पाया जा सकता है operator*जिसमें एक quaternion और एक वेक्टर ( vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v))
j00hi

7

सबसे पहले, q ^ (- 1) -q / परिमाण (q) नहीं है; यह q * / (परिमाण (q)) ^ 2 (q * संयुग्म है; जो वास्तविक को छोड़कर सभी घटकों को नकारता है)। बेशक, आप परिमाण द्वारा विभाजन को छोड़ सकते हैं यदि आपके सभी quaternions पहले से ही सामान्यीकृत हैं, जो वे आम तौर पर एक रोटेशन प्रणाली में होंगे।

एक वेक्टर के साथ गुणा करने के लिए, आप वेक्टर को एक क्वाटर्नियन तक बढ़ाते हैं और एक क्वाट के वास्तविक घटक को वेक्टर के xyz में शून्य और इसके ijk घटकों को सेट करते हैं। तब आप v 'प्राप्त करने के लिए quaternion गुणन करते हैं, और फिर ijk घटकों को फिर से निकालें। (V का वास्तविक भाग 'हमेशा शून्य, प्लस या शून्य से कुछ फ़्लोटिंग-पॉइंट त्रुटि से बाहर आना चाहिए।)


5

पहला अवलोकन: इसका उलटा qनहीं है -q/magnitude(q), यह पूरी तरह से गलत है। चतुर्भुज के साथ घूर्णन का अर्थ है कि इन 4D जटिल संख्या समतुल्य एकात्मक मानदंड है, इसलिए उस 4D स्थान में S3 इकाई क्षेत्र पर झूठ है। तथ्य यह है कि एक quat एकात्मक है इसका मतलब है कि इसका आदर्श हैnorm(q)^2=q*conjugate(q)=1 और इसका मतलब है कि quat का व्युत्क्रम इसका संयुग्म है।

यदि एक इकाई चतुर्धातुक q=(w,x,y,z)= (cos (t), sin (t) v ) केconjugate(q)=(w,-x,-y,-z) रूप में लिखा जाता है , तो इसका संयुग्म = (cos (t), - sin (t) v ) है, जहाँ t रोटेशन के कोण से आधा है और v रोटेशन अक्ष (निश्चित रूप से एक इकाई वेक्टर के रूप में) है।

जब हैमिल्टन ड्यूड ने उच्च आयामों में जटिल संख्या समकक्षों के साथ खेलने का फैसला किया, तो उन्होंने कुछ अच्छे गुणों पर भी ठोकर खाई। उदाहरण के लिए, यदि आप एक पूरी तरह से शुद्ध चतुर्भुज q=(0,x,y,z)(कोई स्केलर भाग w !) को नियुक्त करते हैं, तो आप उस बकवास को एक वेक्टर के रूप में मान सकते हैं (यह वास्तव में एक क्वैट है जिसे लोग S3 क्षेत्र के भूमध्य रेखा कह सकते हैं, जो एक S2 क्षेत्र है! ! - अगर हम 19 वीं सदी में तकनीकी रूप से लोगों को कमज़ोर समझते हैं, तो हम भौंकते हैं। तो हैमिल्टन ने उस वैक्टर को अपने क्वाट रूप में लिया: v=(0,x,y,z)और क्वांटों के ज्यामितीय गुणों पर विचार करते हुए कई प्रयोग किए। लंबी कहानी:

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)

कहा पे

 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

अवलोकन: q * (0, v) * संयुग्मन (q) को फॉर्म (0, v ') का एक और उद्धरण होना चाहिए। मैं यह सब स्पष्ट रूप से जटिल विवरण के माध्यम से नहीं करूँगा कि ऐसा क्यों होता है, लेकिन यदि आप एक शुद्ध काल्पनिक चतुर्धातुक (या हमारे मामले में एक वेक्टर!) को घुमाते हैं, तो इस विधि के माध्यम से, आपको एक समान प्रकार की वस्तु मिलनी चाहिए: शुद्ध काल्पनिक क्वाट। । और आप अपने काल्पनिक भाग को अपने परिणाम के रूप में लेते हैं। आपके पास यह है, एक नट (टीवाई) शेल में चतुर्धातुक के साथ घूमने की अद्भुत दुनिया।

नोट : कि overused वाक्यांश के साथ छलांग लगाने के लिए: quats अच्छे हैं क्योंकि वे 'उन्हें गिमबल लॉक' से बचते हैं .. पहले अपनी कल्पना को अनलॉक करना चाहिए !! उद्धरण एक "सुरुचिपूर्ण" गणितीय उपकरण हैं और अन्य दृष्टिकोणों का उपयोग करके पूरी तरह से बचा जा सकता है, जिसे मैं अक्षीय दृष्टिकोण के रूप में पूरी तरह से ज्यामितीय रूप से समतुल्य पाता हूं।

कोड : C ++ लाइब्रेरी I फैंसी सरल है, लेकिन सभी मैट्रिक्स, वेक्टर और क्वाट ऑपरेशंस हैं, जिन्हें सीखने के लिए 15 मिनट से अधिक समय बर्बाद करने के बिना एक 3 डी ग्राफिक्स प्रयोगात्मकता की आवश्यकता होनी चाहिए .. आप यहां उन चीजों का परीक्षण कर सकते हैं जिन्हें मैंने उपयोग करके लिखा है। 15 मिनट में अगर आप C ++ नौसिखिए नहीं हैं। सौभाग्य!


अपने नोट के लिए +1। मैं शर्त लगाता हूं कि अधिकांश लोग असली जिम्बल लॉक हासिल नहीं कर सकते हैं अगर वे कोशिश करते हैं। यह घूर्णन करते समय किसी भी अप्रत्याशित व्यवहार के लिए एक पकड़ है।
स्टीव एच

अधिकांश लोग एक उचित गिम्बल तंत्र का निर्माण नहीं कर सकते हैं और सोचते हैं कि यदि वे एक साथ 3 घुमावों की श्रृंखला बनाते हैं, तो वे "यूलर एंगल्स" प्रतिनिधित्व के साथ स्वचालित रूप से समाप्त हो जाते हैं .. जिम्बल चीज़ केवल घूर्णन के सबसे सरल रोबोट-आर्म-प्रकार में से एक है जोड़ों कि अतिरेक का अनुभव कर सकते हैं जब उलटा कीनेमेटीक्स प्रदर्शन करने की कोशिश कर रहा है (यह वास्तव में वांछित अभिविन्यास का उत्पादन करने की आवश्यकता से अधिक स्वतंत्रता है)। ओह ठीक है, यह एक और विषय है, लेकिन मैंने सोचा कि इस "महान" मुद्दे को प्रचार कार्यक्रम से दूर रहने में अच्छा लगता है .. सीजी प्रोग्रामर्स के बीच उत्पन्न हुआ है ..
तियोड्रोन

नाइटपिकेरी: जबकि एक्सिस-एंगल समान है, जिसमें दोनों निरूपण SO (3) के सभी घुमावों का विशिष्ट रूप से प्रतिनिधित्व कर सकते हैं (ठीक है, सामान्य डबल-कवर modulo) और निश्चित रूप से उनके बीच आगे और पीछे लगभग-तुच्छ परिवर्तन है, चतुर्धातुक है अन्य सभी गैर-मैट्रिक्स अभ्यावेदन की तुलना में बहुत आसान होने का लाभ।
स्टीवन स्टडनिक

उन्हें किसी भी ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग भाषा में अपने अच्छे व्यवहार के कारण रचना करने में आसानी होती है, खासकर जब ऑपरेटर ओवरलोडिंग का उपयोग करते हैं। मुझे यकीन नहीं है, लेकिन शायद उनके गोलाकार प्रक्षेप गुण भी अक्ष-कोण (SQUAD के लिए छोड़कर शायद) के लिए संरक्षित करते हैं।)।
तियोड्रोन

2

यहां एक वेक्टर को चतुर्धातुक में बदलने का एक वैकल्पिक तरीका है। यह जिस तरह से एमएस एक्सना ढांचे में एमएस करता है। http://pastebin.com/fAFp6NnN


-1

मैंने इसे हाथ से काम करने की कोशिश की, और निम्नलिखित समीकरण / विधि के साथ आया:

// 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;
}

मैं सराहना करता हूं कि यदि कोई व्यक्ति मुझे अपमानजनक रूप से देखेगा, जिसका मैंने http://pastebin.com/8QHQqGbv उपयोग किया है तो मैं एक पाठ संपादक को कॉपी करने का सुझाव दूंगा जो साइड स्क्रॉलिंग का समर्थन करता है

अपने नोटेशन में मैंने संयुक्ताक्षर का अर्थ q ^ (- 1) का उपयोग किया, और प्रतिलोम नहीं, और विभिन्न पहचानकर्ता, लेकिन मुझे आशा है कि यह अनुवर्ती है। मुझे लगता है कि बहुमत विशेष रूप से सही है जहां साबित करने पर वेक्टर का असली हिस्सा गायब हो जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.