Hareket sensörleri

Android platformu, bir cihazın hareketini izlemenizi sağlayan çeşitli sensörler sağlar.

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

  • 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 çoğu cihazda ivme ölçer bulunur ve artık bu cihazların çoğunda jiroskop da vardır. 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ü kullanılır. Bu yazılım tabanlı sensörler, cihaza bağlı olarak ivme ölçer ve manyetometreden ya da jiroskoptan veri elde edebilir.

Hareket sensörleri; yatırma, titreme, döndürme veya sallama gibi cihaz hareketlerini izlemek için kullanışlıdır. Hareket genellikle doğrudan kullanıcı girdisinin bir yansımasıdır (örneğin, oyunda arabayı Yönlendiren veya maçta bir topu kontrol eden kullanıcı) ancak aynı zamanda cihazın oturduğu fiziksel ortamın da (örneğin, arabanızı sürerken üzerinizde olma) bir yansıması olabilir. İlkinde cihazın referans çerçevesine veya uygulamanızın referans çerçevesine göre hareketi izliyorsunuz. İkincisinde ise dünyanın referans çerçevesine göre hareketi izliyorsunuz. Hareket sensörleri genellikle cihazın konumunu izlemek için kullanılmaz ancak cihazın konumunu dünyanın referans çerçevesine göre 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 bir SensorEvent için çok boyutlu sensör değeri dizilerini döndürür. Örneğin, tek bir sensör olayı sırasında ivme ölçer, üç koordinat ekseni için ivme kuvveti verilerini, jiroskop ise üç koordinat ekseni için dönüş verilerinin hızını döndürür. Bu veri değerleri, diğer SensorEvent parametreleriyle birlikte bir float dizisi (values) içinde döndürülür. Tablo 1'de Android platformunda bulunan hareket sensörleri özetlenmektedir.

Tablo 1. Android platformunda desteklenen hareket sensörleri.

