মোশন সেন্সর

অ্যান্ড্রয়েড প্ল্যাটফর্ম বেশ কয়েকটি সেন্সর সরবরাহ করে যা আপনাকে একটি ডিভাইসের গতি নিরীক্ষণ করতে দেয়।

সেন্সরগুলির সম্ভাব্য স্থাপত্যগুলি সেন্সরের প্রকার অনুসারে পরিবর্তিত হয়:

  • মাধ্যাকর্ষণ, রৈখিক ত্বরণ, ঘূর্ণন ভেক্টর, উল্লেখযোগ্য গতি, স্টেপ কাউন্টার এবং স্টেপ ডিটেক্টর সেন্সরগুলি হয় হার্ডওয়্যার-ভিত্তিক বা সফ্টওয়্যার-ভিত্তিক।
  • অ্যাক্সিলোমিটার এবং জাইরোস্কোপ সেন্সর সবসময় হার্ডওয়্যার-ভিত্তিক।

বেশিরভাগ অ্যান্ড্রয়েড-চালিত ডিভাইসে একটি অ্যাক্সিলোমিটার থাকে এবং অনেকগুলি এখন একটি জাইরোস্কোপ অন্তর্ভুক্ত করে। সফ্টওয়্যার-ভিত্তিক সেন্সরগুলির প্রাপ্যতা আরও পরিবর্তনশীল কারণ তারা প্রায়শই তাদের ডেটা সংগ্রহের জন্য এক বা একাধিক হার্ডওয়্যার সেন্সরের উপর নির্ভর করে। ডিভাইসের উপর নির্ভর করে, এই সফ্টওয়্যার-ভিত্তিক সেন্সরগুলি অ্যাক্সিলোমিটার এবং ম্যাগনেটোমিটার বা জাইরোস্কোপ থেকে তাদের ডেটা সংগ্রহ করতে পারে।

মোশন সেন্সরগুলি ডিভাইসের গতিবিধি নিরীক্ষণের জন্য উপযোগী, যেমন কাত, ঝাঁকান, ঘূর্ণন বা সুইং। আন্দোলনটি সাধারণত সরাসরি ব্যবহারকারীর ইনপুটের প্রতিফলন হয় (উদাহরণস্বরূপ, একজন ব্যবহারকারী একটি গেমে একটি গাড়ির স্টিয়ারিং বা একটি ব্যবহারকারী একটি গেমে একটি বল নিয়ন্ত্রণ করছেন), তবে এটি ডিভাইসটি যে শারীরিক পরিবেশে বসে আছে তারও প্রতিফলন হতে পারে। (উদাহরণস্বরূপ, আপনার গাড়ি চালানোর সময় আপনার সাথে চলাফেরা করা)। প্রথম ক্ষেত্রে, আপনি ডিভাইসের রেফারেন্সের ফ্রেম বা আপনার অ্যাপ্লিকেশনের রেফারেন্সের ফ্রেমের সাথে সম্পর্কিত গতি পর্যবেক্ষণ করছেন; দ্বিতীয় ক্ষেত্রে আপনি বিশ্বের রেফারেন্স ফ্রেম আপেক্ষিক গতি নিরীক্ষণ করছেন. মোশন সেন্সরগুলি সাধারণত ডিভাইসের অবস্থান নিরীক্ষণ করতে ব্যবহৃত হয় না, তবে সেগুলি অন্যান্য সেন্সরগুলির সাথে ব্যবহার করা যেতে পারে, যেমন জিওম্যাগনেটিক ফিল্ড সেন্সর, বিশ্বের রেফারেন্সের ফ্রেমের সাথে সম্পর্কিত একটি ডিভাইসের অবস্থান নির্ধারণ করতে (আরো তথ্যের জন্য অবস্থান সেন্সর দেখুন)।

