मोशन सेंसर

Android प्लैटफ़ॉर्म में कई सेंसर होते हैं. इनकी मदद से, किसी डिवाइस की गतिविधि पर नज़र रखी जा सकती है.

सेंसर के संभावित आर्किटेक्चर, सेंसर के टाइप के हिसाब से अलग-अलग होते हैं:

  • गुरुत्वाकर्षण, लीनियर एक्सेलरेशन, रोटेशन वेक्टर, अहम मोशन, कदम काउंटर, और कदम का पता लगाने वाले सेंसर, हार्डवेयर पर आधारित या सॉफ़्टवेयर पर आधारित होते हैं.
  • एक्सलरोमीटर और जाइरोस्कोप सेंसर हमेशा हार्डवेयर पर आधारित होते हैं.

ज़्यादातर Android डिवाइसों में ऐक्सीलेरोमीटर होता है. साथ ही, अब कई डिवाइसों में घुमाव की जानकारी देने वाला गायरोस्कोप भी होता है. सॉफ़्टवेयर पर आधारित सेंसर की उपलब्धता, डिवाइस के हिसाब से अलग-अलग हो सकती है. ऐसा इसलिए, क्योंकि ये सेंसर अक्सर एक या एक से ज़्यादा हार्डवेयर सेंसर से डेटा लेते हैं. डिवाइस के हिसाब से, ये सॉफ़्टवेयर-आधारित सेंसर, अपना डेटा एक्सलरोमीटर और मैग्नेटोमीटर या फिर जाइरोस्कोप से पा सकते हैं.

मोशन सेंसर, डिवाइस की गतिविधि को मॉनिटर करने के लिए काम के होते हैं. जैसे, डिवाइस को झुकाना, हिलाना, घुमाना या स्विंग करना. आम तौर पर, यह मूवमेंट उपयोगकर्ता के सीधे इनपुट से जुड़ा होता है. उदाहरण के लिए, कोई उपयोगकर्ता किसी गेम में कार चला रहा है या गेम में गेंद को कंट्रोल कर रहा है. हालांकि, यह मूवमेंट उस जगह के भौतिक वातावरण से भी जुड़ा हो सकता है जहां डिवाइस मौजूद है. उदाहरण के लिए, कार चलाते समय आपके साथ मूवमेंट करना. पहले मामले में, डिवाइस के फ़्रेम ऑफ़ रेफ़रंस या ऐप्लिकेशन के फ़्रेम ऑफ़ रेफ़रंस के हिसाब से गति को मॉनिटर किया जाता है. वहीं, दूसरे मामले में दुनिया के फ़्रेम ऑफ़ रेफ़रंस के हिसाब से गति को मॉनिटर किया जाता है. आम तौर पर, मोशन सेंसर का इस्तेमाल डिवाइस की जगह की जानकारी को मॉनिटर करने के लिए नहीं किया जाता. हालांकि, दुनिया के फ़्रेम ऑफ़ रेफ़रंस के हिसाब से डिवाइस की जगह की जानकारी तय करने के लिए, इनका इस्तेमाल अन्य सेंसर के साथ किया जा सकता है. जैसे, जियोमैग्नेटिक फ़ील्ड सेंसर. ज़्यादा जानकारी के लिए, जगह की जानकारी देने वाले सेंसर देखें.

सभी मोशन सेंसर, हर SensorEvent के लिए सेंसर वैल्यू के मल्टी-डाइमेंशनल ऐरे दिखाते हैं. उदाहरण के लिए, किसी एक सेंसर इवेंट के दौरान, एक्सलरोमीटर तीन निर्देशांक अक्षों के लिए, ऐक्सेलरेशन फ़ोर्स का डेटा दिखाता है. वहीं, जाइरोस्कोप तीन निर्देशांक अक्षों के लिए, रोटेशन रेट का डेटा दिखाता है. ये डेटा वैल्यू, अन्य SensorEvent पैरामीटर के साथ float कलेक्शन (values) में दिखती हैं. टेबल 1 में, Android प्लैटफ़ॉर्म पर उपलब्ध मोशन सेंसर के बारे में खास जानकारी दी गई है.

टेबल 1. Android प्लैटफ़ॉर्म पर काम करने वाले मोशन सेंसर.

