Hareket sensörleri

Android platformu, bir cihazın hareketini izlemenize olanak tanıyan çeşitli sensörler sunar.

Sensörlerin olası mimarileri sensör türüne göre değişir:

  • Yerçekimi, doğrusal ivme, dönüş vektörü, önemli hareket, adım sayacı ve adım algılayıcı sensörleri donanım tabanlı veya yazılım tabanlıdır.
  • İvme ölçer ve jiroskop sensörleri her zaman donanım tabanlıdır.

Android destekli cihazların çoğunda ivme ölçer, birçoğunda ise jiroskop bulunur. Yazılım tabanlı sensörlerin kullanılabilirliği daha değişkendir çünkü verilerini elde etmek için genellikle bir veya daha fazla donanım sensörüne ihtiyaç duyarlar. Cihaza bağlı olarak bu yazılım tabanlı sensörler, verilerini ivme ölçer ve manyetometreden veya jiroskoptan alabilir.

Hareket sensörleri; eğme, sallama, döndürme veya salınım gibi cihaz hareketlerini izlemek için kullanışlıdır. Hareket genellikle doğrudan kullanıcı girişinin bir yansımasıdır (örneğin, bir oyunda araba kullanan bir kullanıcı veya bir oyunda topu kontrol eden bir kullanıcı) ancak cihazın bulunduğu fiziksel ortamın bir yansıması da olabilir (örneğin, arabanızı sürerken sizinle birlikte hareket etmesi). İlk durumda, hareketi cihazın referans çerçevesine veya uygulamanızın referans çerçevesine göre izlersiniz. İkinci durumda ise hareketi dünyanın referans çerçevesine göre izlersiniz. Hareket sensörleri tek başlarına genellikle cihaz konumunu izlemek için kullanılmaz ancak cihazın dünya referans çerçevesine göre konumunu belirlemek için jeomanyetik alan sensörü gibi diğer sensörlerle birlikte kullanılabilir (daha fazla bilgi için Konum Sensörleri bölümüne bakın).

Tüm hareket sensörleri, her SensorEvent için sensör değerlerinin çok boyutlu dizilerini döndürür. Örneğin, tek bir sensör etkinliği sırasında ivme ölçer, üç koordinat ekseni için ivme kuvveti verilerini, jiroskop ise üç koordinat ekseni için dönüş hızı verilerini döndürür. Bu veri değerleri, diğer SensorEvent parametreleriyle birlikte bir float dizisinde (values) döndürülür. Tablo 1'de, Android platformunda kullanılabilen hareket sensörleri özetlenmektedir.

Tablo 1. Android platformunda desteklenen hareket sensörleri.

