2013-05-20 9 views
6

मैं ज्ञात इकाई वैक्टर के साथ दो कार्तीय निर्देशांक प्रणाली है:गिना जा रहा है चार का समुदाय समन्वय प्रणाली

प्रणाली ए (x_A, y_A, z_A)

और

प्रणाली बी (x_B , y_B, z_B)

दोनों सिस्टम एक ही मूल (0,0,0) साझा करते हैं। मैं एक quaternion की गणना करने की कोशिश कर रहा हूँ, ताकि सिस्टम बी में वेक्टर सिस्टम ए

में व्यक्त किया जा सकता है मैं quaternions की गणितीय अवधारणा से परिचित हूँ। मैंने पहले से ही आवश्यक गणित लागू कर दिया है: http://content.gpwiki.org/index.php/OpenGL%3aTutorials%3aUsing_Quaternions_to_represent_rotation

एक संभावित समाधान यूलर कोणों की गणना करने और 3 quaternions के लिए उनका उपयोग करने के लिए हो सकता है। उन्हें गुणा करने पर एक अंतिम एक करने के लिए नेतृत्व ताकि मेरी वैक्टर परिवर्तित कर जाएगा:

वी (ए) = क्ष * वी (बी) * q_conj

लेकिन इस गिम्बल ताला फिर से शामिल होता है, जो कारण था शुरुआत में यूलर कोण का उपयोग न करें।

कोई विचारधारा इसे कैसे हल करें?

उत्तर

0

आपको ए के संबंध में ए के संबंध में बी के अभिविन्यास को व्यक्त करने की आवश्यकता है। फिर बी में किसी भी वेक्टर को ए में एक वेक्टर में परिवर्तित किया जा सकता है। Q. vectorInA = R * vectorInB से व्युत्पन्न एक रोटेशन मैट्रिक्स आर का उपयोग करके। http://simonbox.info/index.php/blog/86-rocket-news/92-quaternions-to-model-rotations

1

आप कौन-सी भाषा का उपयोग कर रहे हैं:

इस लिए इस साइट पर उपलब्ध मैटलैब/सप्टक पुस्तकालय में (एक अच्छा दृश्य भी शामिल है) करने के लिए एक डेमो स्क्रिप्ट नहीं है? C++, मेरे खुला स्रोत पुस्तकालय का उपयोग करने के लिए स्वतंत्र महसूस करते हैं:

http://sourceforge.net/p/transengine/code/HEAD/tree/transQuaternion/

की बात है, तो आप quaternions करने के लिए अपने वैक्टर कन्वर्ट करने के लिए, अपनी गणना करना तो एक परिवर्तन करने के लिए अपने चार का समुदाय परिवर्तित की आवश्यकता होगी, और लघु मैट्रिक्स।

cQuat nTrans::quatFromVec(Vec vec) { 
    float angle = vec.v[3]; 
    float s_angle = sin(angle/2); 
    float c_angle = cos(angle/2); 
    return (cQuat(c_angle, vec.v[0]*s_angle, vec.v[1]*s_angle, 
        vec.v[2]*s_angle)).normalized(); 
} 

और चार का समुदाय से मैट्रिक्स के लिए:

Matrix nTrans::matFromQuat(cQuat q) { 
    Matrix t; 
    q = q.normalized(); 
    t.M[0][0] = (1 - (2*q.y*q.y + 2*q.z*q.z)); 
    t.M[0][1] = (2*q.x*q.y + 2*q.w*q.z);   
    t.M[0][2] = (2*q.x*q.z - 2*q.w*q.y); 
    t.M[0][3] = 0; 
    t.M[1][0] = (2*q.x*q.y - 2*q.w*q.z);   
    t.M[1][1] = (1 - (2*q.x*q.x + 2*q.z*q.z)); 
    t.M[1][2] = (2*q.y*q.z + 2*q.w*q.x);   
    t.M[1][3] = 0; 
    t.M[2][0] = (2*q.x*q.z + 2*q.w*q.y);  
    t.M[2][1] = (2*q.y*q.z - 2*q.w*q.x);   
    t.M[2][2] = (1 - (2*q.x*q.x + 2*q.y*q.y)); 
    t.M[2][3] = 0; 
    t.M[3][0] = 0;     
    t.M[3][1] = 0;     
    t.M[3][2] = 0;    
    t.M[3][3] = 1; 
    return t; 
} 
+0

