2012-06-24 24 views
20

में एक्सेलेरोमीटर का उपयोग कर एक्सवाई प्लेन में फोन के झुकाव को मापने के लिए कैसे मैंने सेंसरएवेंट.वैल्यूज़ से जेड अक्ष डेटा का उपयोग करने की कोशिश की, लेकिन यह एक्सवाई विमान में यानी मेरे फोन के घूर्णन का पता नहीं लगाता है। जेड-अक्ष के आसपास।एंड्रॉइड

मैं इसे समन्वय अक्ष के संदर्भ के रूप में उपयोग कर रहा हूं। क्या यह सही है?

axes

मैं कैसे को मापने कि accelerometer मानों का उपयोग गति करते हैं?

ये गेम कुछ समान करते हैं: Extreme Skater, डूडल जंप।

पीएस: मेरा फोन अभिविन्यास परिदृश्य होगा।

उत्तर

56

अनिवार्य रूप से, यहां 2 मामले हैं: डिवाइस फ्लैट बिछा रहा है और फ्लैट नहीं है। यहां फ्लैट का मतलब है कि डिवाइस स्क्रीन की सतह और विश्व एक्सई प्लेन (मैं इसे झुकाव कहता हूं) के बीच कोण 25 डिग्री से कम या 155 डिग्री से बड़ा है। फोन को फ्लैट से झूठ बोलने या टेबल से थोड़ा सा झुकाव के बारे में सोचें।

सबसे पहले आपको एक्सीलरोमीटर वेक्टर को सामान्य करने की आवश्यकता है।
यह है कि जी एक्सेलेरोमीटर सेंसर ईवेंट मानों द्वारा वेक्टर रिटर्न है। कोड में

float[] g = new float[3]; 
g = event.values.clone(); 

double norm_Of_g = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2]); 

// Normalize the accelerometer vector 
g[0] = g[0]/norm_Of_g 
g[1] = g[1]/norm_Of_g 
g[2] = g[2]/norm_Of_g 

फिर झुकाव के रूप में

int inclination = (int) Math.round(Math.toDegrees(Math.acos(g[2]))); 
इस प्रकार

if (inclination < 25 || inclination > 155) 
{ 
    // device is flat 
} 
else 
{ 
    // device is not flat 
} 

गणना की जा सकती फ्लैट बिछाने के मामले के लिए, आप एक कम्पास का उपयोग करने के लिए कितना डिवाइस को देखने के लिए शुरुआती स्थिति से घूर्णन कर रहा है।

फ्लैट नहीं होने की स्थिति के लिए, रोटेशन (झुकाव) के रूप में पालन

int rotation = (int) Math.round(Math.toDegrees(Math.atan2(g[0], g[1]))); 

अब रोटेशन = 0 का मतलब डिवाइस सामान्य स्थिति में है गणना की जाती है। यह अधिकांश फोन के लिए किसी भी झुकाव के बिना चित्र और शायद टैबलेट के लिए परिदृश्य है। तो यदि आप ऊपर अपनी तस्वीर में फोन रखते हैं और घूर्णन शुरू करते हैं, तो रोटेशन बदल जाएगा और जब फोन परिदृश्य में होगा तो रोटेशन 90 या -90 होगा रोटेशन की दिशा पर निर्भर करता है।

+4

शानदार! आम तौर पर लोग इस कार्य के लिए सेंसर.TYPE_MAGNETIC_FIELD का उपयोग करने का सुझाव देते हैं, हालांकि आपने समाधान को सरल बना दिया है; और जिस तरह एक्सेलेरोमीटर एकमात्र सेंसर है जो एंड्रॉइड पर मौजूद होने की गारंटी देता है। – southerton

+1

क्या मैं आपसे पूछ सकता हूं कि "एसी वेक्टर के सामान्यीकरण" के पीछे गणित क्या है? और डिग्री प्राप्त करने के लिए आप एटान (जी [1]/जी [0]) (या एटन (वाई/एक्स)) क्यों करते हैं? ? @Hoan Nguyen –