Sensör Sensör etkinliği verileri Açıklama Ölçü birimleri
TYPE_ACCELEROMETER SensorEvent.values[0] X ekseni boyunca ivme kuvveti (yer çekimi dahil). m/sn2
SensorEvent.values[1] Y ekseni boyunca ivme kuvveti (yer çekimi dahil).
SensorEvent.values[2] Z ekseni boyunca ivme kuvveti (yer çekimi dahil).
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] Herhangi bir sapma telafisi olmadan X ekseni boyunca ölçülen ivme. m/sn2
SensorEvent.values[1] Y ekseni boyunca herhangi bir sapma telafisi olmadan ölçülen ivme.
SensorEvent.values[2] Herhangi bir sapma telafisi olmadan Z ekseni boyunca ölçülen ivme.
SensorEvent.values[3] Tahmini sapma telafisiyle X ekseni boyunca ölçülen ivme.
SensorEvent.values[4] Tahmini sapma telafisiyle Y ekseni boyunca ölçülen ivme.
SensorEvent.values[5] Tahmini sapma telafisiyle Z ekseni boyunca ölçülen ivme.
TYPE_GRAVITY SensorEvent.values[0] X ekseni boyunca yerçekimi kuvveti. m/sn2
SensorEvent.values[1] Y ekseni boyunca yer çekimi kuvveti.
SensorEvent.values[2] Z ekseni boyunca yer çekimi kuvveti.
TYPE_GYROSCOPE SensorEvent.values[0] X ekseni etrafındaki dönüş hızı. rad/sn
SensorEvent.values[1] Y ekseni etrafındaki dönüş hızı.
SensorEvent.values[2] Z ekseni etrafındaki dönüş hızı.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] X ekseni etrafındaki dönüş hızı (sapma telafisi olmadan). rad/sn
SensorEvent.values[1] Y ekseni etrafındaki dönüş hızı (sapma telafisi olmadan).
SensorEvent.values[2] Z ekseni etrafındaki dönüş hızı (sapma telafisi olmadan).
SensorEvent.values[3] X ekseni etrafındaki tahmini sapma.
SensorEvent.values[4] Y ekseni etrafındaki tahmini sapma.
SensorEvent.values[5] Z ekseni etrafındaki tahmini sapma.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] X ekseni boyunca ivme kuvveti (yer çekimi hariç). m/sn2
SensorEvent.values[1] Y ekseni boyunca ivme kuvveti (yer çekimi hariç).
SensorEvent.values[2] Z ekseni boyunca ivme kuvveti (yer çekimi hariç).
TYPE_ROTATION_VECTOR SensorEvent.values[0] X ekseni boyunca dönüş vektörü bileşeni (x * sin(θ/2)). Birim yok
SensorEvent.values[1] Y ekseni boyunca dönüş vektörü bileşeni (y * sin(θ/2)).
SensorEvent.values[2] Z ekseni boyunca dönüş vektörü bileşeni (z * sin(θ/2)).
SensorEvent.values[3] Dönüş vektörünün skaler bileşeni ((cos(θ/2)).1
TYPE_SIGNIFICANT_MOTION Yok Yok Yok
TYPE_STEP_COUNTER SensorEvent.values[0] Sensör etkinleştirildikten sonra son yeniden başlatmadan bu yana kullanıcının attığı adım sayısı. Adımlar
TYPE_STEP_DETECTOR Yok Yok Yok

1 Skaler bileşen isteğe bağlı bir değerdir.

Dönüş vektörü sensörü ve yerçekimi sensörü, hareket algılama ve izleme için en sık kullanılan sensörlerdir. Dönüş vektörü sensörü özellikle çok yönlüdür ve hareketle ilgili çok çeşitli görevler için kullanılabilir. Örneğin, hareketleri algılama, açısal değişimi izleme ve göreceli yön değişikliklerini izleme. Örneğin, bir oyun, artırılmış gerçeklik uygulaması, 2 boyutlu veya 3 boyutlu pusula ya da kamera sabitleme uygulaması geliştiriyorsanız dönme vektörü sensörü idealdir. Çoğu durumda, bu sensörleri kullanmak, ivme ölçer ve jeomanyetik alan sensörünü veya yön sensörünü kullanmaktan daha iyi bir seçimdir.

Android Açık Kaynak Projesi sensörleri

Android Açık Kaynak Projesi (AOSP), yazılım tabanlı üç hareket sensörü sunar: yerçekimi sensörü, doğrusal ivme sensörü ve dönüş vektörü sensörü. Bu sensörler Android 4.0'da güncellenmiştir ve artık kararlılığı ve performansı artırmak için cihazın jiroskopunu (diğer sensörlere ek olarak) kullanmaktadır. Bu sensörleri denemek isterseniz getVendor() ve getVersion() yöntemlerini kullanarak sensörleri tanımlayabilirsiniz (Tedarikçi Google LLC, sürüm numarası ise 3'tür). Android sistemi bu üç sensörü ikincil sensör olarak kabul ettiğinden, bu sensörlerin tedarikçi ve sürüm numarasına göre tanımlanması gerekir. Örneğin, bir cihaz üreticisi kendi yerçekimi sensörünü sağlıyorsa AOSP yerçekimi sensörü, ikincil bir yerçekimi sensörü olarak görünür. Bu üç sensörün tümü jiroskopa bağlıdır. Cihazda jiroskop yoksa bu sensörler görünmez ve kullanılamaz.

Yer çekimi sensörünü kullanma

Yerçekimi sensörü, yerçekiminin yönünü ve büyüklüğünü gösteren üç boyutlu bir vektör sağlar. Bu sensör genellikle cihazın uzaydaki göreceli yönünü belirlemek için kullanılır. Aşağıdaki kodda, varsayılan yerçekimi sensörünün bir örneğini nasıl alacağınız gösterilmektedir:

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

Birimler, ivme sensörü tarafından kullanılanlarla aynıdır (m/sn2) ve koordinat sistemi, ivme sensörü tarafından kullanılanla aynıdır.

Not: Cihaz hareketsizken yerçekimi sensörünün çıkışı, ivme ölçerin çıkışıyla aynı olmalıdır.

Doğrusal ivme ölçeri kullanma