सेंसर सेंसर इवेंट का डेटा ब्यौरा माप की इकाइयां
TYPE_ACCELEROMETER SensorEvent.values[0] एक्स-ऐक्सिस के साथ त्वरण बल (इसमें गुरुत्वाकर्षण भी शामिल है). मीटर/सेकंड2
SensorEvent.values[1] y ऐक्सिस के साथ त्वरण बल (इसमें गुरुत्वाकर्षण भी शामिल है).
SensorEvent.values[2] z-ऐक्सिस के साथ त्वरण बल (इसमें गुरुत्वाकर्षण भी शामिल है).
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] X ऐक्सिस के साथ-साथ, बिना किसी भेदभाव के मेज़र किया गया एक्सेलेरेशन. मीटर/सेकंड2
SensorEvent.values[1] Y ऐक्सिस के साथ मापा गया एक्सेलरेशन, जिसमें किसी भी तरह का भेदभाव नहीं किया गया है.
SensorEvent.values[2] बिना किसी पूर्वाग्रह के, Z ऐक्सिस के साथ मेज़र किया गया एक्सेलरेशन.
SensorEvent.values[3] अनुमानित बायस कंपेंसेशन के साथ, X ऐक्सिस के साथ मेज़र किया गया एक्सेलरेशन.
SensorEvent.values[4] Y ऐक्सिस के साथ-साथ, अनुमानित बायस कंपेंसेशन के साथ मेज़र किया गया एक्सेलरेशन.
SensorEvent.values[5] अनुमानित बायस कंपेंसेशन के साथ, Z ऐक्सिस के साथ मेज़र किया गया एक्सेलरेशन.
TYPE_GRAVITY SensorEvent.values[0] x ऐक्सिस के साथ गुरुत्वाकर्षण का बल. मीटर/सेकंड2
SensorEvent.values[1] y ऐक्सिस के साथ गुरुत्वाकर्षण का बल.
SensorEvent.values[2] z ऐक्सिस के साथ गुरुत्वाकर्षण का बल.
TYPE_GYROSCOPE SensorEvent.values[0] x-ऐक्सिस के चारों ओर घूमने की दर. रेडियन/सेकंड
SensorEvent.values[1] y-ऐक्सिस के आस-पास घूमने की दर.
SensorEvent.values[2] z ऐक्सिस के चारों ओर घूमने की दर.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] x ऐक्सिस के आस-पास रोटेशन की दर (ड्रिफ़्ट कंपेंसेशन के बिना). रेडियन/सेकंड
SensorEvent.values[1] y ऐक्सिस के आस-पास रोटेशन की दर (ड्रिफ़्ट कम्पेंसेशन के बिना).
SensorEvent.values[2] z ऐक्सिस के आस-पास रोटेशन की दर (ड्रिफ़्ट कम्पेंसेशन के बिना).
SensorEvent.values[3] x-ऐक्सिस के आस-पास का अनुमानित ड्रिफ़्ट.
SensorEvent.values[4] y-ऐक्सिस के आस-पास होने वाले ड्रिफ़्ट का अनुमान.
SensorEvent.values[5] z ऐक्सिस के आस-पास ड्रिफ़्ट का अनुमान.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] एक्स ऐक्सिस के साथ त्वरण बल (गुरुत्वाकर्षण को छोड़कर). मीटर/सेकंड2
SensorEvent.values[1] y-ऐक्सिस के साथ त्वरण बल (गुरुत्वाकर्षण को छोड़कर).
SensorEvent.values[2] z-ऐक्सिस के साथ त्वरण बल (गुरुत्वाकर्षण को छोड़कर).
TYPE_ROTATION_VECTOR SensorEvent.values[0] x-ऐक्सिस के साथ रोटेशन वेक्टर कॉम्पोनेंट (x * sin(θ/2)). बिना इकाई वाला
SensorEvent.values[1] y ऐक्सिस के साथ रोटेशन वेक्टर कॉम्पोनेंट (y * sin(θ/2)).
SensorEvent.values[2] z ऐक्सिस के साथ रोटेशन वेक्टर कॉम्पोनेंट (z * sin(θ/2)).
SensorEvent.values[3] रोटेशन वेक्टर का स्केलर कॉम्पोनेंट ((cos(θ/2)).1
TYPE_SIGNIFICANT_MOTION लागू नहीं लागू नहीं लागू नहीं
TYPE_STEP_COUNTER SensorEvent.values[0] सेंसर चालू होने के दौरान, डिवाइस को पिछली बार रीबूट करने के बाद से उपयोगकर्ता के चले गए कदमों की संख्या. तरीका
TYPE_STEP_DETECTOR लागू नहीं लागू नहीं लागू नहीं

1 स्केलर कॉम्पोनेंट की वैल्यू देना ज़रूरी नहीं है.

मोशन का पता लगाने और निगरानी करने के लिए, रोटेशन वेक्टर सेंसर और गुरुत्वाकर्षण सेंसर का सबसे ज़्यादा इस्तेमाल किया जाता है. रोटेशनल वेक्टर सेंसर का इस्तेमाल, मोशन से जुड़े कई कामों के लिए किया जा सकता है. जैसे, जेस्चर का पता लगाना, ऐंगल में हुए बदलाव को मॉनिटर करना, और रिलेटिव ओरिएंटेशन में हुए बदलावों को मॉनिटर करना. उदाहरण के लिए, अगर आपको कोई गेम, ऑगमेंटेड रिएलिटी ऐप्लिकेशन, दो या तीन डाइमेंशन वाला कंपास या कैमरे को स्थिर रखने वाला ऐप्लिकेशन बनाना है, तो रोटेशन वेक्टर सेंसर का इस्तेमाल करना सबसे सही रहेगा. ज़्यादातर मामलों में, ऐक्सीलेरोमीटर और जियोमैग्नेटिक फ़ील्ड सेंसर या ओरिएंटेशन सेंसर का इस्तेमाल करने के बजाय, इन सेंसर का इस्तेमाल करना बेहतर होता है.

Android Open Source Project के सेंसर

Android Open Source Project (AOSP), सॉफ़्टवेयर पर आधारित तीन मोशन सेंसर उपलब्ध कराता है: गुरुत्वाकर्षण सेंसर, लीनियर ऐक्सेलरेशन सेंसर, और रोटेशन वेक्टर सेंसर. इन सेंसर को Android 4.0 में अपडेट किया गया था. अब ये डिवाइस के अन्य सेंसर के साथ-साथ, उसके गायरोस्कोप का इस्तेमाल करके, डिवाइस के काम करने के तरीके और परफ़ॉर्मेंस को बेहतर बनाते हैं. अगर आपको इन सेंसर को आज़माना है, तो getVendor() और getVersion() तरीके का इस्तेमाल करके उनकी पहचान की जा सकती है. (वेंडर Google LLC है और वर्शन नंबर 3 है). वेंडर और वर्शन नंबर के हिसाब से इन सेंसर की पहचान करना ज़रूरी है, क्योंकि Android सिस्टम इन तीन सेंसर को सेकंडरी सेंसर मानता है. उदाहरण के लिए, अगर डिवाइस मैन्युफ़ैक्चरर अपना गुरुत्वाकर्षण सेंसर उपलब्ध कराता है, तो AOSP गुरुत्वाकर्षण सेंसर, सेकंडरी गुरुत्वाकर्षण सेंसर के तौर पर दिखता है. ये तीनों सेंसर, घुमाव-घुमाव की जानकारी देने वाले डिवाइस (जाइरोस्कोप) पर निर्भर करते हैं: अगर किसी डिवाइस में जायरोस्कोप नहीं है, तो ये सेंसर नहीं दिखते और इस्तेमाल के लिए उपलब्ध नहीं होते.

गुरुत्वाकर्षण सेंसर का इस्तेमाल करना

गुरुत्वाकर्षण सेंसर, गुरुत्वाकर्षण की दिशा और तीव्रता का पता लगाने वाला तीन डाइमेंशन वाला वेक्टर उपलब्ध कराता है. आम तौर पर, इस सेंसर का इस्तेमाल, डिवाइस के स्पेस में मौजूद होने की स्थिति का पता लगाने के लिए किया जाता है. यहां दिए गए कोड में, डिफ़ॉल्ट गुरुत्वाकर्षण सेंसर का उदाहरण पाने का तरीका बताया गया है:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);