সমস্ত মোশন সেন্সর প্রতিটি SensorEvent জন্য সেন্সর মানের বহু-মাত্রিক অ্যারে প্রদান করে। উদাহরণস্বরূপ, একটি একক সেন্সর ইভেন্টের সময় অ্যাক্সিলেরোমিটার তিনটি স্থানাঙ্ক অক্ষের জন্য ত্বরণ বল ডেটা প্রদান করে এবং জাইরোস্কোপ তিনটি স্থানাঙ্ক অক্ষের জন্য ঘূর্ণন ডেটার হার প্রদান করে। অন্যান্য SensorEvent প্যারামিটারের সাথে এই ডেটা মানগুলি একটি float অ্যারে ( values ) এ ফেরত দেওয়া হয়। সারণী 1 এন্ড্রয়েড প্ল্যাটফর্মে উপলব্ধ মোশন সেন্সরগুলির সংক্ষিপ্ত বিবরণ দেয়৷

সারণী 1. মোশন সেন্সর যা অ্যান্ড্রয়েড প্ল্যাটফর্মে সমর্থিত।

সেন্সর সেন্সর ইভেন্ট ডেটা বর্ণনা পরিমাপের একক
TYPE_ACCELEROMETER SensorEvent.values[0] x অক্ষ বরাবর ত্বরণ বল (মাধ্যাকর্ষণ সহ)। m/s 2
SensorEvent.values[1] y অক্ষ বরাবর ত্বরণ বল (মাধ্যাকর্ষণ সহ)।
SensorEvent.values[2] z অক্ষ বরাবর ত্বরণ বল (মাধ্যাকর্ষণ সহ)।
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] কোনো পক্ষপাত ক্ষতিপূরণ ছাড়াই X অক্ষ বরাবর ত্বরণ পরিমাপ করা হয়েছে। m/s 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/s 2
SensorEvent.values[1] y অক্ষ বরাবর মাধ্যাকর্ষণ বল।
SensorEvent.values[2] z অক্ষ বরাবর মাধ্যাকর্ষণ বল।
TYPE_GYROSCOPE SensorEvent.values[0] x অক্ষের চারপাশে ঘূর্ণনের হার। rad/s
SensorEvent.values[1] y অক্ষের চারপাশে ঘূর্ণনের হার।
SensorEvent.values[2] z অক্ষের চারপাশে ঘূর্ণনের হার।
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] x অক্ষের চারপাশে ঘূর্ণনের হার (ড্রিফট ক্ষতিপূরণ ছাড়া)। rad/s
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 অক্ষ বরাবর ত্বরণ বল (মাধ্যাকর্ষণ ব্যতীত)। m/s 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 N/A N/A N/A
TYPE_STEP_COUNTER SensorEvent.values[0] সেন্সর সক্রিয় করার সময় শেষ রিবুট করার পর থেকে ব্যবহারকারীর নেওয়া পদক্ষেপের সংখ্যা৷ ধাপ
TYPE_STEP_DETECTOR N/A N/A N/A

1 স্কেলার উপাদান একটি ঐচ্ছিক মান।

ঘূর্ণন ভেক্টর সেন্সর এবং মাধ্যাকর্ষণ সেন্সর হল গতি সনাক্তকরণ এবং পর্যবেক্ষণের জন্য সর্বাধিক ব্যবহৃত সেন্সর। ঘূর্ণনশীল ভেক্টর সেন্সরটি বিশেষত বহুমুখী এবং গতি-সম্পর্কিত বিভিন্ন কাজের জন্য ব্যবহার করা যেতে পারে, যেমন অঙ্গভঙ্গি সনাক্ত করা, কৌণিক পরিবর্তন পর্যবেক্ষণ করা এবং আপেক্ষিক অভিযোজন পরিবর্তনগুলি পর্যবেক্ষণ করা। উদাহরণস্বরূপ, যদি আপনি একটি গেম, একটি বর্ধিত বাস্তবতা অ্যাপ্লিকেশন, একটি 2-মাত্রিক বা 3-মাত্রিক কম্পাস, বা একটি ক্যামেরা স্থিতিশীলকরণ অ্যাপ্লিকেশন তৈরি করেন তবে ঘূর্ণনশীল ভেক্টর সেন্সরটি আদর্শ। বেশিরভাগ ক্ষেত্রে, এই সেন্সরগুলি ব্যবহার করা অ্যাক্সিলোমিটার এবং জিওম্যাগনেটিক ফিল্ড সেন্সর বা ওরিয়েন্টেশন সেন্সর ব্যবহার করার চেয়ে একটি ভাল পছন্দ।

