मोशन सेंसर

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

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

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

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

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

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

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

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

मोशन का पता लगाने और उसे मॉनिटर करने के लिए, रोटेशन वेक्टर सेंसर और ग्रेविटी सेंसर का सबसे ज़्यादा इस्तेमाल किया जाता है. रोटेशनल वेक्टर सेंसर, कई तरह के काम कर सकता है. इसका इस्तेमाल, मोशन से जुड़े कई कामों के लिए किया जा सकता है. जैसे, जेस्चर का पता लगाना, ऐंगल में होने वाले बदलावों को मॉनिटर करना, और ओरिएंटेशन में होने वाले बदलावों को मॉनिटर करना. उदाहरण के लिए, अगर आपको कोई गेम, ऑगमेंटेड रिएलिटी ऐप्लिकेशन, 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

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

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

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

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

  • 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 मी/से2 की वैल्यू दिखाता है. इसी तरह, जब डिवाइस फ़्री फ़ॉल में होता है और इसलिए 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 मीटर/सेकंड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 सैंपल में, इस पेज पर बताए गए एपीआई के इस्तेमाल के बारे में ज़्यादा जानकारी दी गई है.

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