मोशन सेंसर

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

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

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

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

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

सभी मोशन सेंसर, हर SensorEvent के लिए सेंसर वैल्यू के कई डाइमेंशन वाले सरणियों को दिखाते हैं. उदाहरण के लिए, किसी एक सेंसर इवेंट के दौरान, एक्सलरोमीटर तीन निर्देशांक अक्षों के लिए, त्वरण बल का डेटा दिखाता है. वहीं, जाइरोस्कोप तीन निर्देशांक अक्षों के लिए, घुमाव की दर का डेटा दिखाता है. ये डेटा वैल्यू, अन्य SensorEvent पैरामीटर के साथ float कलेक्शन (values) में दिखती हैं. पहली टेबल में उन मोशन सेंसर की खास जानकारी दी गई है जो 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(\t/2)).1
TYPE_SIGNIFICANT_MOTION लागू नहीं लागू नहीं लागू नहीं
TYPE_STEP_COUNTER SensorEvent.values[0] सेंसर के चालू होने के दौरान, पिछली बार डिवाइस को फिर से चालू करने के बाद से, उपयोगकर्ता ने जो कदम उठाए हैं उनकी संख्या. तरीका
TYPE_STEP_DETECTOR लागू नहीं लागू नहीं लागू नहीं

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

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

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( ANR/2), y*sin( तथा 2)

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

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

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

  • 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 देखें.

स्टेप काउंटर सेंसर का इस्तेमाल करें

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

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

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 सैंपल में, इस पेज पर बताए गए एपीआई के इस्तेमाल के बारे में ज़्यादा जानकारी दी गई है.

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