অ্যান্ড্রয়েড ওপেন সোর্স প্রজেক্ট সেন্সর

অ্যান্ড্রয়েড ওপেন সোর্স প্রজেক্ট (AOSP) তিনটি সফ্টওয়্যার-ভিত্তিক মোশন সেন্সর সরবরাহ করে: একটি মাধ্যাকর্ষণ সেন্সর, একটি রৈখিক ত্বরণ সেন্সর এবং একটি ঘূর্ণন ভেক্টর সেন্সর৷ এই সেন্সরগুলি Android 4.0-এ আপডেট করা হয়েছে এবং এখন স্থিতিশীলতা এবং কর্মক্ষমতা উন্নত করতে একটি ডিভাইসের জাইরোস্কোপ (অন্যান্য সেন্সর ছাড়াও) ব্যবহার করে৷ আপনি যদি এই সেন্সরগুলি ব্যবহার করে দেখতে চান, তাহলে আপনি getVendor() পদ্ধতি এবং getVersion() পদ্ধতি ব্যবহার করে তাদের সনাক্ত করতে পারেন (বিক্রেতা হল Google LLC; সংস্করণ নম্বর 3)। বিক্রেতা এবং সংস্করণ নম্বর দ্বারা এই সেন্সরগুলি সনাক্ত করা প্রয়োজন কারণ অ্যান্ড্রয়েড সিস্টেম এই তিনটি সেন্সরকে সেকেন্ডারি সেন্সর হিসাবে বিবেচনা করে৷ উদাহরণস্বরূপ, যদি একটি ডিভাইস প্রস্তুতকারক তাদের নিজস্ব মাধ্যাকর্ষণ সেন্সর প্রদান করে, তাহলে AOSP মাধ্যাকর্ষণ সেন্সর একটি সেকেন্ডারি মাধ্যাকর্ষণ সেন্সর হিসাবে দেখায়। এই তিনটি সেন্সরই একটি জাইরোস্কোপের উপর নির্ভর করে: যদি একটি ডিভাইসে একটি জাইরোস্কোপ না থাকে তবে এই সেন্সরগুলি প্রদর্শিত হয় না এবং ব্যবহারের জন্য উপলব্ধ নয়।

মাধ্যাকর্ষণ সেন্সর ব্যবহার করুন

মাধ্যাকর্ষণ সেন্সর একটি ত্রিমাত্রিক ভেক্টর প্রদান করে যা অভিকর্ষের দিক এবং মাত্রা নির্দেশ করে। সাধারণত, এই সেন্সরটি মহাকাশে ডিভাইসের আপেক্ষিক অভিযোজন নির্ধারণ করতে ব্যবহৃত হয়। নিম্নলিখিত কোডটি আপনাকে দেখায় কিভাবে ডিফল্ট মাধ্যাকর্ষণ সেন্সরের একটি উদাহরণ পেতে হয়:

কোটলিন

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

জাভা

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

এককগুলি ত্বরণ সেন্সর (m/s 2 ) দ্বারা ব্যবহৃত একই এবং স্থানাঙ্ক সিস্টেমটি ত্বরণ সেন্সর দ্বারা ব্যবহৃত একের মতোই।