Doğrusal ivme sensörü, yer çekimi hariç her cihaz ekseni boyunca ivmeyi temsil eden üç boyutlu bir vektör sağlar. Hareket algılama için bu değeri kullanabilirsiniz. Değer, parakete hesabını kullanan bir atalet navigasyon sistemine giriş olarak da kullanılabilir. Aşağıdaki kodda, varsayılan doğrusal ivme sensörünün bir örneğini nasıl alacağınız gösterilmektedir:

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

Kavramsal olarak bu sensör, aşağıdaki ilişkiye göre ivme verileri sağlar:

linear acceleration = acceleration - acceleration due to gravity

Bu sensörü genellikle yerçekiminin etkisi olmadan ivme verileri elde etmek istediğinizde kullanırsınız. Örneğin, arabanızın ne kadar hızlı gittiğini görmek için bu sensörü kullanabilirsiniz. Doğrusal ivme sensöründe her zaman bir ofset bulunur ve bunu kaldırmanız gerekir. Bunu yapmanın en basit yolu, uygulamanıza bir kalibrasyon adımı eklemektir. Kalibrasyon sırasında kullanıcıdan cihazı masaya koymasını isteyebilir ve ardından üç eksenin de sapma değerlerini okuyabilirsiniz. Ardından, gerçek doğrusal ivmeyi elde etmek için bu farkı ivme sensörünün doğrudan okumalarından çıkarabilirsiniz.

Sensör koordinat sistemi, ivme sensörü tarafından kullanılanla aynıdır. Ölçü birimleri de (m/sn.2) aynıdır.

Dönüş vektörü sensörünü kullanma

Dönüş vektörü, cihazın yönünü bir açı ve eksen kombinasyonu olarak temsil eder. Bu kombinasyonda cihaz, bir eksen (x, y veya z) etrafında θ açısı kadar dönmüştür. Aşağıdaki kodda, varsayılan rotasyon vektörü sensörünün bir örneğini nasıl alacağınız gösterilmektedir:

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

Dönüş vektörünün üç öğesi aşağıdaki gibi ifade edilir:

x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)

Dönüş vektörünün büyüklüğü sin(θ/2) değerine, yönü ise dönüş ekseninin yönüne eşittir.

Şekil 1. Dönüş vektörü sensörü tarafından kullanılan koordinat sistemi.

Dönüş vektörünün üç öğesi, bir birim kuaterniyonun (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)) son üç bileşenine eşittir. Dönüş vektörünün öğeleri birimsizdir. X, y ve z eksenleri, ivme sensörüyle aynı şekilde tanımlanır. Referans koordinat sistemi, doğrudan ortonormal taban olarak tanımlanır (bkz. Şekil 1). Bu koordinat sistemi şu özelliklere sahiptir:

  • X, Y x Z vektörel çarpımı olarak tanımlanır. Cihazın mevcut konumunda zemine teğettir ve yaklaşık olarak doğuyu gösterir.
  • Y, cihazın mevcut konumunda yere teğettir ve jeomanyetik Kuzey Kutbu'nu gösterir.
  • Z, gökyüzünü gösterir ve zemin düzlemine diktir.

Dönüş vektörü sensörünün nasıl kullanılacağını gösteren örnek bir uygulama için RotationVectorDemo.java dosyasına bakın.

Önemli hareket sensörünü kullanma

Önemli hareket sensörü, önemli bir hareket algılandığında bir etkinlik tetikler ve ardından kendini devre dışı bırakır. Önemli hareket, kullanıcının konumunda değişikliğe yol açabilecek bir harekettir (ör. yürüme, bisiklete binme veya hareket halindeki bir arabada oturma). Aşağıdaki kodda, varsayılan önemli hareket sensörünün bir örneğini nasıl alacağınız ve etkinlik işleyiciyi nasıl kaydedeceğiniz gösterilmektedir:

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

Daha fazla bilgi için TriggerEventListener sayfasına bakın.

Adım sayar sensörünü kullanma

Adım sayar sensörü, sensör etkinleştirildikten sonra son yeniden başlatma işleminden bu yana kullanıcının attığı adım sayısını sağlar. Adım sayar, adım algılayıcı sensörden daha fazla gecikmeye (10 saniyeye kadar) ancak daha yüksek doğruluğa sahiptir.