+0

@AndreaBaccega मैं भूल गया कि मुझे सामान्यीकृत करने की आवश्यकता क्यों है या बिल्कुल कोई ज़रूरत नहीं है, बस कुछ और चीज़ के लिए मुझे कुछ करने की ज़रूरत है। एटान (वाई/एक्स) बस सरल त्रिकोणमितीय गणना है। घूर्णन को खोजने के लिए, सबसे पहले आपको xy विमान में गुरुत्वाकर्षण प्रोजेक्ट करने की आवश्यकता है। अब अगर कोई रोटेशन नहीं है तो इस प्रोजेक्शन वेक्टर में समन्वय होगा (0,1) (सामान्यीकरण मानना)। यदि डिवाइस घुमाया गया है, तो यह वेक्टर समान है लेकिन निर्देशांक बदलते हैं और इस वेक्टर और डिवाइस वाई-समन्वय के बीच कोण केवल तन (वाई/एक्स) है। –

0

accelerometer जाँच के रूप में होन बहुत अच्छी तरह से प्रदर्शन किया फोन फ्लैट है अगर के लिए पर्याप्त है।

यहां आने वाले किसी भी व्यक्ति के लिए यह देखने के लिए कि फोन क्यों फ्लैट है, लेकिन फोन का घूर्णन क्या है, इसे Rotation Vector Motion Sensor के माध्यम से हासिल किया जा सकता है।

private double pitch, tilt, azimuth; 

@Override 
public void onSensorChanged(SensorEvent event) { 
    //Get Rotation Vector Sensor Values 
    double[] g = convertFloatsToDoubles(event.values.clone()); 

    //Normalise 
    double norm = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2] + g[3] * g[3]); 
    g[0] /= norm; 
    g[1] /= norm; 
    g[2] /= norm; 
    g[3] /= norm; 

    //Set values to commonly known quaternion letter representatives 
    double x = g[0]; 
    double y = g[1]; 
    double z = g[2]; 
    double w = g[3]; 

    //Calculate Pitch in degrees (-180 to 180) 
    double sinP = 2.0 * (w * x + y * z); 
    double cosP = 1.0 - 2.0 * (x * x + y * y); 
    pitch = Math.atan2(sinP, cosP) * (180/Math.PI); 

    //Calculate Tilt in degrees (-90 to 90) 
    double sinT = 2.0 * (w * y - z * x); 
    if (Math.abs(sinT) >= 1) 
     tilt = Math.copySign(Math.PI/2, sinT) * (180/Math.PI); 
    else 
     tilt = Math.asin(sinT) * (180/Math.PI); 

    //Calculate Azimuth in degrees (0 to 360; 0 = North, 90 = East, 180 = South, 270 = West) 
    double sinA = 2.0 * (w * z + x * y); 
    double cosA = 1.0 - 2.0 * (y * y + z * z); 
    azimuth = Math.atan2(sinA, cosA) * (180/Math.PI); 
} 

private double[] convertFloatsToDoubles(float[] input) 
{ 
    if (input == null) 
     return null; 

    double[] output = new double[input.length]; 

    for (int i = 0; i < input.length; i++) 
     output[i] = input[i]; 

    return output; 
} 

फिर फोन फ्लैट है अगर आप बस एक सहिष्णुता मूल्यों के साथ tilt और pitch मूल्यों की तुलना कर सकते हैं की जाँच करने के। उदाहरण

public boolean flatEnough(double degreeTolerance) { 
    return tilt <= degreeTolerance && tilt >= -degreeTolerance && pitch <= degreeTolerance && pitch >= -degreeTolerance; 
} 

लाभ कर के लिए इस तरह से फोन किसी भी विशिष्ट रोटेशन में आयोजित किया जा रहा है अगर आप जाँच कर सकते हैं।

यह ध्यान देने योग्य है कि ऐप का अभिविन्यास पिच, झुकाव और अजीमुथ के मूल्यों को प्रभावित नहीं करेगा।