দ্রষ্টব্য: যখন একটি ডিভাইস বিশ্রামে থাকে, তখন মাধ্যাকর্ষণ সেন্সরের আউটপুট অ্যাক্সিলোমিটারের মতো হওয়া উচিত।

লিনিয়ার অ্যাক্সিলোমিটার ব্যবহার করুন

রৈখিক ত্বরণ সেন্সর আপনাকে একটি ত্রিমাত্রিক ভেক্টর সরবরাহ করে যা মাধ্যাকর্ষণ বাদ দিয়ে প্রতিটি ডিভাইসের অক্ষ বরাবর ত্বরণ উপস্থাপন করে। আপনি অঙ্গভঙ্গি সনাক্তকরণ সঞ্চালন করতে এই মান ব্যবহার করতে পারেন। মানটি একটি ইনর্শিয়াল নেভিগেশন সিস্টেমে ইনপুট হিসাবেও কাজ করতে পারে, যা ডেড রেকনিং ব্যবহার করে। নিম্নলিখিত কোডটি আপনাকে দেখায় কিভাবে ডিফল্ট রৈখিক ত্বরণ সেন্সরের একটি উদাহরণ পেতে হয়:

কোটলিন

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

জাভা

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/s 2 )।

ঘূর্ণন ভেক্টর সেন্সর ব্যবহার করুন

ঘূর্ণন ভেক্টর একটি কোণ এবং একটি অক্ষের সংমিশ্রণ হিসাবে ডিভাইসের স্থিতিবিন্যাস উপস্থাপন করে, যেখানে ডিভাইসটি একটি অক্ষের (x, y, বা z) চারপাশে θ কোণের মাধ্যমে ঘোরে। নিম্নলিখিত কোডটি আপনাকে দেখায় কিভাবে ডিফল্ট ঘূর্ণন ভেক্টর সেন্সরের একটি উদাহরণ পেতে হয়:

কোটলিন

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

জাভা

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) এর সমান এবং ঘূর্ণন ভেক্টরের দিক ঘূর্ণনের অক্ষের দিকের সমান।

চিত্র 1. ঘূর্ণন ভেক্টর সেন্সর দ্বারা ব্যবহৃত স্থানাঙ্ক সিস্টেম।

ঘূর্ণন ভেক্টরের তিনটি উপাদান একটি ইউনিট কোয়াটারনিয়নের শেষ তিনটি উপাদানের সমান (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/) 2))। ঘূর্ণন ভেক্টরের উপাদানগুলি এককবিহীন। x, y, এবং z অক্ষগুলিকে ত্বরণ সেন্সরের মতো একইভাবে সংজ্ঞায়িত করা হয়। রেফারেন্স কোঅর্ডিনেট সিস্টেমকে সরাসরি অর্থনর্মাল ভিত্তি হিসাবে সংজ্ঞায়িত করা হয়েছে (চিত্র 1 দেখুন)। এই সমন্বয় ব্যবস্থার নিম্নলিখিত বৈশিষ্ট্য রয়েছে:

  • X কে ভেক্টর পণ্য Y x Z হিসাবে সংজ্ঞায়িত করা হয়েছে। এটি ডিভাইসের বর্তমান অবস্থানে স্থলের স্পর্শক এবং আনুমানিক পূর্ব দিকে নির্দেশ করে।
  • Y ডিভাইসের বর্তমান অবস্থানে মাটিতে স্পর্শক এবং ভূ-চৌম্বকীয় উত্তর মেরুর দিকে নির্দেশ করে।
  • Z আকাশের দিকে নির্দেশ করে এবং স্থল সমতলে লম্ব।

একটি নমুনা অ্যাপ্লিকেশনের জন্য যা দেখায় কিভাবে ঘূর্ণন ভেক্টর সেন্সর ব্যবহার করতে হয়, RotationVectorDemo.java দেখুন।

উল্লেখযোগ্য গতি সেন্সর ব্যবহার করুন