हालांकि आपका कोड दिलचस्प था, यह वास्तव में मेरी समस्या का समाधान नहीं करता था। अंत में मैंने नौकरी करने के लिए एक दिशा कोसिनस मैट्रिक्स (डीसीएम) का उपयोग किया।मुझे अभी भी दिलचस्पी है यदि कोई व्यक्ति रूपांतरण quaternion प्राप्त करने के लिए एक तरीका प्रदान कर सकता है, लेकिन मुझे सच में यकीन नहीं है कि यूलर या डीसीएम का उपयोग किए बिना सीधे इस quaternion प्राप्त करना संभव है। – Mo3bius

4

आप चौका गणना कर सकते हैं में से एक से सबसे अच्छा संभव परिवर्तन का प्रतिनिधित्व करने

वेक्टर से Quaternion:

कोड स्निपेट है इस पेपर में वर्णित विधि द्वारा सिस्टम को समन्वयित करें:

पॉल जे। बेसल और नील डी। मैके "3-डी आकार के पंजीकरण के लिए विधि", सेंसर फ़्यूज़न IV: नियंत्रण पैराडिगम्स और डेटा स्ट्रक्चर, 586 (30 अप्रैल, 1 99 2); http://dx.doi.org/10.1117/12.57955

कागज खुली पहुंच नहीं है, लेकिन मैं तुम्हें अजगर कार्यान्वयन दिखा सकते हैं:

def get_quaternion(lst1,lst2,matchlist=None): 
if not matchlist: 
    matchlist=range(len(lst1)) 
M=np.matrix([[0,0,0],[0,0,0],[0,0,0]]) 

for i,coord1 in enumerate(lst1): 
    x=np.matrix(np.outer(coord1,lst2[matchlist[i]])) 
    M=M+x 

N11=float(M[0][:,0]+M[1][:,1]+M[2][:,2]) 
N22=float(M[0][:,0]-M[1][:,1]-M[2][:,2]) 
N33=float(-M[0][:,0]+M[1][:,1]-M[2][:,2]) 
N44=float(-M[0][:,0]-M[1][:,1]+M[2][:,2]) 
N12=float(M[1][:,2]-M[2][:,1]) 
N13=float(M[2][:,0]-M[0][:,2]) 
N14=float(M[0][:,1]-M[1][:,0]) 
N21=float(N12) 
N23=float(M[0][:,1]+M[1][:,0]) 
N24=float(M[2][:,0]+M[0][:,2]) 
N31=float(N13) 
N32=float(N23) 
N34=float(M[1][:,2]+M[2][:,1]) 
N41=float(N14) 
N42=float(N24) 
N43=float(N34) 

N=np.matrix([[N11,N12,N13,N14],\ 
       [N21,N22,N23,N24],\ 
       [N31,N32,N33,N34],\ 
       [N41,N42,N43,N44]]) 


values,vectors=np.linalg.eig(N) 
w=list(values) 
mw=max(w) 
quat= vectors[:,w.index(mw)] 
quat=np.array(quat).reshape(-1,).tolist() 
return quat 

यह समारोह चार का समुदाय है कि आप देख रहे थे देता है। तर्क lst1 और lst2 numpy की सूचियां हैं।सरणी जहां हर सरणी एक 3 डी वेक्टर का प्रतिनिधित्व करता है। यदि दोनों सूचियां लंबाई 3 (और ऑर्थोगोनल यूनिट वैक्टर शामिल हैं) हैं, तो quaternion सटीक परिवर्तन होना चाहिए। यदि आप लंबी सूचियां प्रदान करते हैं, तो आपको quaternion मिलता है जो दोनों बिंदु सेटों के बीच अंतर को कम करता है। वैकल्पिक मिलानसूची तर्क का उपयोग फ़ंक्शन को बताने के लिए किया जाता है जो lst2 के बिंदु को lst1 में किस बिंदु पर परिवर्तित किया जाना चाहिए। कोई matchlist प्रदान की जाती है, तो समारोह मानता है कि lst1 में पहला बिंदु lst2 में और बहुत आगे है पहला बिंदु से मेल खाना चाहिए ...

C++ 3 अंक के सेट के लिए एक समान कार्य निम्नलिखित है:

#include <Eigen/Dense> 
#include <Eigen/Geometry> 

using namespace Eigen; 