इन इकाइयों का इस्तेमाल, ऐक्सेलरेशन सेंसर (m/s2) में भी किया जाता है. साथ ही, इनमें इस्तेमाल किया गया कोऑर्डिनेट सिस्टम भी वही है जो ऐक्सेलरेशन सेंसर में इस्तेमाल किया जाता है.

ध्यान दें: जब कोई डिवाइस एक ही जगह पर होता है, तो गुरुत्वाकर्षण सेंसर का आउटपुट, एक्सलरोमीटर के आउटपुट से मेल खाना चाहिए.

लीनियर ऐक्सीलरॉमीटर का इस्तेमाल करना

लीनियर ऐक्सेलरेशन सेंसर, आपको तीन डाइमेंशन वाला वेक्टर दिखाता है. इसमें डिवाइस के हर ऐक्सिस के साथ-साथ गुरुत्वाकर्षण की वजह से होने वाला त्वरण भी शामिल होता है. जेस्चर की पहचान करने के लिए, इस वैल्यू का इस्तेमाल किया जा सकता है. इस वैल्यू का इस्तेमाल, इनर्शियल नेविगेशन सिस्टम के इनपुट के तौर पर भी किया जा सकता है. यह सिस्टम डेड रेकिंग का इस्तेमाल करता है. नीचे दिए गए कोड में, डिफ़ॉल्ट लीनियर ऐक्सेलरेशन सेंसर का इंस्टेंस पाने का तरीका बताया गया है:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);

इस सेंसर से, आपको नीचे दिए गए संबंध के हिसाब से, ऐक्सेलरेशन डेटा मिलता है:

linear acceleration = acceleration - acceleration due to gravity