গুরুত্বপূর্ণ মোশন সেন্সর প্রতিবার গুরুত্বপূর্ণ গতি সনাক্ত করা হলে একটি ইভেন্ট ট্রিগার করে এবং তারপর এটি নিজেকে অক্ষম করে। একটি উল্লেখযোগ্য গতি হল এমন একটি গতি যা ব্যবহারকারীর অবস্থান পরিবর্তন করতে পারে; যেমন হাঁটা, বাইক চালানো, বা চলন্ত গাড়িতে বসা। নিম্নলিখিত কোডটি আপনাকে দেখায় কিভাবে ডিফল্ট উল্লেখযোগ্য মোশন সেন্সরের একটি উদাহরণ পেতে হয় এবং কীভাবে একটি ইভেন্ট লিসেনার নিবন্ধন করতে হয়:

কোটলিন

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)
}

জাভা

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 (API স্তর 29) বা উচ্চতর চলমান ডিভাইসগুলিতে এই সেন্সর ব্যবহার করার জন্য আপনাকে অবশ্যই ACTIVITY_RECOGNITION অনুমতি ঘোষণা করতে হবে৷

নিচের কোডটি আপনাকে দেখায় কিভাবে ডিফল্ট স্টেপ কাউন্টার সেন্সরের একটি উদাহরণ পেতে হয়:

কোটলিন

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

জাভা

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

আপনার অ্যাপ চালানোর ডিভাইসে ব্যাটারি সংরক্ষণ করতে, আপনাকে একটি নির্দিষ্ট ব্যবধানে স্টেপ কাউন্টার সেন্সর থেকে বর্তমান মান পুনরুদ্ধার করতে JobScheduler ক্লাস ব্যবহার করা উচিত। যদিও বিভিন্ন ধরনের অ্যাপের জন্য বিভিন্ন সেন্সর-পড়ার ব্যবধানের প্রয়োজন হয়, তবে আপনার অ্যাপটির জন্য সেন্সর থেকে রিয়েল-টাইম ডেটার প্রয়োজন না হলে যতক্ষণ সম্ভব এই ব্যবধানটি করা উচিত।

স্টেপ ডিটেক্টর সেন্সর ব্যবহার করুন

স্টেপ ডিটেক্টর সেন্সর প্রতিবার ব্যবহারকারী যখন একটি পদক্ষেপ নেয় তখন একটি ইভেন্ট ট্রিগার করে। লেটেন্সি 2 সেকেন্ডের নিচে হবে বলে আশা করা হচ্ছে।

দ্রষ্টব্য: আপনার অ্যাপটি Android 10 (API স্তর 29) বা উচ্চতর চলমান ডিভাইসগুলিতে এই সেন্সর ব্যবহার করার জন্য আপনাকে অবশ্যই ACTIVITY_RECOGNITION অনুমতি ঘোষণা করতে হবে৷

নিচের কোডটি আপনাকে দেখায় কিভাবে ডিফল্ট স্টেপ ডিটেক্টর সেন্সরের একটি উদাহরণ পেতে হয়:

কোটলিন

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

জাভা

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

কাঁচা ডেটা নিয়ে কাজ করুন

নিম্নলিখিত সেন্সরগুলি আপনার অ্যাপটিকে ডিভাইসে প্রয়োগ করা রৈখিক এবং ঘূর্ণনশীল শক্তি সম্পর্কে কাঁচা ডেটা সরবরাহ করে৷ এই সেন্সরগুলি থেকে মানগুলি কার্যকরভাবে ব্যবহার করার জন্য, আপনাকে পরিবেশ থেকে কারণগুলি ফিল্টার করতে হবে, যেমন মাধ্যাকর্ষণ৷ শব্দ কমানোর জন্য আপনাকে মানগুলির প্রবণতায় একটি মসৃণ অ্যালগরিদম প্রয়োগ করতে হতে পারে।