Sensör Sensör etkinlik 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 üzerindeki ivme kuvveti (yer çekimi dahil).
SensorEvent.values[2] Z ekseni üzerindeki ivme kuvveti (yer çekimi dahil).
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] X ekseni boyunca herhangi bir sapma telafisi olmadan ölçülen ivme. m/sn2
SensorEvent.values[1] Y ekseninde herhangi bir sapma telafisi olmadan ölçülen ivme.
SensorEvent.values[2] Z ekseni boyunca herhangi bir sapma telafisi olmadan ölçülen ivme.
SensorEvent.values[3] X ekseni boyunca tahmini sapma telafisi ile ölçülen ivme.
SensorEvent.values[4] Y ekseninde tahmini sapma telafisi ile ölçülen ivme.
SensorEvent.values[5] Z ekseni boyunca tahmini sapma telafisi ile ölçülen ivme.
TYPE_GRAVITY SensorEvent.values[0] X eksenindeki yer çekimi kuvveti. m/sn2
SensorEvent.values[1] Y eksenindeki yer çekimi kuvveti.
SensorEvent.values[2] Z ekseni boyunca yer çekimi kuvveti.
TYPE_GYROSCOPE SensorEvent.values[0] X ekseni etrafında dönme hızı. rad/sn
SensorEvent.values[1] Y ekseni etrafında dönme hızı.
SensorEvent.values[2] Z ekseni etrafında dönme hızı.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] x ekseni etrafında dönme hızı (kayma telafisi olmadan). rad/sn
SensorEvent.values[1] y ekseni etrafında dönme hızı (kayma telafisi olmadan).
SensorEvent.values[2] Z ekseni etrafında dönme hızı (kayma telafisi olmadan).
SensorEvent.values[3] X ekseni etrafında tahmini kayma.
SensorEvent.values[4] Y ekseni etrafında tahmini kayma.
SensorEvent.values[5] Z ekseni etrafında tahmini kayma.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] x ekseni boyunca ivme kuvveti (yer çekimi hariç). m/sn2
SensorEvent.values[1] Y eksenindeki ivme kuvveti (yer çekimi hariç).
SensorEvent.values[2] Z ekseni boyunca ivme kuvveti (yer çekimi hariç).
TYPE_ROTATION_VECTOR SensorEvent.values[0] x ekseni (x * sin(∧/2)) boyunca döndürme vektör bileşeni). Birimsiz
SensorEvent.values[1] Y eksenindeki döndürme vektör bileşeni (y * sin(∧/2)).
SensorEvent.values[2] Z ekseni boyunca döndürme vektör bileşeni (z * sin(rel/2)).
SensorEvent.values[3] Dönme vektörünün skaler bileşeni ((cos(başladı/2)).1
TYPE_SIGNIFICANT_MOTION Yok Yok Yok
TYPE_STEP_COUNTER SensorEvent.values[0] Sensör etkinleştirilirken son yeniden başlatmadan bu yana kullanıcının gerçekleştirdiği 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önme vektör sensörü özellikle çok yönlüdür ve hareketleri algılama, açısal değişiklikleri izleme ve göreli yön değişikliklerini izleme gibi hareketle ilgili çok çeşitli görevlerde kullanılabilir. Örneğin, oyun, artırılmış gerçeklik uygulaması, 2 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ü sağlar: 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 kararlılık ile performansı iyileştirmek için artık bir cihazın jiroskopunu (diğer sensörlere ek olarak) kullanmaktadır. Bu sensörleri denemek isterseniz getVendor() ve getVersion() yöntemini kullanarak tanıyabilirsiniz (Tedarikçi firma Google LLC; sürüm numarası 3'tür). Android sistemi bu üç sensörü ikincil sensör olarak kabul ettiği için bu sensörleri satıcı ve sürüm numarasına göre tanımlamak 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österilir. Bu sensörlerin üçü de jiroskopla çalışır. Bir cihazda jiroskop yoksa bu sensörler görünmez ve kullanılamaz.

Yer çekimi sensörünü kullanın

Yerçekimi sensörü, yer çekiminin yönünü ve büyüklüğünü gösteren üç boyutlu bir vektör sağlar. Genellikle bu sensör, cihazın uzaydaki göreli 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ü (m/s2) tarafından kullanılanlarla aynıdır ve koordinat sistemi, ivme sensörü tarafından kullanılan sistemle 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 bir cihaz ekseninde ivmeyi temsil eden üç boyutlu bir vektör sunar. Bu değeri, hareket algılamayı gerçekleştirmek için kullanabilirsiniz. Bu değer, ölü hesaplama kullanan atalet navigasyon sistemlerine girdi 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 size aşağıdaki ilişkiye göre ivme verileri sağlar:

linear acceleration = acceleration - acceleration due to gravity

Genellikle bu sensörü, yer çekiminin etkisi olmadan hızlanma verilerini 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ünün her zaman bir ofseti vardır 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ı bir masaya koymasını isteyebilirsiniz ve ardından üç eksen için de ofsetleri okuyabilirsiniz. Daha sonra bu ofseti, ivme sensörünün doğrudan okumalarından çıkararak gerçek doğrusal ivmeyi elde edebilirsiniz.

Sensör koordinat sistemi, ivme sensörü tarafından kullanılan ve ölçü birimleri (m/sn2) tarafından kullanılan sistemle aynıdır.

Döndürme vektör sensörünü kullanma

Döndürme vektörü, cihazın yönünü bir açı ve eksenin bir kombinasyonu olarak gösterir. Bu açıda, cihaz bir eksen (x, y veya z) etrafında bir engelleme açısıyla döndürülmektedir. Aşağıdaki kodda, varsayılan dönme 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öndürme vektörünün üç öğesi şu şekilde ifade edilir:

x*sin(/2), y*sin(lerdeki/2), z*sin(lerdeki/2) ve

Bu durumda, dönme vektörünün büyüklüğü sin(rel/2) değerine eşittir ve dönme vektörünün yönü, dönme ekseninin yönüne eşittir.

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

Dönme vektörünün üç elemanı, bir birim dördüncünün son üç bileşenine (cos(circle/2), x*sin(puan/2), y*sin(∧/2), z*sin(başladı/2) eşittir. Döndürme 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 temel olarak tanımlanır (bkz. Şekil 1). Bu koordinat sistemi aşağıdaki özelliklere sahiptir:

  • X, Y x Z vektör çarpımı olarak tanımlanır. Cihazın mevcut konumunda zemine teğettir ve yaklaşık olarak Doğu'yu işaret eder.
  • Y, cihazın mevcut konumunda zemine teğettir ve jeomanyetik Kuzey Kutbu'na işaret eder.
  • Z gökyüzünü işaret eder ve yer düzlemine diktir.

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

Önemli hareket sensörünü kullanın

Anlamlı hareket sensörü, her önemli hareket algılandığında bir etkinliği 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 eden bir arabada oturma). Aşağıdaki kodda, varsayılan önemli hareket sensörünün bir örneğini nasıl alacağınız ve bir etkinlik işleyicinin 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 bilgiyi TriggerEventListener sayfasında bulabilirsiniz.

Adım sayacı sensörünü kullanma

Adım sayacı sensörü, kullanıcının, sensör etkinleştirildiği son yeniden başlatmadan bu yana attığı adım sayısını gösterir. Adım sayacının gecikme süresi (10 saniyeye kadar) ancak adım algılayıcı sensörüne göre 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 beyan etmeniz gerekir.

Aşağıdaki kodda, varsayılan adım sayacı 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 adım sayacı sensöründen belirli bir aralıktaki mevcut değeri almak üzere JobScheduler sınıfını kullanmanız gerekir. Farklı uygulama türleri için farklı sensör okuma aralıkları gerekse de uygulamanız sensörden gerçek zamanlı verilere ihtiyaç duymadığı 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 etkinliği tetikler. Gecikmenin 2 saniyenin altında olması bekleniyor.

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 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ışın

Aşağıdaki sensörler, uygulamanıza, cihaza uygulanan doğrusal ve döndürme 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ğer trendine bir yumuşatma algoritması uygulamanız da gerekebilir.

İvme ölçeri kullanma

İvme sensörü, cihaza uygulanan ivmeyi (yerçekimi kuvveti dahil) ölçer. Aşağıdaki kodda, varsayılan hızlanma 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 sonraki sürümleri hedefliyorsa bu sensör hızla sınırlıdır.

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

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

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

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

Bu nedenle, cihaz bir masada durduğunda (ve hızlanmadığında) ivme ölçer, g = 9,81 m/sn2 büyüklük gösterir. Benzer şekilde, cihaz serbest düşüşteyken ve bu nedenle yere doğru hızla 9,81 m/sn2 hızla hızlandığında, ivme ölçerin büyüklüğü g = 0 m/s2 olur. 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ş filtresi uygulayarak elde edilebilir. Buna karşılık, yerçekimi kuvvetini ayırt etmek için düşük geçiş filtresi kullanılabilir. Aşağıdaki örnekte bunu nasıl yapabileceğiniz gösterilmiştir:

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çişli filtre oluşturmak için basit bir filtre sabiti (alfa) kullanılmaktadır. Bu filtre sabiti, filtrenin sensör etkinliklerine eklediği gecikmenin ve sensörün etkinlik iletim hızının (dt) kabaca bir temsili olan zaman sabitinden (t) türetilir. Kod örneği, gösterim amacıyla 0,8 olan bir alfa değeri kullanı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. Pratikte bu, bir cihaz bir masanın üzerine doğal yönünde düz bir şekilde yerleştirildiğinde aşağıdaki koşulların geçerli olduğu anlamına gelir:

  • Cihazı sol tarafa iterseniz (bu şekilde sağa hareket eder) x ivme değeri pozitif olur.
  • Cihazı aşağı iterseniz (yani sizden uzaklaşır) y ivme değeri pozitif olur.
  • Cihazı gökyüzüne doğru A m/s2 ivmeyle iterseniz z ivmesi değeri A + 9, 81'e eşit olur. Bu da cihazın ivmesi (+A m/s2) eksi yer çekimi kuvvetine (-9, 81 m/s2) karşılık gelir.
  • Sabit cihazın +9,81 ivme değeri vardır. Bu değer, cihazın ivmesine karşılık gelir (0 m/sn2, yer çekimi kuvveti, -9,81 m/sn2).

Genel olarak, cihaz hareketini izliyorsanız ivme ölçer iyi bir sensördür. Android destekli hemen hemen her telefon ve tablette bir ivme ölçer bulunur ve diğer hareket sensörlerinden yaklaşık 10 kat daha az güç tüketir. Dezavantajlarından biri, yerçekimi kuvvetlerini ortadan kaldırmak ve gürültüyü azaltmak için düşük geçiş ve yüksek geçiş filtreleri uygulamak zorunda kalabilmenizdir.

Jiroskopu kullanma

Jiroskop, bir cihazın x, y ve z eksenleri etrafında dönüş hızını rad/s 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 sonraki sürümleri hedefliyorsa bu sensör hızla sınırlıdır.

Sensörün koordinat sistemi, ivme sensörü için kullanılan sistemle aynıdır. Saat yönünün tersine doğru döndürmedir. Yani, başlangıç noktasına yerleştirilmiş bir cihazda x, y veya z eksenindeki pozitif bir konumdan bakan gözlemci, cihaz saat yönünün tersine döndüğünde pozitif bir dönüş rapor eder. Bu, pozitif dönüşün standart matematiksel tanımıdır ve yön sensörü tarafından kullanılan yuvarlanma tanımıyla aynı değildir.

Genellikle, jiroskopun çıktısı, açı değişiminin zaman adımıyla açıklandığı bir dönüşü 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 (önyargı) için herhangi bir filtreleme veya düzeltme yapmadan ham dönme verileri sağlar. Pratikte, jiroskop gürültüsü ve kayması, düzeltilmesi gereken hatalara neden olur. Kayma (ön yargı) 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, jiroskop ile benzerdir ancak dönme hızına jiroskop telafisi uygulanmaz. Fabrika kalibrasyonu ve sıcaklık dengelemesi, dönüş hızına uygulanmaya devam etmektedir. Kalibre edilmemiş jiroskop, işleme sonrası ve yön verilerinin birleştirilmesinde kullanışlıdır. Genel olarak, gyroscope_event.values[0], uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3] civarındadır. Yani,

calibrated_x ~= uncalibrated_x - bias_estimate_x

Not: Kalibre edilmemiş sensörler daha fazla ham sonuç sağlar ve bir miktar sapma içerebilir ancak bu sensörlerin ölçümleri, kalibrasyon yoluyla uygulanan düzeltmelere ilişkin daha az atlama içerir. Bazı uygulamalar, daha düzgün ve güvenilir oldukları için kalibre edilmemiş bu sonuçları tercih edebilir. Örneğin, bir uygulama kendi sensör füzyonunu yürütmeye çalışıyorsa kalibrasyon uygulamak aslında sonuçları bozabilir.

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

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ı şekilde gösterir.

Ayrıca şunları da okumalısınız: