Hareket sensörleri

Android platformu, cihazın hareketini izlemenize olanak tanıyan çeşitli sensörler sağlar.

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

  • Yerçekimi, doğrusal hızlanma, dönme vektörü, önemli hareket, adım sayıcı ve adım algılayıcı sensörleri donanım veya yazılım tabanlı olabilir.
  • İvme ölçer ve jiroskop sensörleri her zaman donanım tabanlı olur.

Android işletim sistemli cihazların çoğunda ivme ölçer bulunur ve çoğunda artık jiroskop da vardır. Verilerini elde etmek için genellikle bir veya daha fazla donanım sensörüne ihtiyaç duydukları için yazılım tabanlı sensörlerin kullanılabilirliği daha değişkendir. Cihazlara bağlı olarak bu yazılım tabanlı sensörler verilerini ivme ölçerden, manyetometreden veya jiroskoptan alabilir.

Hareket sensörleri; yatırma, sallama, döndürme veya sallanma gibi cihaz hareketlerini izlemek için yararlıdır. Hareket genellikle doğrudan kullanıcı girişinin bir yansımasıdır (ör. bir oyunda araba kullanan veya topu kontrol eden kullanıcı). Ancak cihazın bulunduğu fiziksel ortamın da yansıması olabilir (ör. arabanızı sürerken cihazın 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 genellikle cihaz konumunu izlemek için tek başına 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 çok boyutlu sensör değeri dizileri 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önme 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 özetlenmiştir.

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/s2
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] Sapma telafisi olmadan X ekseni boyunca ölçülen ivme. m/s2
SensorEvent.values[1] Y ekseni boyunca herhangi bir sapma telafisi olmadan ölçülen ivme.
SensorEvent.values[2] Sapma telafisi olmadan Z ekseni boyunca ölçülen ivme.
SensorEvent.values[3] Tahmini önyargı telafisi ile X ekseni boyunca ölçülen ivme.
SensorEvent.values[4] Tahmini önyargı telafisi ile Y ekseni boyunca ölçülen ivme.
SensorEvent.values[5] Tahmini önyargı telafisi ile Z ekseni boyunca ölçülen hızlanma.
TYPE_GRAVITY SensorEvent.values[0] X ekseni boyunca yer çekimi kuvveti. m/s2
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önme hızı. rad/s
SensorEvent.values[1] Y ekseni etrafındaki dönme hızı.
SensorEvent.values[2] Z ekseni etrafındaki dönme hızı.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] X ekseni etrafındaki dönme hızı (kayma telafisi olmadan). rad/s
SensorEvent.values[1] Y ekseni etrafındaki dönme hızı (sapma telafisi olmadan).
SensorEvent.values[2] z ekseni etrafındaki dönme hızı (sapma telafisi olmadan).
SensorEvent.values[3] X ekseni etrafındaki tahmini kayma.
SensorEvent.values[4] Y ekseni etrafındaki tahmini kayma.
SensorEvent.values[5] Z ekseni etrafındaki tahmini kayma.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] x ekseni boyunca ivme kuvveti (yer çekimi hariç). m/s2
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önme vektörü bileşeni (x * sin(θ/2)). Birimsiz
SensorEvent.values[1] Y ekseni boyunca dönme vektörü bileşeni (y * sin(θ/2)).
SensorEvent.values[2] z ekseni boyunca dönme vektörü bileşeni (z * sin(θ/2)).
SensorEvent.values[3] Döndürme vektörünün skaler bileşeni ((cos(θ/2)).1
TYPE_SIGNIFICANT_MOTION Yok Yok Yok
TYPE_STEP_COUNTER SensorEvent.values[0] Sensör etkinken 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önme vektörü sensörü ve yerçekimi sensörü, hareket algılama ve izleme için en sık kullanılan sensörlerdir. Dönme vektörü sensörü çok yönlüdür ve hareketle ilgili çeşitli görevler için kullanılabilir (ör. hareketleri algılama, açısal değişimi izleme ve göreceli yön değişimlerini 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ü 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ü sağlar: yerçekimi sensörü, doğrusal hızlanma sensörü ve dönme vektörü sensörü. Android 4.0'ta güncellenen bu sensörler, kararlılığı ve performansı iyileştirmek için artık cihazın jiroskopunu (diğer sensörlere ek olarak) kullanıyor. Bu sensörleri denemek istiyorsanız getVendor() yöntemini ve getVersion() yöntemini kullanarak tanımlayabilirsiniz (tedarikçi firma Google LLC; sürüm numarası 3'tür). Android sistemi bu üç sensörü ikincil sensör olarak kabul ettiğinden, bu sensörlerin tedarikçiye 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 yerçekimi sensörü olarak görünür. Bu sensörlerin üçü de jiroskop kullanır. Cihazınızda jiroskop yoksa bu sensörler gösterilmez 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 uzayda 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ğinin nasıl alınacağı 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 (m/s2) aynıdır 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şlemini gerçekleştirmek için bu değeri kullanabilirsiniz. Bu değer, tahmini konum belirleme yöntemini kullanan bir eylemsiz navigasyon sistemine giriş olarak da kullanılabilir. Aşağıdaki kodda, varsayılan doğrusal hızlanma sensörünün bir örneğinin nasıl alınacağı 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);

