मोशन सेंसर

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

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

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

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

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

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

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

सेंसर सेंसर इवेंट डेटा ब्यौरा माप की इकाई
TYPE_ACCELEROMETER SensorEvent.values[0] X ऐक्सिस के साथ ऐक्सेलिरेशन फ़ोर्स (इसमें गुरुत्वाकर्षण भी शामिल है). m/s2
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 ऐक्सिस पर गुरुत्वाकर्षण बल. m/s2
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] X ऐक्सिस पर ऐक्सेलिरेशन फ़ोर्स (गुरुत्वाकर्षण को छोड़कर). मी॰/से॰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 स्केलर कॉम्पोनेंट की वैल्यू देना ज़रूरी नहीं है.

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

Android ओपन सोर्स प्रोजेक्ट के सेंसर

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

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

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

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, और Z ऐक्सिस को ऐक्सेलिरेशन सेंसर की तरह ही तय किया जाता है. रेफ़रंस कोऑर्डिनेट सिस्टम को डायरेक्ट ऑर्थोनॉर्मल बेसिस के तौर पर तय किया जाता है (इमेज 1 देखें). इस कोऑर्डिनेट सिस्टम की ये विशेषताएं हैं:

  • 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 की ऐल्फ़ा वैल्यू का इस्तेमाल किया गया है. अगर फ़िल्टर करने के लिए इस तरीके का इस्तेमाल किया जाता है, तो आपको कोई दूसरी ऐल्फ़ा वैल्यू चुननी पड़ सकती है.

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

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

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

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

जाइरोस्कोप, डिवाइस के x, y, और z ऐक्सिस के आस-पास रोटेशन की दर को रेडियन/सेकंड में मेज़र करता है. यहां दिए गए कोड से, डिफ़ॉल्ट जाइरोस्कोप का इंस्टेंस पाने का तरीका पता चलता है:

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

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