Not: Uygulamanızın Android 10 (API düzeyi 29) veya sonraki sürümlerin yüklü olduğu cihazlarda bu sensörü kullanabilmesi için ACTIVITY_RECOGNITION iznini beyan etmeniz gerekir.

Aşağıdaki kodda, varsayılan adım sayar sensörünün bir örneğini nasıl alacağınız gösterilmektedir:

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

Uygulamanızı çalıştıran cihazların pilini korumak için JobScheduler sınıfını kullanarak adım sayar sensöründen belirli bir aralıkta mevcut değeri almanız gerekir. Farklı uygulama türleri farklı sensör okuma aralıkları gerektirse de uygulamanız sensörden gerçek zamanlı veri gerektirmediği sürece bu aralığı mümkün olduğunca uzun tutmanız gerekir.

Adım algılama sensörünü kullanma

Adım algılayıcı sensör, kullanıcı her adım attığında bir etkinlik tetikler. Gecikmenin 2 saniyenin altında olması beklenir.

Not: Uygulamanızın Android 10 (API düzeyi 29) veya sonraki sürümlerin yüklü olduğu cihazlarda bu sensörü kullanabilmesi için ACTIVITY_RECOGNITION iznini beyan etmeniz gerekir.

Aşağıdaki kodda, varsayılan adım algılayıcı sensörünün bir örneğini nasıl alacağınız gösterilmektedir:

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

Ham verilerle çalışma

Aşağıdaki sensörler, uygulamaya cihaza uygulanan doğrusal ve dönme kuvvetleri hakkında ham veri sağlar. Bu sensörlerden gelen değerleri etkili bir şekilde kullanmak için yer çekimi gibi ortam faktörlerini filtrelemeniz gerekir. Gürültüyü azaltmak için değerlerin trendine bir düzeltme algoritması uygulamanız da gerekebilir.

İvme ölçeri kullanma

İvme sensörü, yer çekimi kuvveti de dahil olmak üzere cihaza uygulanan ivmeyi ölçer. Aşağıdaki kodda, varsayılan ivme sensörünün bir örneğini nasıl alacağınız gösterilmektedir:

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

Not: Uygulamanız Android 12 (API düzeyi 31) veya daha yeni bir sürümü hedefliyorsa bu sensör sıklık sınırlamasına tabidir.

Kavramsal olarak, bir ivme sensörü, sensörün kendisine uygulanan kuvvetleri (Fs) aşağıdaki ilişkiyi kullanarak ölçerek bir cihaza uygulanan ivmeyi (Ad) belirler:

A_D=-(1/kütle)∑F_S

Ancak yerçekimi kuvveti, ölçülen ivmeyi her zaman aşağıdaki ilişkiye göre etkiler:

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

Bu nedenle, cihaz bir masanın üzerinde dururken (ve hızlanmıyorken) ivme ölçer g = 9,81 m/sn2 büyüklüğünü okur. Benzer şekilde, cihaz serbest düşüşte olduğunda ve bu nedenle 9, 81 m/sn2 hızla yere doğru hızla ivme kazandığında ivme ölçeri g = 0 m/sn2 büyüklüğünü okur. Bu nedenle, cihazın gerçek ivmesini ölçmek için yerçekimi kuvvetinin katkısı ivme ölçer verilerinden kaldırılmalıdır. Bu, yüksek geçişli bir filtre uygulanarak yapılabilir. Bunun aksine, yerçekimi kuvvetini izole etmek için alçak geçiren filtre kullanılabilir. Aşağıdaki örnekte bunu nasıl yapabileceğiniz gösterilmektedir:

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

Not: Sensör verilerini filtrelemek için birçok farklı teknik kullanabilirsiniz. Yukarıdaki kod örneğinde, alçak geçiren filtre oluşturmak için basit bir filtre sabiti (alfa) kullanılmıştır. Bu filtre sabiti, filtrenin sensör etkinliklerine eklediği gecikmenin kaba bir temsili olan zaman sabitinden (t) ve sensörün etkinlik yayınlama hızından (dt) türetilir. Kod örneğinde, açıklama amacıyla 0,8 alfa değeri kullanılmıştır. Bu filtreleme yöntemini kullanırsanız farklı bir alfa değeri seçmeniz gerekebilir.