Bu sensör, kavramsal olarak aşağıdaki ilişkiye göre size hızlanma verileri sağlar:

linear acceleration = acceleration - acceleration due to gravity

Bu sensörü genellikle yerçekimi etkisi olmadan hızlanma verileri elde etmek istediğinizde kullanırsınız. Örneğin, aracınızın ne kadar hızlı gittiğini görmek için bu sensörü kullanabilirsiniz. Doğrusal hızlanma sensöründe her zaman kaldırmanız gereken bir ofset bulunur. Bunu yapmanın en kolay yolu, uygulamanıza bir kalibrasyon adımı eklemektir. Kalibrasyon sırasında kullanıcıdan cihazı bir masaya koymasını ve ardından üç eksenin de ofsetlerini okumasını isteyebilirsiniz. Ardından, gerçek doğrusal ivmeyi elde etmek için bu ofseti hızlanma 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/s2) aynıdır.

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

Dönme vektörü, cihazın bir eksen (x, y veya z) etrafında θ açısıyla döndüğü bir açı ve eksen kombinasyonu olarak cihazın yönünü temsil eder. Aşağıdaki kodda, varsayılan dönme vektörü sensörünün bir örneğinin nasıl alınacağı 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öndürme vektörünün üç öğesi aşağıdaki gibi ifade edilir:

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

Burada, dönme vektörünün büyüklüğü sin(θ/2)'ye, dönme vektörünün yönü ise dönme ekseninin yönüne eşittir.

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

Döndürme vektörünün üç öğesi, bir birim dört boyutlu vektörün son üç bileşenine (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)) eşittir. Döndürme vektörünün öğeleri birimsizdir. x, y ve z eksenleri, ivme ölçer ile aynı şekilde tanımlanır. Referans koordinat sistemi, doğrudan ortonormal bir temel olarak tanımlanır (bkz. Şekil 1). Bu koordinat sisteminin özellikleri şunlardır:

  • X, Y x Z vektör çarpımı olarak tanımlanır. Cihazın mevcut konumunda yere teğet geçer ve yaklaşık olarak doğuyu gösterir.
  • Y, cihazın mevcut konumunda yere teğet geçer ve coğrafi Kuzey Kutbu'nu gösterir.
  • Z, gökyüz yönündedir ve zemin düzleminde dikeydir.

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

Önemli hareket sensörünü kullanma

Önemli hareket sensörü, önemli bir hareket her algılandığında bir etkinlik tetikler ve ardından kendini devre dışı bırakır. Önemli hareket, kullanıcının konumunda değişiklik yapabilecek hareketlerdir (ör. yürüme, bisiklet sürme veya hareket eden bir arabada oturmak). Aşağıdaki kodda, varsayılan önemli hareket sensörünün bir örneğinin nasıl alınacağı ve bir etkinlik dinleyicisinin nasıl kaydedileceği 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 etkinken son yeniden başlatmadan bu yana kullanıcının attığı adım sayısını sağlar. Adım sayıcı, adım algılayıcı sensörüne kıyasla daha fazla gecikmeye (10 saniyeye kadar) sahiptir ancak daha doğrudur.

Not: Uygulamanızın Android 10 (API düzeyi 29) veya sonraki sürümleri çalıştıran cihazlarda bu sensörü kullanabilmesi için ACTIVITY_RECOGNITION iznini belirtmeniz gerekir.

Aşağıdaki kodda, varsayılan adım sayıcı sensörünün bir örneğinin nasıl alınacağı 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 cihazlardaki pili korumak için belirli bir aralıkta adım sayar sensöründen mevcut değeri almak üzere JobScheduler sınıfını kullanmanı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 tutmalısınız.

Adım algılayıcı 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ümleri çalıştıran cihazlarda bu sensörü kullanabilmesi için ACTIVITY_RECOGNITION iznini belirtmeniz gerekir.

Aşağıdaki kodda, varsayılan adım algılayıcı sensörünün bir örneğinin nasıl alınacağı 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, uygulamanıza cihaza uygulanan doğrusal ve dönme kuvvetleri hakkında ham veriler sağlar. Bu sensörlerden gelen değerleri etkili bir şekilde kullanmak için yerçekimi gibi çevresel faktörleri filtrelemeniz gerekir. Gürültüyü azaltmak için değerlerin eğilimine bir yumuşatma 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ğinin nasıl alınacağı 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'yi (API düzeyi 31) veya daha yeni bir sürümü hedefliyorsa bu sensör hız sınırlıdır.

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