आम तौर पर, इस सेंसर का इस्तेमाल तब किया जाता है, जब आपको गुरुत्वाकर्षण के असर के बिना, ऐक्सेलरेशन का डेटा चाहिए. उदाहरण के लिए, इस सेंसर का इस्तेमाल करके यह देखा जा सकता है कि आपकी कार कितनी तेज़ी से चल रही है. लीनियर ऐक्सेलरेशन सेंसर में हमेशा एक ऑफ़सेट होता है, जिसे आपको हटाना होगा. ऐसा करने का सबसे आसान तरीका है कि आप अपने ऐप्लिकेशन में कैलिब्रेशन का चरण जोड़ें. कैलिब्रेशन के दौरान, उपयोगकर्ता से डिवाइस को टेबल पर सेट करने के लिए कहा जा सकता है. इसके बाद, तीनों अक्षों के लिए ऑफ़सेट पढ़े जा सकते हैं. इसके बाद, असल लीनियर ऐक्सेलरेशन पाने के लिए, उस ऑफ़सेट को ऐक्सेलरेशन सेंसर की डायरेक्ट रीडिंग से घटाया जा सकता है.

सेंसर कोऑर्डिनेट सिस्टम और एक्सलरोमीटर का इस्तेमाल करने वाला सिस्टम एक ही होता है. साथ ही, दोनों की माप की इकाइयां भी एक ही होती हैं (m/s2).

रोटेशन वेक्टर सेंसर का इस्तेमाल करना

रोटेशन वेक्टर, डिवाइस के ओरिएंटेशन को कोण और अक्ष के कॉम्बिनेशन के तौर पर दिखाता है. इसमें डिवाइस को किसी अक्ष (x, y या z) के चारों ओर कोण θ के ज़रिए घुमाया गया है. नीचे दिए गए कोड में, डिफ़ॉल्ट रोटेशन वेक्टर सेंसर का इंस्टेंस पाने का तरीका बताया गया है:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);

रोटेशन वेक्टर के तीन एलिमेंट को इस तरह दिखाया जाता है:

x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)

यहां रोटेशन वेक्टर का मैग्नीट्यूड, sin(θ/2) के बराबर होता है और रोटेशन वेक्टर की दिशा, रोटेशन ऐक्सिस की दिशा के बराबर होती है.

पहली इमेज. रोटेशन वेक्टर सेंसर का इस्तेमाल करने वाला कोऑर्डिनेट सिस्टम.

रोटेशन वेक्टर के तीन एलिमेंट, यूनिट क्वेटरनियन (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)) के आखिरी तीन कॉम्पोनेंट के बराबर होते हैं. रोटेशन वेक्टर के एलिमेंट में यूनिट नहीं होती. एक्स, वाई, और ज़ेड ऐक्सिस को उसी तरह से तय किया जाता है जिस तरह से एक्सलरेटर सेंसर को तय किया जाता है. रेफ़रंस कोऑर्डिनेट सिस्टम को डायरेक्ट ऑर्थोनॉर्मल बेसिस के तौर पर परिभाषित किया गया है (पहली इमेज देखें). इस निर्देशांक प्रणाली की ये विशेषताएं हैं:

  • X को Y x Z के सदिश गुणनफल के तौर पर परिभाषित किया गया है. यह डिवाइस की मौजूदा जगह पर, ज़मीन के साथ टेंजेंशियल होता है और यह पूर्व की ओर दिखता है.
  • Y, डिवाइस की मौजूदा जगह पर जमीन के स्पर्शरेखा के बराबर होता है और यह भू-चुंबकीय उत्तरी ध्रुव की ओर इशारा करता है.
  • Z, आसमान की ओर इशारा करता है और यह ग्राउंड प्लेन के लिए परपेंडिकुलर होता है.

रोटेशन वेक्टर सेंसर का इस्तेमाल करने का तरीका बताने वाले सैंपल ऐप्लिकेशन के लिए, RotationVectorDemo.java देखें.

बेहतर मोशन सेंसर का इस्तेमाल करना

जब भी कोई ज़रूरी गतिविधि का पता चलता है, तो ज़रूरी मोशन सेंसर एक इवेंट को ट्रिगर करता है और फिर अपने-आप बंद हो जाता है. ज़्यादा गतिविधि का मतलब है कि उपयोगकर्ता की जगह में बदलाव हो सकता है. जैसे, पैदल चलना, साइकल चलाना या चलती हुई कार में बैठना. यहां दिए गए कोड में, डिफ़ॉल्ट ज़रूरी मोशन सेंसर का इंस्टेंस पाने और इवेंट लिसनर को रजिस्टर करने का तरीका बताया गया है:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val mSensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION)
val triggerEventListener = object : TriggerEventListener() {
    override fun onTrigger(event: TriggerEvent?) {
        // Do work
    }
}
mSensor?.also { sensor ->
    sensorManager.requestTriggerSensor(triggerEventListener, sensor)
}