/// Determine rotation quaternion from coordinate system 1 (vectors 
/// x1, y1, z1) to coordinate system 2 (vectors x2, y2, z2) 
Quaterniond QuaternionRot(Vector3d x1, Vector3d y1, Vector3d z1, 
          Vector3d x2, Vector3d y2, Vector3d z2) { 

    Matrix3d M = x1*x2.transpose() + y1*y2.transpose() + z1*z2.transpose(); 

    Matrix4d N; 
    N << M(0,0)+M(1,1)+M(2,2) ,M(1,2)-M(2,1)   , M(2,0)-M(0,2)   , M(0,1)-M(1,0), 
     M(1,2)-M(2,1)   ,M(0,0)-M(1,1)-M(2,2) , M(0,1)+M(1,0)   , M(2,0)+M(0,2), 
     M(2,0)-M(0,2)   ,M(0,1)+M(1,0)   ,-M(0,0)+M(1,1)-M(2,2) , M(1,2)+M(2,1), 
     M(0,1)-M(1,0)   ,M(2,0)+M(0,2)   , M(1,2)+M(2,1)   ,-M(0,0)-M(1,1)+M(2,2); 

    EigenSolver<Matrix4d> N_es(N); 
    Vector4d::Index maxIndex; 
    N_es.eigenvalues().real().maxCoeff(&maxIndex); 

    Vector4d ev_max = N_es.eigenvectors().col(maxIndex).real(); 

    Quaterniond quat(ev_max(0), ev_max(1), ev_max(2), ev_max(3)); 
    quat.normalize(); 

    return quat; 
} 
+0

बीटीडब्ल्यू, https://scholar.google.com/scholar?q="Method+for+registration+of+3-D+shapes "वेब के चारों ओर बहुत सारी प्रतियां पाता है; दुर्भाग्य से मैंने किसी लेखक की वेबसाइट या ओपन-एक्सेस आर्काइव (जिसे कुछ समय के लिए जगह पर रहने की उम्मीद की जा सकती है) पर अधिकतर नहीं देखा, ज्यादातर पाठ्यक्रम वेबसाइटों पर। – SamB

1

मैं बस इसी समस्या में भाग गया। मैं एक समाधान के लिए ट्रैक पर था, लेकिन मैं अटक गया।

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

इसके साथ, quaternions की धुरी-कोण व्याख्या पर विचार करें, कुछ वेक्टर वी है जिसके बारे में कुछ निर्देशांक से डिवाइस के निर्देशांक को वैश्विक निर्देशांक से मिलान करने के लिए घुमाया जा सकता है। मैं अपने (नकारात्मक) गुरुत्वाकर्षण वेक्टर जी, और चुंबकीय क्षेत्र एम (दोनों सामान्यीकृत) कॉल करेंगे।

वी, जी और एम सभी इकाई क्षेत्र पर अंक का वर्णन करते हैं। तो Z_dev और Y_dev (मेरे डिवाइस के समन्वय प्रणाली के लिए जेड और वाई बेस) करें। लक्ष्य एक घूर्णन ढूंढना है जो जी को Z_dev और M पर Y_dev पर मानचित्र करता है। जी को Z_dev पर घुमाने के लिए वी के लिए जी और वी द्वारा परिभाषित बिंदुओं के बीच की दूरी V और Z_dev द्वारा परिभाषित बिंदुओं के बीच की दूरी के समान होना चाहिए। समीकरणों में:

| वी - जी | = | वी - Z_dev |

इस समीकरण का समाधान एक विमान बनाता है (सभी बिंदु जी और Z_dev के समतुल्य हैं)। लेकिन, वी इकाई-लंबाई होने के लिए बाध्य है, जिसका मतलब है कि समाधान उत्पत्ति पर केंद्रित एक अंगूठी है - अभी भी अंक की एक अनंत संख्या है।

लेकिन, एक ही स्थिति Y_dev, एम और वी का सच है:

| वी - एम | = | वी - वाई_देव |

इसका समाधान मूल पर केंद्रित एक अंगूठी भी है। इन छल्ले में दो चौराहे बिंदु होते हैं, जहां एक दूसरे का नकारात्मक होता है। या तो रोटेशन की वैध धुरी है (घूर्णन का कोण सिर्फ एक मामले में नकारात्मक होगा)।

उपरोक्त दो समीकरणों का उपयोग करना, और तथ्य यह है कि इन वैक्टर की प्रत्येक इकाई लंबाई है आप वी

तो फिर तुम बस से बारी बारी से करने, जो आप होना चाहिए कोण खोजने के लिए के लिए हल करने के लिए सक्षम होना चाहिए वी से आपके संबंधित अड्डों (जी और Z_dev मेरे लिए) में जाने वाले वैक्टरों का उपयोग करने में सक्षम।

आखिरकार, मैं वी के लिए हल करने में बीजगणित के अंत की ओर बढ़ गया .. लेकिन किसी भी तरह से, मुझे लगता है कि आपको जो कुछ चाहिए वह यहां है - शायद आपके पास बेहतर भाग्य होगा।

संबंधित मुद्दे