A_D=-(1/mass)∑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 üzerindeyken (ve ivmelenmiyorsa) ivmeölçer g = 9,81 m/s2 değerini okur. Benzer şekilde, cihaz serbest düşüşteyken ve dolayısıyla 9,81 m/s2 hızla yere doğru hızlanırken, ivmeölçeri g = 0 m/s2 değerini gösterir. 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çiren filtre uygulayarak yapılabilir. Buna karşılık, yerçekimi kuvvetini izole etmek için düşük geçirimli 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, düşük geçiren filtre oluşturmak için basit bir filtre sabit değeri (alpha) kullanılmaktadır. Bu filtre sabiti, filtrenin sensör etkinliklerine eklediği gecikmenin kaba bir temsili olan bir zaman sabiti (t) ve sensörün etkinlik yayınlama hızı (dt) ile elde edilir. Kod örneğinde, açıklama amacıyla 0,8 alfa değeri kullanılmıştır. Bu filtreleme yöntemini kullanıyorsanı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ü ile masanın üzerine düz bir şekilde yerleştirildiğinde 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ı alttan iterseniz (sizden uzaklaşacak şekilde) y ivme değeri pozitif olur.
  • Cihazı A m/s2 ivmesiyle gökyüzüne doğru iterseniz z ivme değeri A + 9,81'e eşittir. Bu değer, cihazın ivmesine (+A m/s2) yer çekimi kuvvetinin (-9,81 m/s2) eklenmesidir.
  • Sabit cihazın ivme değeri +9,81'dir. Bu değer, cihazın ivmesine (0 m/s2 eksi yerçekimi kuvveti olan -9,81 m/s2) karşılık gelir.

Genel olarak, cihaz hareketini izliyorsanız ivme ölçer iyi bir sensördür. Android işletim sistemli hemen hemen her cep telefonu ve tablette bulunan ivmeölçer, diğer hareket sensörlerinden yaklaşık 10 kat daha az güç kullanır. Bu yöntemin bir dezavantajı, yerçekimi kuvvetlerini ortadan kaldırmak ve gürültüyü azaltmak için düşük geçiren ve yüksek geçiren filtreler uygulamanız gerekmesidir.

Jiroskopu kullanma

Jiroskop, bir cihazın x, y ve z ekseni etrafındaki dönme hızını rad/sn cinsinden ölçer. Aşağıdaki kodda, varsayılan jiroskop örneğinin nasıl alınacağı 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'yi (API düzeyi 31) veya daha yeni bir sürümü hedefliyorsa bu sensör hız sınırlıdır.

Sensörün koordinat sistemi, ivme sensörü için kullanılanla aynıdır. Dönme, saat yönünün tersine doğru pozitiftir. Yani, x, y veya z eksenindeki pozitif bir konumdan bakıldığında, orijinde konumlandırılmış bir cihaz saat yönünün tersine dönüyorsa gözlemci pozitif dönme bildirir. Bu, pozitif dönme işleminin standart matematiksel tanımıdır ve yön sensörü tarafından kullanılan yuvarlanma tanımı ile aynı değildir.

Genellikle jiroskopun çıkışı, adım aralığındaki açı değişimini açıklayan bir dönme hesaplamak için zaman içinde entegre edilir. Örnek:

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 kayma (yanlışlık) için herhangi bir filtreleme veya düzeltme yapmadan ham dönme verileri sağlar. Pratikte, jiroskop gürültüsü ve kayması telafi edilmesi gereken hatalar oluşturur. Genellikle yer çekimi sensörü veya ivme ölçer gibi diğer sensörleri izleyerek kaymayı (yanlışlığı) ve gürültüyü belirlersiniz.

Kalibre edilmemiş jiroskopu kullanma

Kalibre edilmemiş jiroskop, dönme hızına jiroskop kayması telafisi uygulanmaması dışında jiroskopa benzer. Fabrika kalibrasyon ve sıcaklık telafisi, dönme hızına uygulanmaya devam eder. Kalibre edilmemiş jiroskop, işleme sonrası işlemler ve yönelim 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]'e yakındır. Yani,

calibrated_x ~= uncalibrated_x - bias_estimate_x

Not: Kalibre edilmemiş sensörler daha ham sonuçlar sağlar ve bazı önyargılar içerebilir ancak ölçümlerinde kalibrasyon sırasında uygulanan düzeltmelerden kaynaklanan daha az sıçrama bulunur. Bazı uygulamalar, daha düzgün ve güvenilir oldukları için kalibre edilmemiş sonuçları tercih edebilir. Örneğin, bir uygulama kendi sensör füzyonunu gerçekleştirmeye çalışıyorsa kalibrasyonların uygulanması sonuçları bozabilir.

Kalibre edilmemiş jiroskop, dönme hızlarının yanı sıra her bir eksen etrafındaki tahmini kaymayı da sağlar. Aşağıdaki kodda, varsayılan kalibre edilmemiş jiroskop örneğinin nasıl alınacağı 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);

Diğer kod örnekleri

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

Ayrıca