অ্যাক্সিলোমিটার ব্যবহার করুন

একটি ত্বরণ সেন্সর মাধ্যাকর্ষণ বল সহ ডিভাইসে প্রয়োগ করা ত্বরণ পরিমাপ করে। নিম্নলিখিত কোডটি আপনাকে দেখায় কিভাবে ডিফল্ট ত্বরণ সেন্সরের একটি উদাহরণ পেতে হয়:

কোটলিন

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

জাভা

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

দ্রষ্টব্য: যদি আপনার অ্যাপটি Android 12 (API স্তর 31) বা উচ্চতরকে লক্ষ্য করে, তাহলে এই সেন্সরটি রেট-সীমিত

ধারণাগতভাবে, একটি ত্বরণ সেন্সর নিম্নলিখিত সম্পর্ক ব্যবহার করে সেন্সর নিজেই (F s ) প্রয়োগ করা শক্তিগুলি পরিমাপ করে একটি ডিভাইস (A d ) এ প্রয়োগ করা ত্বরণ নির্ধারণ করে:

A_D=-(1/ভর) ∑F_S

যাইহোক, মাধ্যাকর্ষণ বল সর্বদা নিম্নোক্ত সম্পর্ক অনুসারে পরিমাপিত ত্বরণকে প্রভাবিত করে:

A_D=-g-(1/ভর) ∑F_S

এই কারণে, যখন ডিভাইসটি একটি টেবিলে বসে থাকে (এবং ত্বরণ না করে), তখন অ্যাক্সিলোমিটারটি g = 9.81 m/s 2 এর মাত্রা পড়ে। একইভাবে, যখন ডিভাইসটি মুক্ত পতনের মধ্যে থাকে এবং তাই দ্রুত ভূমির দিকে 9.81 m/s 2 এ ত্বরান্বিত হয়, তখন এর অ্যাক্সিলোমিটারটি g = 0 m/s 2 এর একটি মাত্রা রিড করে। অতএব, ডিভাইসের প্রকৃত ত্বরণ পরিমাপ করতে, অভিকর্ষ বলের অবদানকে অ্যাক্সিলোমিটার ডেটা থেকে সরিয়ে ফেলতে হবে। এটি একটি উচ্চ-পাস ফিল্টার প্রয়োগ করে অর্জন করা যেতে পারে। বিপরীতভাবে, একটি লো-পাস ফিল্টার মাধ্যাকর্ষণ শক্তিকে বিচ্ছিন্ন করতে ব্যবহার করা যেতে পারে। নিম্নলিখিত উদাহরণ দেখায় কিভাবে আপনি এটি করতে পারেন:

কোটলিন

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]
}

জাভা

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/s 2 এর ত্বরণের সাথে ডিভাইসটিকে আকাশের দিকে ঠেলে দেন, তাহলে z ত্বরণের মান A + 9.81 এর সমান, যা ডিভাইসের ত্বরণ (+A m/s 2 ) বিয়োগ মাধ্যাকর্ষণ শক্তির সাথে মিলে যায় (-9.81 m/s 2 )।
  • স্থির ডিভাইসটির ত্বরণ মান +9.81 হবে, যা ডিভাইসের ত্বরণের সাথে মিলে যায় (0 m/s 2 বিয়োগ মাধ্যাকর্ষণ বল, যা -9.81 m/s 2 )।

সাধারণভাবে, আপনি যদি ডিভাইসের গতি নিরীক্ষণ করেন তবে অ্যাক্সিলোমিটার ব্যবহার করার জন্য একটি ভাল সেন্সর। প্রায় প্রতিটি অ্যান্ড্রয়েড-চালিত হ্যান্ডসেট এবং ট্যাবলেটে একটি অ্যাক্সিলোমিটার থাকে এবং এটি অন্যান্য মোশন সেন্সরগুলির তুলনায় প্রায় 10 গুণ কম শক্তি ব্যবহার করে৷ একটি অপূর্ণতা হল যে আপনাকে মহাকর্ষীয় শক্তি দূর করতে এবং শব্দ কমাতে কম-পাস এবং উচ্চ-পাস ফিল্টারগুলি প্রয়োগ করতে হতে পারে।