İvme ölçerler standart sensör koordinat sistemini kullanır. Uygulamada bu, bir cihaz doğal yönünde bir masanın üzerinde düz dururken aşağıdaki koşulların geçerli olduğu anlamına gelir:

  • Cihazı sol taraftan iterseniz (sağa doğru hareket eder) x ivme değeri pozitif olur.
  • Cihazı alt kısmından iterseniz (sizden uzaklaşacak şekilde) y ivme değeri pozitif olur.
  • Cihazı A m/sn2 ivmeyle gökyüzüne doğru iterseniz z ivme değeri A + 9,81'e eşit olur. Bu değer, cihazın ivmesinden (+A m/sn2) yer çekimi kuvvetinin (-9,81 m/sn2) çıkarılmasıyla elde edilir.
  • Sabit cihazın ivme değeri +9,81 olur. Bu değer, cihazın ivmesine (0 m/sn2 eksi yer çekimi kuvveti olan -9,81 m/sn2) karşılık gelir.

Genel olarak, cihaz hareketini izliyorsanız ivme ölçer kullanmak iyi bir seçenektir. Android destekli neredeyse her telefon ve tablette ivme ölçer bulunur ve bu sensör, diğer hareket sensörlerine kıyasla yaklaşık 10 kat daha az güç kullanır. Yer çekimi kuvvetlerini ortadan kaldırmak ve gürültüyü azaltmak için alçak geçiren ve yüksek geçiren filtreler uygulamanız gerekebilir.

Jiroskopu kullanma

Jiroskop, bir cihazın x, y ve z ekseni etrafındaki dönüş hızını rad/sn cinsinden ölçer. Aşağıdaki kodda, varsayılan jiroskopun bir örneğini nasıl alacağınız gösterilmektedir:

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

Not: Uygulamanız Android 12 (API düzeyi 31) veya daha yeni bir sürümü hedefliyorsa bu sensör sıklık sınırlamasına tabidir.

Sensörün koordinat sistemi, ivme sensörü için kullanılanla aynıdır. Dönüş, saat yönünün tersine doğru pozitiftir. Yani x, y veya z eksenindeki pozitif bir konumdan başlangıç noktasına yerleştirilmiş bir cihaza bakan gözlemci, cihaz saat yönünün tersine dönüyorsa pozitif dönüş bildirir. Bu, pozitif dönüşün standart matematiksel tanımıdır ve yön sensörü tarafından kullanılan dönüş tanımıyla aynı değildir.

Genellikle jiroskopun çıkışı, zaman adımı boyunca açıların değişimini açıklayan bir dönüşü hesaplamak için zaman içinde entegre edilir. Örneğin:

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

Standart jiroskoplar, gürültü ve sapma (sapma) için herhangi bir filtreleme veya düzeltme yapmadan ham dönüş verileri sağlar. Uygulamada, jiroskop gürültüsü ve sapması, telafi edilmesi gereken hatalara neden olur. Sapmayı (yanlılık) ve gürültüyü genellikle yer çekimi sensörü veya ivme ölçer gibi diğer sensörleri izleyerek belirlersiniz.

Kalibre edilmemiş jiroskopu kullanma

Kalibre edilmemiş jiroskop, dönüş hızına jiroskop sapma telafisi uygulanmaması dışında jiroskopa benzer. Fabrika kalibrasyonu ve sıcaklık telafisi, dönüş hızına uygulanmaya devam eder. Kalibre edilmemiş jiroskop, işleme sonrası ve yön verilerini birleştirme için kullanışlıdır. Genel olarak gyroscope_event.values[0], uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3] değerine yakın olur. Yani,

calibrated_x ~= uncalibrated_x - bias_estimate_x

Not: Kalibre edilmemiş sensörler daha ham sonuçlar sağlar ve bazı sapmalar içerebilir ancak ölçümlerinde kalibrasyon yoluyla uygulanan düzeltmelerden kaynaklanan daha az sıçrama olur. Bazı uygulamalar, bu kalibre edilmemiş sonuçları daha sorunsuz ve güvenilir olduğu için tercih edebilir. Örneğin, bir uygulama kendi sensör füzyonunu yapmaya çalışıyorsa kalibrasyonların eklenmesi sonuçları bozabilir.

Kalibre edilmemiş jiroskop, dönüş hızlarına ek olarak her bir eksen çevresindeki tahmini sapmayı da sağlar. Aşağıdaki kodda, varsayılan kalibre edilmemiş jiroskopun bir örneğini nasıl alacağınız gösterilmektedir:

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

Ek kod örnekleri

BatchStepSensor örneği, bu sayfada ele alınan API'lerin kullanımını daha ayrıntılı bir şekilde gösterir.

Ayrıca,