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