Java

private SensorManager sensorManager;
private Sensor sensor;
private TriggerEventListener triggerEventListener;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);

triggerEventListener = new TriggerEventListener() {
    @Override
    public void onTrigger(TriggerEvent event) {
        // Do work
    }
};

sensorManager.requestTriggerSensor(triggerEventListener, mSensor);

ज़्यादा जानकारी के लिए, TriggerEventListener देखें.

कदमों की गिनती करने वाले सेंसर का इस्तेमाल करना

सेंसर चालू होने के दौरान, पिछले रीबूट के बाद से उपयोगकर्ता ने जितने कदम चले हैं उनकी संख्या, कदमों की गिनती करने वाला सेंसर दिखाता है. कदमों की गिनती करने वाले सेंसर की तुलना में, कदमों की गिनती करने वाले काउंटर में ज़्यादा देरी (10 सेकंड तक) होती है. हालांकि, यह सेंसर ज़्यादा सटीक होता है.

ध्यान दें: Android 10 (एपीआई लेवल 29) या उसके बाद के वर्शन पर चलने वाले डिवाइसों पर, आपके ऐप्लिकेशन को इस सेंसर का इस्तेमाल करने के लिए, आपको ACTIVITY_RECOGNITION अनुमति का एलान करना होगा.

यहां दिए गए कोड में, डिफ़ॉल्ट गतिविधि काउंटर सेंसर का इंस्टेंस पाने का तरीका बताया गया है:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);

आपके ऐप्लिकेशन को चलाने वाले डिवाइसों की बैटरी बचाने के लिए, आपको JobScheduler क्लास का इस्तेमाल करना चाहिए. इससे, किसी तय इंटरवल पर, कदमों की गिनती करने वाले सेंसर से मौजूदा वैल्यू को वापस पाया जा सकता है. अलग-अलग तरह के ऐप्लिकेशन के लिए, सेंसर से डेटा पढ़ने के इंटरवल अलग-अलग होते हैं. हालांकि, आपको इस इंटरवल को ज़्यादा से ज़्यादा लंबा रखना चाहिए. ऐसा तब तक करें, जब तक आपके ऐप्लिकेशन को सेंसर से रीयल-टाइम डेटा की ज़रूरत न हो.

कदमों की गिनती करने वाले सेंसर का इस्तेमाल करना

जब भी उपयोगकर्ता एक कदम आगे बढ़ता है, तब कदम का पता लगाने वाला सेंसर एक इवेंट ट्रिगर करता है. वीडियो स्ट्रीम होने और उसके दिखने के समय का अंतर, दो सेकंड से कम होना चाहिए.

ध्यान दें: Android 10 (एपीआई लेवल 29) या उसके बाद के वर्शन पर चलने वाले डिवाइसों पर, आपके ऐप्लिकेशन को इस सेंसर का इस्तेमाल करने के लिए, आपको ACTIVITY_RECOGNITION अनुमति का एलान करना होगा.

यहां दिए गए कोड में, डिफ़ॉल्ट गतिविधि डिटेक्टर सेंसर का इंस्टेंस पाने का तरीका बताया गया है:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);

रॉ डेटा के साथ काम करना

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

ऐक्सीलरॉमीटर का इस्तेमाल करना

ऐक्सेलरेशन सेंसर, डिवाइस पर होने वाले ऐक्सेलरेशन को मेज़र करता है. इसमें गुरुत्वाकर्षण का फ़ोर्स भी शामिल है. नीचे दिए गए कोड में, डिफ़ॉल्ट एक्सेलेरेशन सेंसर का इंस्टेंस पाने का तरीका बताया गया है:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

Java

private SensorManager sensorManager;
private Sensor sensor;
  ...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

ध्यान दें: अगर आपका ऐप्लिकेशन Android 12 (एपीआई लेवल 31) या उससे बाद के वर्शन को टारगेट करता है, तो इस सेंसर की गति सीमित होती है.

कॉन्सेप्ट के हिसाब से, किसी डिवाइस (Ad) पर लगने वाले ऐक्सेलरेशन का पता लगाने के लिए, ऐक्सेलरेशन सेंसर, सेंसर पर लगने वाले फ़ोर्स (Fs) को मेज़र करता है. इसके लिए, यह संबंध इस्तेमाल किया जाता है:

A_D=-(1/mass)∑F_S

हालांकि, गुरुत्वाकर्षण का फ़ोर्स, मापे गए त्वरण पर हमेशा असर डालता है. यह असर, नीचे दिए गए संबंध के हिसाब से होता है:

A_D=-g-(1/mass)∑F_S

