مستشعرات الحركة

يوفّر نظام Android الأساسي العديد من أدوات الاستشعار التي تتيح لك مراقبة الحركة. الجهاز.

أجهزة الاستشعار تختلف البُنى الهندسية الممكنة حسب نوع المستشعر:

  • الجاذبية، التسارع الخطي، متجه الدوران، الحركة المهمة، الخطوة وأجهزة استشعار جهاز كشف الخطوات وأجهزة الاستشعار مستندة إلى البرامج.
  • تعتمد أجهزة استشعار مقياس التسارع والجيروسكوب دائمًا على الأجهزة.

يتوفر في معظم الأجهزة التي تعمل بنظام التشغيل Android مقياس تسارع، ويتضمن الكثير منها الآن الجيروسكوب. أصبح توفر أدوات الاستشعار القائمة على البرامج أكثر لأنها غالبًا ما تعتمد على جهاز استشعار واحد أو أكثر من الأجهزة لاشتقاق البيانات. وبناءً على الجهاز، يمكن أن تستمد المستشعرات المستندة إلى البرامج البيانات إما من مقياس التسارع ومقياس المغناطيسية أو من الجيروسكوب.

تكون أجهزة استشعار الحركة مفيدة لمراقبة حركة الجهاز، مثل الإمالة أو الاهتزاز أو التدوير أَجْهِزَة عادةً ما تكون الحركة انعكاسًا للإدخال المباشر للمستخدم (على سبيل المثال، عندما يوجّه المستخدم سيارة في لعبة أو مستخدم يتحكم في كرة في لعبة)، ولكن يمكن أن يكون أيضًا انعكاسًا البيئة المادية التي يجلس فيها الجهاز (على سبيل المثال، يتحرك معك أثناء القيادة سيارتك). في الحالة الأولى، أنت تراقب الحركة بالنسبة إلى الإطار المرجعي للجهاز أو الإطار المرجعي لطلبك وفي الحالة الثانية، أنت تراقب الحركة بالنسبة الإطار المرجعي في العالم. لا تُستخدم عادةً أجهزة استشعار الحركة لمراقبة الحركة موضع الجهاز، ولكن يمكن استخدامها مع أدوات استشعار أخرى، مثل مستشعر المجال المغناطيسي الأرضي، لتحديد موضع الجهاز بالنسبة إلى الإطار المرجعي في العالم (راجِع أجهزة استشعار الموضع لمزيد من المعلومات المعلومات).

تعرض كل أجهزة استشعار الحركة صفائف متعددة الأبعاد لقيم أداة الاستشعار لكل SensorEvent. على سبيل المثال، عند رصد جهاز استشعار واحد، يعود مقياس التسارع. بيانات قوة التسارع للمحاور الثلاثة ومعدّل إرجاع الجيروسكوب للدوران البيانات الخاصة بمحاور الإحداثيات الثلاثة. يتم عرض قيم البيانات هذه في مصفوفة float. (values) مع غيرها من SensorEvent المعلَمات. يلخّص الجدول 1 أجهزة استشعار الحركة المتوفرة على نظام Android الأساسي.

الجدول 1. أجهزة استشعار الحركة المتاحة على نظام Android الأساسي