জাইরোস্কোপ ব্যবহার করুন

জাইরোস্কোপ একটি ডিভাইসের x, y, এবং z অক্ষের চারপাশে rad/s-এ ঘূর্ণনের হার পরিমাপ করে। নিম্নলিখিত কোডটি আপনাকে দেখায় কিভাবে ডিফল্ট জাইরোস্কোপের একটি উদাহরণ পেতে হয়:

কোটলিন

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

জাভা

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

দ্রষ্টব্য: যদি আপনার অ্যাপটি Android 12 (API স্তর 31) বা উচ্চতরকে লক্ষ্য করে, তাহলে এই সেন্সরটি রেট-সীমিত

সেন্সরের স্থানাঙ্ক সিস্টেমটি ত্বরণ সেন্সরের জন্য ব্যবহৃত একটির মতোই। ঘড়ির কাঁটার বিপরীত দিকে ঘূর্ণন ইতিবাচক; অর্থাৎ, কোনো পর্যবেক্ষক উৎপত্তিস্থলে অবস্থানরত কোনো ডিভাইসে x, y বা z অক্ষের কিছু ইতিবাচক অবস্থান থেকে দেখছেন, যদি ডিভাইসটি ঘড়ির কাঁটার বিপরীতে ঘোরে বলে মনে হয় তাহলে ইতিবাচক ঘূর্ণন রিপোর্ট করবে। এটি ধনাত্মক ঘূর্ণনের মানক গাণিতিক সংজ্ঞা এবং অভিযোজন সেন্সর দ্বারা ব্যবহৃত রোলের সংজ্ঞার মতো নয়।

সাধারণত, জাইরোস্কোপের আউটপুট সময়ের সাথে একত্রিত করা হয় একটি ঘূর্ণন গণনা করার জন্য যা টাইমস্টেপের উপর কোণের পরিবর্তন বর্ণনা করে। যেমন:

কোটলিন

// 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;
}

জাভা

// 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

দ্রষ্টব্য: ক্যালিব্রেটেড সেন্সরগুলি আরও কাঁচা ফলাফল প্রদান করে এবং এতে কিছু পক্ষপাত থাকতে পারে, তবে তাদের পরিমাপগুলি ক্রমাঙ্কনের মাধ্যমে প্রয়োগ করা সংশোধন থেকে কম লাফ ধারণ করে। কিছু অ্যাপ্লিকেশন এই অক্যালিব্রেটেড ফলাফলগুলিকে মসৃণ এবং আরও নির্ভরযোগ্য হিসাবে পছন্দ করতে পারে। উদাহরণস্বরূপ, যদি একটি অ্যাপ্লিকেশন তার নিজস্ব সেন্সর ফিউশন পরিচালনা করার চেষ্টা করে, তাহলে ক্রমাঙ্কন প্রবর্তন আসলে ফলাফলকে বিকৃত করতে পারে।

ঘূর্ণনের হার ছাড়াও, ক্যালিব্রেটেড জাইরোস্কোপ প্রতিটি অক্ষের চারপাশে আনুমানিক প্রবাহ প্রদান করে। নিম্নলিখিত কোডটি আপনাকে দেখায় কিভাবে ডিফল্ট আনক্যালিব্রেটেড জাইরোস্কোপের একটি উদাহরণ পেতে হয়:

কোটলিন

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

জাভা

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

অতিরিক্ত কোড নমুনা

BatchStepSensor নমুনা এই পৃষ্ঠায় কভার করা API-এর ব্যবহার আরও প্রদর্শন করে।

আপনারও পড়া উচিত