इस वजह से, जब डिवाइस किसी टेबल पर होता है और उसकी गति में कोई बदलाव नहीं होता, तो ऐक्सेलेरोमीटर g = 9.81 m/s2 का मैग्नीट्यूड पढ़ता है. इसी तरह, जब डिवाइस ज़मीन पर गिर रहा हो और इसलिए 9.81 मीटर/सेकंड2 की रफ़्तार से ज़मीन की ओर तेज़ी से बढ़ रहा हो, तो उसका ऐक्सेलेरोमीटर g = 0 मीटर/सेकंड2 की माप दिखाता है. इसलिए, डिवाइस के असल एक्सेलरेशन को मेज़र करने के लिए, एक्सलरोमीटर डेटा से गुरुत्वाकर्षण के फ़ंक्शन को हटाना ज़रूरी है. ऐसा करने के लिए, हाई-पास फ़िल्टर लागू करें. इसके उलट, गुरुत्वाकर्षण के फ़ोर्स को अलग करने के लिए, लो-पास फ़िल्टर का इस्तेमाल किया जा सकता है. नीचे दिए गए उदाहरण में, ऐसा करने का तरीका बताया गया है:

Kotlin

override fun onSensorChanged(event: SensorEvent) {
    // In this example, alpha is calculated as t / (t + dT),
    // where t is the low-pass filter's time-constant and
    // dT is the event delivery rate.

    val alpha: Float = 0.8f

    // Isolate the force of gravity with the low-pass filter.
    gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]
    gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]
    gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]

    // Remove the gravity contribution with the high-pass filter.
    linear_acceleration[0] = event.values[0] - gravity[0]
    linear_acceleration[1] = event.values[1] - gravity[1]
    linear_acceleration[2] = event.values[2] - gravity[2]
}

Java

public void onSensorChanged(SensorEvent event){
    // In this example, alpha is calculated as t / (t + dT),
    // where t is the low-pass filter's time-constant and
    // dT is the event delivery rate.

    final float alpha = 0.8;

    // Isolate the force of gravity with the low-pass filter.
    gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
    gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
    gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];

    // Remove the gravity contribution with the high-pass filter.
    linear_acceleration[0] = event.values[0] - gravity[0];
    linear_acceleration[1] = event.values[1] - gravity[1];
    linear_acceleration[2] = event.values[2] - gravity[2];
}

ध्यान दें: सेंसर डेटा को फ़िल्टर करने के लिए, कई अलग-अलग तरीकों का इस्तेमाल किया जा सकता है. ऊपर दिया गया कोड सैंपल, लो-पास फ़िल्टर बनाने के लिए, फ़िल्टर के एक आसान कॉन्स्टेंट (अल्फा) का इस्तेमाल करता है. यह फ़िल्टर कॉन्स्टेंट, टाइम कॉन्स्टेंट (t) से लिया जाता है. यह उस लैटेंसी का अनुमानित डेटा होता है जो फ़िल्टर, सेंसर इवेंट में जोड़ता है. साथ ही, यह सेंसर के इवेंट डिलीवरी रेट (dt) का भी डेटा होता है. कोड सैंपल में, डेमो के मकसद से 0.8 की अल्फा वैल्यू का इस्तेमाल किया गया है. फ़िल्टर करने के इस तरीके का इस्तेमाल करने पर, आपको कोई दूसरी अल्फा वैल्यू चुननी पड़ सकती है.

ऐक्सेलेरोमीटर, स्टैंडर्ड सेंसर कोऑर्डिनेट सिस्टम का इस्तेमाल करते हैं. इसका मतलब है कि जब कोई डिवाइस टेबल पर अपने सामान्य ओरिएंटेशन में, सपाट हो, तो ये शर्तें लागू होती हैं:

  • अगर डिवाइस को बाईं ओर दबाया जाता है, ताकि वह दाईं ओर मुड़े, तो एक्स एक्सेलेरेशन की वैल्यू सकारात्मक होती है.
  • अगर डिवाइस को नीचे की ओर धकेला जाता है, ताकि वह आपसे दूर हो जाए, तो y ऐक्सेलरेशन वैल्यू सकारात्मक होती है.
  • अगर डिवाइस को A मीटर/सेकंड2 के त्वरण के साथ आसमान की ओर धकेला जाता है, तो z-ऐक्सिस के त्वरण की वैल्यू A + 9.81 के बराबर होती है. यह वैल्यू, डिवाइस के त्वरण (+A मीटर/सेकंड2) में गुरुत्वाकर्षण के बल (-9.81 मीटर/सेकंड2) को घटाने पर मिलती है.
  • स्टैशनरी डिवाइस की त्वरण वैल्यू +9.81 होगी. यह वैल्यू, डिवाइस के त्वरण से मेल खाती है. त्वरण वैल्यू, 0 मीटर/सेकंड2 में गुरुत्वाकर्षण बल (-9.81 मीटर/सेकंड2) को घटाने पर मिलती है.