أداة استشعار بيانات أحداث أداة الاستشعار الوصف وحدات القياس
TYPE_ACCELEROMETER SensorEvent.values[0] قوة التسارع على طول المحور س (بما في ذلك الجاذبية). م/ث2
SensorEvent.values[1] قوة التسارع على طول المحور ص (بما في ذلك الجاذبية).
SensorEvent.values[2] قوة التسارع على طول المحور z (بما في ذلك الجاذبية).
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] قياس التسارع على طول المحور س دون أي تعويض للتحيز. م/ث2
SensorEvent.values[1] تم قياس التسارع على طول المحور ص دون أي تعويض للتحيز.
SensorEvent.values[2] قياس التسارع على طول المحور Z دون أي تعويض للتحيز.
SensorEvent.values[3] قياس التسارع على طول المحور س مع تعويض التحيز المقدر.
SensorEvent.values[4] تم قياس التسارع على طول المحور ص مع تعويض التحيز المقدر.
SensorEvent.values[5] تم قياس التسارع على طول المحور Z مع تعويض التحيز المقدر.
TYPE_GRAVITY SensorEvent.values[0] قوة الجاذبية على المحور x. م/ث2
SensorEvent.values[1] قوة الجاذبية على المحور ص.
SensorEvent.values[2] قوة الجاذبية على المحور z.
TYPE_GYROSCOPE SensorEvent.values[0] معدل الدوران حول المحور x. راد/ثانية
SensorEvent.values[1] معدل الدوران حول المحور ص.
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] الانجراف المقدر حول المحور ص.
SensorEvent.values[5] الانجراف المقدّر حول المحور z.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] قوة التسارع على طول المحور س (باستثناء الجاذبية). م/ث2
SensorEvent.values[1] قوة التسارع على طول المحور ص (باستثناء الجاذبية).
SensorEvent.values[2] قوة التسارع على طول المحور z (باستثناء الجاذبية).
TYPE_ROTATION_VECTOR SensorEvent.values[0] مكوّن متجه التدوير على طول المحور x (x * sin(الوارد/2)). بلا وحدة
SensorEvent.values[1] مكوّن متجه الدوران على طول المحور ص (y * sin(الوارد/2)).
SensorEvent.values[2] مكوّن متجه التدوير على طول المحور z (z * sin(الوارد/2)).
SensorEvent.values[3] المكوِّن العددي لمتجه الدوران ((cos(main/2)).1
TYPE_SIGNIFICANT_MOTION لا ينطبق (لا ينطبق) لا ينطبق
TYPE_STEP_COUNTER SensorEvent.values[0] عدد الخطوات التي اتخذها المستخدم منذ آخر عملية إعادة تشغيل أثناء عمل جهاز الاستشعار تم تفعيل. الخطوات
TYPE_STEP_DETECTOR لا ينطبق (لا ينطبق) لا ينطبق

1 المكوِّن العددي هو قيمة اختيارية.

مستشعر اتجاه الدوران ومستشعر الجاذبية هما أكثر أدوات الاستشعار استخدامًا في الحركة والرصد والمراقبة يعد مستشعر المتجه الدوراني متعدد الاستخدامات بشكل خاص ويمكن استخدامه مجموعة واسعة من المهام المتعلقة بالحركة، مثل اكتشاف الإيماءات ومراقبة التغير الزاوي بمراقبة تغيرات الاتجاه النسبي. فعلى سبيل المثال، يعد مستشعر المتجه الدوران مثاليًا إذا يطورون لعبة، أو تطبيق واقع معزز، أو بوصلة ثنائية الأبعاد أو ثلاثية الأبعاد، أو أحد تطبيقات تثبيت الكاميرا. وفي معظم الحالات، يكون استخدام أجهزة الاستشعار هذه خيارًا أفضل من استخدام مقياس التسارع ومستشعر المجال المغناطيسي الأرضي أو أداة استشعار الاتجاه.

أدوات استشعار مشروع البرامج المفتوحة المصدر على Android

يوفر "المشروع المفتوح المصدر لنظام Android" (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);

وتكون الوحدات متطابقة مع الوحدات التي يستخدمها التسارع. (م/ث2)، ويكون نظام الإحداثيات هو نفسه النظام الذي يستخدمه جهاز استشعار التسارع.

ملاحظة: عندما يكون الجهاز غير نشِط، يتم تسجيل مُخرجات أداة استشعار الجاذبية. من المفترض أن يتطابق ذلك مع مقياس التسارع.

استخدام مقياس التسارع الخطي

تقدّم لك أداة استشعار التسارع الخطّي خطًا متّجهًا ثلاثي الأبعاد. التي تمثل التسارع على طول كل محور جهاز، مع استبعاد الجاذبية. يمكنك استخدام هذه القيمة لإجراء اكتشاف الإيماءة. يمكن أن تكون القيمة أيضًا بمثابة مدخل نظام الملاحة الجوية، والذي يستخدم الحساب المميت. يُظهر الرمز التالي في ما يلي كيفية الحصول على مثيل لمستشعر التسارع الخطي التلقائي:

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

استخدام أداة استشعار متجه الدوران

يمثل متجه الدوران اتجاه الجهاز كمجموعة من الزاوية الذي يتم فيه تدوير الجهاز بزاوية LIVE حول محور (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(reset/2)

حيث يكون مقدار متجه الدوران يساوي sin(subtitle/2)، واتجاه خط متجه الدوران يساوي اتجاه محور الدوران.

الشكل 1. نظام التنسيق المستخدم بواسطة مستشعر متجه الدوران.

العناصر الثلاثة لمتجه الدوران تساوي المكوّنات الثلاثة الأخيرة للوحدة quaternion (cos(spn/2) وx*sin(المستهلكين) وy*sin(الموثوق بها) - z*sin(الموثوقتين) عناصر خط متجه الدوران هي لا وحدة تم تحديد المحاور x وy وz بالطريقة ذاتها التي يتم بها تحديد محاور استشعار التسارع. المرجع يُعرّف نظام الإحداثيات على أنه أساس خصابي مباشر (راجع الشكل 1). نظام الإحداثيات هذا السمات التالية:

  • يُعرّف س على أنه ناتج الخط المتجه ص × ع. العرض المماسي الأرض في الموقع الحالي للجهاز والنقاط الشرقية تقريبًا.
  • يُعدّ ص اتجاهًا للأرض في الموقع الجغرافي الحالي للجهاز ويشير إلى مغناطيسية أرضية القطب الشمالي.
  • يشير 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 ثوانٍ) ولكنّه يزيد عن من جهاز استشعار الخطوة.

ملاحظة: يجب الإفصاح عن ACTIVITY_RECOGNITION لكي يتمكّن تطبيقك من استخدام جهاز الاستشعار هذا على الأجهزة قيد التشغيل. Android 10 (المستوى 29 من واجهة برمجة التطبيقات) أو إصدار أحدث

يوضح الرمز التالي طريقة الحصول على مثيل للخطوة التلقائية أداة الاستشعار المضادة:

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 لاسترداد القيمة الحالية من أداة استشعار عدّاد الخطوات في فاصل محدَّد. وعلى الرغم من اختلاف أنواع التطبيقات تتطلب فواصل زمنية مختلفة لقراءة المستشعر، فيجب جعل هذا الفاصل الزمني لأطول مدة ممكنة، إلا إذا كان تطبيقك يتطلب بيانات في الوقت الفعلي من أداة الاستشعار.

استخدام أداة استشعار أداة رصد الخطوات

تعمل أداة استشعار أداة رصد الخطوات على تشغيل حدث في كل مرة يتخذ فيها المستخدم خطوة. يقدر وقت الاستجابة من المتوقع أن يكون أقل من ثانيتين.

ملاحظة: يجب الإفصاح عن ACTIVITY_RECOGNITION لكي يتمكّن تطبيقك من استخدام جهاز الاستشعار هذا على الأجهزة قيد التشغيل. Android 10 (المستوى 29 من واجهة برمجة التطبيقات) أو إصدار أحدث

يوضح الرمز التالي طريقة الحصول على مثيل للخطوة التلقائية أداة استشعار الكاشف:

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 من واجهة برمجة التطبيقات) أو أعلى، فهذا المستشعر معدّل محدود:

من الناحية النظرية، يحدد مستشعر التسارع التسارع الذي يتم تطبيقه على الجهاز (A) من خلال قياس القوى التي يتم تطبيقها على أداة الاستشعار نفسها (Fs) باستخدام العلاقة التالية:

A_D=-(1/ماس)∑F_S

ومع ذلك، فإن قوة الجاذبية دائمًا ما تؤثر في التسارع الذي يتم قياسه وفقًا العلاقة التالية:

A_D=-g-(1/mass)∑F_S

ولهذا السبب، عندما يكون الجهاز على طاولة (وليس متسارعًا)، لا يشير مقياس التسارع إلى المقدار g = 9.81 م/ث2. وبالمثل، عندما يكون الجهاز في السقوط الحر، وبالتالي تزداد سرعة باتجاه الأرض بسرعة 9.81 متر/ثانية، يشير مقياس التسارع إلى المقدار 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 إيجابية.
  • إذا دفعت الجهاز إلى الأسفل (بحيث يتحرك بعيدًا عنك)، تكون قيمة التسارع ص إيجابية.
  • إذا دفعت الجهاز نحو السماء بتسارع A م/ث2، تساوي قيمة التسارع z A + 9.81، والتي تتجاوب مع تسريع الجهاز (+A). م/ث2) مطروحًا منه قوة الجاذبية (-9.81 م/ث2).
  • وستكون قيمة التسارع للجهاز الثابت +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 من واجهة برمجة التطبيقات) أو أعلى، فهذا المستشعر معدّل محدود:

نظام الإحداثيات لأداة الاستشعار هو نفسه الذي يُستخدم في مستشعر التسارع. التبديل موجب في اتجاه عكس عقارب الساعة؛ أي، مراقب ينظر من موقع موجب على المحور "س" أو "ص" أو "ع" على جهاز موضوع على المصدر دوران موجب إذا بدا أن الجهاز يدور عكس عقارب الساعة. هذه هي التعريف الرياضي القياسي للدوران الإيجابي ولا يكون هو نفسه تعريف اللفة التي تستخدمها أداة استشعار الاتجاه.

وعادةً ما يتم دمج ناتج الجيروسكوب مع مرور الوقت لحساب الدوران، وذلك من خلال وصف تغير الزوايا بمرور الوقت. مثلاً:

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 استخدام واجهات برمجة التطبيقات المشمولة في هذه الصفحة.

يجب عليك أيضًا قراءة