Hareket sensörleri

Android platformu, hareketi izleyebilmenizi sağlayan çeşitli sensörler sağlar. bir şekilde tanımlar.

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

  • Yer çekimi, doğrusal ivme, dönme vektörü, önemli hareket, adım sensör ve adım dedektörü sensörleri donanım tabanlı veya her şeyi kapsıyor.
  • İ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 çoğunda bir ivme ölçer vardır. jiroskop. Yazılım tabanlı sensörlerin kullanılabilirliği Çünkü çoğu zaman bir veya daha fazla donanım sensörünü kullanarak dışı verilerdir. Cihaza bağlı olarak bu yazılım tabanlı sensörler, ya da ivme ölçerden veya jiroskoptan alınan verileri toplar.

Hareket sensörleri; eğme, titreme, döndürme veya kullanabilirsiniz. Bu hareket genellikle doğrudan kullanıcı girişlerini (örneğin, bir kullanıcıyı doğrudan veya oyunda topu kontrol eden bir kullanıcı) temsil eder. Ancak bu durum, oyunun cihazın bulunduğu fiziksel ortamın (örneğin, araç kullanırken yanınızda olması) arabanızda . İlk örnekte, cihazın referans çerçevesine göre hareketi izliyorsunuz veya uygulamanızın referans çerçevesi; ikincisinde gözlemlediğiniz özelliklere göre düşünülebilir. Hareket sensörleri genellikle izleme amacıyla kullanılmaz. Ancak daha başka sensörlerle örneğin, jeomanyetik alan sensörü gibi bir cihazın konumunu dünyanın referans çerçevesine göre belirler (daha fazla bilgi için Konum Sensörleri konusuna bakın ) ekleyin.

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 eksenine ilişkin ivme kuvveti verileri ve jiroskop dönüş hızını döndürür verileri de içerir. Bu veri değerleri bir float dizisinde döndürülür (values) ve diğer SensorEvent parametreleridir. 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(∧/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 son yeniden başlatmadan bu yana kullanıcının gerçekleştirdiği adım sayısı etkinleştirildi. 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 için en sık kullanılan sensörlerdir tespiti ve takibidir. Dönme vektör sensörü özellikle çok yönlüdür ve çeşitli açılardan hareketleri algılama, açısal değişiklikleri izleme ve göreceli yön değişikliklerini izleme. Örneğin, dönme jenerasyonunu oyun, artırılmış gerçeklik uygulaması, 2 boyutlu veya 3 boyutlu pusula, kamera sabitleme uygulaması kullanabilirsiniz. Çoğu durumda, bu sensörleri kullanmak ivme ölçer ve jeomanyetik alan sensörü veya yön sensörü olabilir.

Android Açık Kaynak Projesi sensörleri

Android Açık Kaynak Projesi (AOSP) yazılım tabanlı üç hareket sensörü sağlar: yerçekimi doğrusal ivme sensörü ve dönüş vektörü sensörünü içerir. Bu sensörlerin güncellendiği zaman: Android 4.0 çalıştıran ve artık stabiliteyi artırmak ve diğer sensörlere ek olarak bir cihazın jiroskopunu bazı yolları da görmüştük. Denemek istediğiniz bu sensörleri, getVendor() ve getVersion() yöntemleriyle tanıyabilirsiniz (tedarikçi firma Google LLC'dir; sürüm numarası 3'tür). Bu sensörleri tedarikçi firmaya ve Android sistemi bu üç sensörü ikincil sensör olarak algıladığı için sürüm numarası gereklidir olabilir. Ö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 bir jiroskop: Bir cihazda jiroskop yoksa bu sensörler görünmez ve kullanılabilir.

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

Yer çekimi sensörü, bu hareketin yerini gösteren üç boyutlu bir vektör yer çekiminin yönünü ve büyüklüğünü değiştirirsiniz. Genellikle bu sensör, cihazın cihazın uzaydaki göreceli yönünü. Aşağıdaki kodda bu işlemin nasıl varsayılan yer çekimi sensörünün bir örneğini al:

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, hızlandırma tarafından kullanılanlarla aynıdır. sensör (m/sn2) ve koordinat sistemi ivme sensörüne sahiptir.

Not: Cihaz aktif değilken yerçekimi sensörünün çıkışı ivme ölçerinkiyle aynı olmalıdır.

Doğrusal ivme ölçeri kullanma

Doğrusal ivme sensörü, size üç boyutlu bir vektörel yerçekimi hariç her bir cihaz eksenindeki ivmeyi temsil eder. Tekliflerinizi otomatikleştirmek ve optimize etmek için bu değeri kullanabilirsiniz. Değer, aynı zamanda bir aracılı hareket ettirme sistemidir. Aşağıdaki kodda varsayılan doğrusal ivme sensörünün bir örneğini nasıl alırsınız:

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 değerlere göre size ivme verilerini sağlar. ilişki:

linear acceleration = acceleration - acceleration due to gravity

Genellikle bu sensörü, hızın etkisi olmadan ivme verilerini elde etmek istediğinizde yerçekimi. Ö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. Bunu kaldırmanız gerekir. Bunu yapmanın en basit yolu bir kalibrasyon adımı oluşturmanız gerekir. Kalibrasyon sırasında kullanıcıdan ardından, üç eksenin ofsetlerini okumak. Daha sonra bu değerden gerçek doğrusal değeri elde etmek için ivme sensörünün doğrudan ölçümlerinden uzaklık ivme artışı.

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

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

Döndürme vektörü, açı ile cihazın yönünün bir kombinasyonu olarak cihazın bir eksen (x, y veya z) eksenindeki bir engelleme açısıyla döndürüldüğü eksendir. Aşağıdakiler kodu, varsayılan dönme vektör sensörünün 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_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

Dönme vektörünün büyüklüğü sin(∧/2) ve dönüş vektörünün yönünün dönme vektörü, dönme ekseninin yönüne eşittir.

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

Döndürme vektörünün üç elemanı, bir birimin son üç bileşenine eşittir kuaterniyon (cos(∧/2), x*sin(∧/2), y*sin(∧/2), z*sin(∧/2)). 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. Bu, projenin ve yaklaşık Doğu'yu işaret ediyor.
  • Y, cihazın mevcut konumunda zemine teğettir ve jeomanyetik kuzey Kutbu.
  • 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 işlemiyle bağlantılıdır.

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

Anlamlı hareket sensörü, önemli bir hareket algılandığında bir etkinliği tetikler ve kendini devre dışı bırakır. Önemli bir hareket, değişime yol açabilecek bir harekettir kullanıcının konumu; Örneğin yürüme, bisiklete binme veya hareket eden bir arabada oturma gibi. Aşağıdaki kodda Varsayılan önemli hareket sensörünün örneği nasıl alınır ve bir etkinlik nasıl kaydedilir? dinleyici:

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 son yeniden başlatmadan bu yana attığı adım sayısını sağlar sensör etkinleştiğinde. Adım sayacında daha fazla gecikme (10 saniyeye kadar) ancak daha fazla gecikme var daha doğru sonuçlar verir.

Not: ACTIVITY_RECOGNITION uygulamanızın bu sensörü çalışan cihazlarda kullanması için izin verin Android 10 (API düzeyi 29) veya sonraki sürümler.

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

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 Geçerli değerin alınacağı JobScheduler sınıf adım sayacı sensörüne otomatik olarak eklenir. Her ne kadar farklı türde için farklı sensör okuma aralıklarına ihtiyacınız varsa bu aralığı mümkün olduğunca uzun süre tanıyın.

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. Gecikme 2 saniyeden kısa olması beklenir.

Not: ACTIVITY_RECOGNITION uygulamanızın bu sensörü çalışan cihazlarda kullanması için izin verin Android 10 (API düzeyi 29) veya sonraki sürümler.

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

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 doğrusal ve örtüşen görüntüler hakkında ham veriler sağlar Cihaza uygulanan dönme kuvveti. Arkadaş Bitkiler projesinin bu sensörleri etkili şekilde kullanmak için çevresel, yer çekimi gibi. Trende bir yumuşatma algoritması uygulamanız da gerekebilir. farklı değerler kullanabilirsiniz.

İvme ölçeri kullanma

Bir ivme sensörü, cihaza uygulanan ivmeyi ölçer. Buna kuvvet de dahildir yerçekimi. 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 bu sensör daha yüksek sıralı olarak sınırlandırılmıştır.

Kavramsal olarak ivme sensörü, uygulanan ivmeyi belirler sensöre uygulanan kuvvetleri ölçerek (d) cihaza şu ilişkiyi kullanarak kendisi (Fs) olarak değiştirin:

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

Ancak yer çekimi kuvveti her zaman şu ilişki:

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üğünü okur. Benzer şekilde, cihaz Yere doğru 9,81 m/sn2 hızla hızlanıyorsa, ivme ölçer, g = 0 m/sn2 büyüklüğünü okur. Bu nedenle, cihazın gerçek ivmesi, yer çekimi kuvvetinin katkısı ivme ölçer verilerini görebilirsiniz. Bu, yüksek geçiş filtresi uygulayarak elde edilebilir. Öte yandan, düşük geçişli yerçekimi kuvvetini izole etmek için kullanılabilir. Aşağıdaki örnekte, farklı reklam biçimlerini nasıl bu:

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 sabit değeri, zaman sabitinden (t) türetilir; bu, ilgili süreye ilişkin gecikmenin kabaca bir temsilidir. filtre, sensör etkinliklerini ve sensörün etkinlik iletim hızını (dt) ekler. Kod örneği özelliğinin alfa değeri olarak 0,8 kullanılmıştır. Bu filtreleme yöntemini kullanıyorsanız farklı bir alfa değeri seçin.

İvme ölçerler standart sensör koordinatını kullanır hakkında bilgi edinin. Pratikte bu, cihaz döşeme sırasında aşağıdaki koşulların geçerli olduğu anlamına gelir bir tablo üzerinde doğal yönünde düz olarak:

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

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 bu cihaz yaklaşık 10 kez ivme ölçer. daha az güç tüketiyor. Dezavantajlarından biri de düşük geçişli ve yüksek geçişli filtrelerle yer çekimi kuvvetlerini ortadan kaldırır ve gürültüyü azaltır.

Jiroskopu kullanma

Jiroskop, bir cihazın x, y ve etrafında dönme hızını rad/s cinsinden ölçer z eksenini seçin. 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 bu sensör daha yüksek sıralı olarak sınırlandırılmıştır.

Sensörün koordinat sistemi ivme sensörü için kullanılanla aynıdır. Rotasyon pozitif saat yönünün tersine; gözlemci tarafından başlangıç noktasında bulunan bir cihazdaki x, y veya z eksenindeki bazı pozitif konumlardan cihaz saat yönünün tersine dönüyormuş gibi görünüyorsa pozitif döndürme. Bu, pozitif rotasyonun standart matematiksel tanımıdır ve Yön sensörü tarafından kullanılan rulo.

Genellikle, jiroskopun çıktısı zaman içinde entegre edilerek açıklığa kavuşturulan bir döndürme hareketi açı değişimini görebilirsiniz. Ö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 renk değişimleri için herhangi bir filtreleme veya düzeltme yapmadan ham dönme verileri sağlar. kayma (ön yargı). Pratikte, jiroskop gürültüsü ve kayması, dikkat edilmesi gereken hatalara neden olacaktır. yardımcı olur. Kaymayı (ön yargı) ve gürültüyü genellikle aşağıdakiler gibi diğer sensörleri izleyerek belirleyebilirsiniz: olarak kullanabilirsiniz.

Kalibre edilmemiş jiroskopu kullanma

Kalibre edilmemiş jiroskop jiroskop'a benzer, Tek fark, dönüş hızına jiroskop telafisi uygulanmamasıdır. Fabrika kalibrasyonu ve sıcaklık dengelemesi, dönüş hızına uygulanmaya devam etmektedir. Kalibre edilmemiş jiroskop, ileri işleme ve yön verilerinin eritilmesinde yararlıdır. Genel olarak gyroscope_event.values[0], şuna yakın olacak: uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]. Yani,

calibrated_x ~= uncalibrated_x - bias_estimate_x

Not: Kalibre edilmemiş sensörler daha fazla ham sonuç sağlar ve bazı sapmaları da içerir, ancak ölçümlerine kalibrasyondur. Bazı uygulamalar, kalibre edilmemiş bu sonuçları daha akıcı ve etkili olduğu için tercih edebilir. yardımcı olur. Örneğin, bir uygulama kendi sensör füzyonunu yapmaya çalışıyorsa Hatta kalibrasyon uygulamak sonuçları bozabilir.

Kalibre edilmemiş jiroskop, dönüş hızlarına ek olarak yaklaşık 80 metredir. Aşağıdaki kodda, varsayılan öğenin bir örneğini nasıl alacağınız gösterilmektedir kalibre edilmemiş jiroskop:

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

İlgili içeriği oluşturmak için kullanılan BatchStepSensor örneği ayrıca şunları gösterir: API'lerin kullanımını devre dışı bırakabilirsiniz.

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