आम तौर पर, अगर आपको डिवाइस की गति पर नज़र रखनी है, तो एक्सलरोमीटर एक अच्छा सेंसर है. Android वाले ज़्यादातर हैंडसेट और टैबलेट में ऐक्सीलेरोमीटर होता है. यह अन्य मोशन सेंसर की तुलना में, करीब 10 गुना कम बैटरी इस्तेमाल करता है. इसकी एक समस्या यह है कि गुरुत्वाकर्षण के फ़ोर्स को खत्म करने और शोर को कम करने के लिए, आपको कम पास और हाई पास फ़िल्टर लागू करने पड़ सकते हैं.

जाइरोस्कोप का इस्तेमाल करना

जीरोस्कोप, डिवाइस के x, y, और z ऐक्सिस के चारों ओर घूमने की दर को रेडियन प्रति सेकंड (rad/s) में मेज़र करता है. यहां दिए गए कोड से, डिफ़ॉल्ट गायरोस्कोप का इंस्टेंस पाने का तरीका पता चलता है:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

ध्यान दें: अगर आपका ऐप्लिकेशन Android 12 (एपीआई लेवल 31) या उससे बाद के वर्शन को टारगेट करता है, तो इस सेंसर की गति सीमित होती है.

सेंसर का कोऑर्डिनेट सिस्टम वही होता है जो एक्सलरोमीटर सेंसर के लिए इस्तेमाल किया जाता है. घुमाव की दिशा, ऐन्टी-क्लाइकवाइज़ होती है. इसका मतलब है कि अगर कोई व्यक्ति, ऑरिजिन पर मौजूद किसी डिवाइस को x, y या z ऐक्सिस पर किसी पोज़िटिव जगह से देखता है और डिवाइस ऐन्टी-क्लाइकवाइज़ घूमता हुआ दिखता है, तो वह व्यक्ति डिवाइस के घूमने की दिशा को पोज़िटिव बताएगा. यह, ऐंगल के बढ़ने की गणितीय परिभाषा है. यह ऑरियंटेशन सेंसर के इस्तेमाल किए गए रोल की परिभाषा से अलग है.

आम तौर पर, रोटेशन का हिसाब लगाने के लिए, समय के साथ-साथ जीरोस्कोप के आउटपुट को इंटिग्रेट किया जाता है. इससे, टाइमस्टेप के दौरान ऐंगल में हुए बदलाव का पता चलता है. उदाहरण के लिए:

Kotlin

// Create a constant to convert nanoseconds to seconds.
private val NS2S = 1.0f / 1000000000.0f
private val deltaRotationVector = FloatArray(4) { 0f }
private var timestamp: Float = 0f

override fun onSensorChanged(event: SensorEvent?) {
    // This timestep's delta rotation to be multiplied by the current rotation
    // after computing it from the gyro sample data.
    if (timestamp != 0f && event != null) {
        val dT = (event.timestamp - timestamp) * NS2S
        // Axis of the rotation sample, not normalized yet.
        var axisX: Float = event.values[0]
        var axisY: Float = event.values[1]
        var axisZ: Float = event.values[2]

        // Calculate the angular speed of the sample
        val omegaMagnitude: Float = sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ)

        // Normalize the rotation vector if it's big enough to get the axis
        // (that is, EPSILON should represent your maximum allowable margin of error)
        if (omegaMagnitude > EPSILON) {
            axisX /= omegaMagnitude
            axisY /= omegaMagnitude
            axisZ /= omegaMagnitude
        }

        // Integrate around this axis with the angular speed by the timestep
        // in order to get a delta rotation from this sample over the timestep
        // We will convert this axis-angle representation of the delta rotation
        // into a quaternion before turning it into the rotation matrix.
        val thetaOverTwo: Float = omegaMagnitude * dT / 2.0f
        val sinThetaOverTwo: Float = sin(thetaOverTwo)
        val cosThetaOverTwo: Float = cos(thetaOverTwo)
        deltaRotationVector[0] = sinThetaOverTwo * axisX
        deltaRotationVector[1] = sinThetaOverTwo * axisY
        deltaRotationVector[2] = sinThetaOverTwo * axisZ
        deltaRotationVector[3] = cosThetaOverTwo
    }
    timestamp = event?.timestamp?.toFloat() ?: 0f
    val deltaRotationMatrix = FloatArray(9) { 0f }
    SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
    // User code should concatenate the delta rotation we computed with the current rotation
    // in order to get the updated rotation.
    // rotationCurrent = rotationCurrent * deltaRotationMatrix;
}

Java

// Create a constant to convert nanoseconds to seconds.
private static final float NS2S = 1.0f / 1000000000.0f;
private final float[] deltaRotationVector = new float[4]();
private float timestamp;

public void onSensorChanged(SensorEvent event) {
    // This timestep's delta rotation to be multiplied by the current rotation
    // after computing it from the gyro sample data.
    if (timestamp != 0) {
      final float dT = (event.timestamp - timestamp) * NS2S;
      // Axis of the rotation sample, not normalized yet.
      float axisX = event.values[0];
      float axisY = event.values[1];
      float axisZ = event.values[2];

      // Calculate the angular speed of the sample
      float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);

      // Normalize the rotation vector if it's big enough to get the axis
      // (that is, EPSILON should represent your maximum allowable margin of error)
      if (omegaMagnitude > EPSILON) {
        axisX /= omegaMagnitude;
        axisY /= omegaMagnitude;
        axisZ /= omegaMagnitude;
      }

      // Integrate around this axis with the angular speed by the timestep
      // in order to get a delta rotation from this sample over the timestep
      // We will convert this axis-angle representation of the delta rotation
      // into a quaternion before turning it into the rotation matrix.
      float thetaOverTwo = omegaMagnitude * dT / 2.0f;
      float sinThetaOverTwo = sin(thetaOverTwo);
      float cosThetaOverTwo = cos(thetaOverTwo);
      deltaRotationVector[0] = sinThetaOverTwo * axisX;
      deltaRotationVector[1] = sinThetaOverTwo * axisY;
      deltaRotationVector[2] = sinThetaOverTwo * axisZ;
      deltaRotationVector[3] = cosThetaOverTwo;
    }
    timestamp = event.timestamp;
    float[] deltaRotationMatrix = new float[9];
    SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
    // User code should concatenate the delta rotation we computed with the current rotation
    // in order to get the updated rotation.
    // rotationCurrent = rotationCurrent * deltaRotationMatrix;
}

स्टैंडर्ड गायरोस्कोप, बिना किसी फ़िल्टर या गड़बड़ी और ड्रिफ़्ट (बायस) के रोटेशन का रॉ डेटा देते हैं. असल में, गायरोसकोप के नॉइज़ और ड्रिफ़्ट की वजह से गड़बड़ियां होंगी. इन गड़बड़ियों को ठीक करना ज़रूरी है. आम तौर पर, गुरुत्वाकर्षण सेंसर या एक्सलरोमीटर जैसे दूसरे सेंसर की निगरानी करके, ड्रिफ़्ट (बायस) और नॉइज़ का पता लगाया जाता है.

कैलिब्रेट नहीं किए गए जाइरोस्कोप का इस्तेमाल करना

कैलिब्रेट नहीं किया गया जाइरोस्कोप, जाइरोस्कोप जैसा ही होता है. हालांकि, इसमें रोटेशन की दर पर कोई जाइरो-ड्रिफ़्ट कॉम्पेंसेशन लागू नहीं होता. फ़ैक्ट्री कैलिब्रेशन और तापमान में बदलाव की वजह से होने वाले बदलाव को अब भी रोटेशन की दर पर लागू किया जाता है. बिना कैलिब्रेट किए गए घिरौंडे का इस्तेमाल, पोस्ट-प्रोसेसिंग और ओरिएंटेशन डेटा को मर्ज करने के लिए किया जाता है. आम तौर पर, gyroscope_event.values[0] का मतलब uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3] से होगा. इसका मतलब है कि,

calibrated_x ~= uncalibrated_x - bias_estimate_x

ध्यान दें: कैलिब्रेट नहीं किए गए सेंसर, ज़्यादा रॉ नतीजे देते हैं और इनमें कुछ गड़बड़ी हो सकती है. हालांकि, कैलिब्रेशन की मदद से किए गए सुधारों की वजह से, इनके मेज़रमेंट में कम उतार-चढ़ाव होते हैं. कुछ ऐप्लिकेशन, कैलिब्रेट नहीं किए गए इन नतीजों को ज़्यादा भरोसेमंद और बेहतर मान सकते हैं. उदाहरण के लिए, अगर कोई ऐप्लिकेशन अपने सेंसर फ़्यूज़न को पूरा करने की कोशिश कर रहा है, तो कैलिब्रेशन की सुविधा जोड़ने से नतीजों में गड़बड़ी हो सकती है.

रोटेशन की दरों के अलावा, कैलिब्रेट नहीं किया गया गायरोस्कोप, हर अक्ष के आस-पास अनुमानित ड्रिफ़्ट भी देता है. यहां दिए गए कोड से, डिफ़ॉल्ट रूप से मौजूद और कैलिब्रेट नहीं किए गए जीरोस्कोप का इंस्टेंस पाने का तरीका पता चलता है:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);

अन्य कोड सैंपल

BatchStepSensor सैंपल में, इस पेज पर बताए गए एपीआई के इस्तेमाल के बारे में ज़्यादा जानकारी दी गई है.

आपको यह लेख भी पढ़ना चाहिए