Android platformu, cihaz 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 ivme, dönme vektörü, önemli hareket, adım sayacı ve adım algılayıcı sensörler donanım tabanlı veya yazılım tabanlıdır.
- İvme ölçer ve jiroskop sensörleri her zaman donanıma dayalıdır.
Android destekli cihazların çoğunda ivmeölçer bulunur ve birçoğunda artık jiroskop da yer alır. Yazılıma dayalı sensörlerin kullanılabilirliği daha değişkendir. Çünkü bu sensörler, verilerini elde etmek için genellikle bir veya daha fazla donanım sensörüne bağlıdır. Cihaza bağlı olarak bu yazılıma dayalı sensörler, verilerini ivme ölçer ve manyetometreden ya da jiroskoptan alabilir.
Hareket sensörleri, cihaz hareketini (ör. eğme, sallama, döndürme veya sallanma) izlemek için kullanışlıdır. Hareket genellikle doğrudan kullanıcı girişinin bir yansımasıdır (örneğin, bir kullanıcının oyunda araba sürmesi veya topu kontrol etmesi). 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 cihaz konumunu izlemek için kullanılmaz. Ancak cihazın dünyanın 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ğerleri 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 float
dizisinde (values
) döndürülür. 1. tabloda, Android platformunda bulunan 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 hızlanma kuvveti (yer çekimi dahil). | m/s2 |
SensorEvent.values[1] |
y ekseni boyunca hızlanma 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/s2 |
SensorEvent.values[1] |
Y ekseni boyunca ölçülen ve herhangi bir sapma telafisi uygulanmamış ivme. | ||
SensorEvent.values[2] |
Herhangi bir sapma telafisi olmadan Z ekseni boyunca ölçülen ivme. | ||
SensorEvent.values[3] |
Tahmini sapma telafisi ile X ekseni boyunca ölçülen ivme. | ||
SensorEvent.values[4] |
Tahmini sapma telafisi ile Y ekseni boyunca ölçülen ivme. | ||
SensorEvent.values[5] |
Tahmini sapma telafisi ile Z ekseni boyunca ölçülen ivme. | ||
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/sn |
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ı (sapma telafisi olmadan). | rad/sn |
SensorEvent.values[1] |
Y ekseni etrafında 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 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/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] |
Dönüş vektörünün x ekseni üzerindeki bileşeni (x * sin(θ/2)). | Birim yok |
SensorEvent.values[1] |
Dönüş vektörünün y ekseni üzerindeki bileşeni (y * sin(θ/2)). | ||
SensorEvent.values[2] |
Dönüş vektörünün z ekseni üzerindeki 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 Skalar 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 çeşitli görevler için kullanılabilir. Örneğin, hareketleri algılama, açısal değişimi izleme ve göreceli yönlendirme değişikliklerini izleme gibi. Ö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ü ya da 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ıma dayalı üç hareket sensörü sağlar: yerçekimi sensörü, doğrusal ivme sensörü ve dönme vektörü sensörü. Bu sensörler Android 4.0'da güncellendi ve artık kararlılığı ve performansı artırmak için diğer sensörlerin yanı sıra cihazın jiroskopunu kullanıyor. Bu sensörleri denemek isterseniz getVendor()
yöntemi ve getVersion()
yöntemiyle tanımlayabilirsiniz (satıcı Google LLC, sürüm numarası 3'tür). Android sistemi bu üç sensörü ikincil sensörler olarak kabul ettiğinden bu sensörlerin satıcı 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örün tümü jiroskop kullanır. Cihazda 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 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ılan birimlerle (m/sn2) aynıdır ve koordinat sistemi, ivme sensörü tarafından kullanılan sistemle aynıdır.
Not: Bir cihaz dinlenirken 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ç olmak üzere her cihaz ekseni boyunca ivmeyi temsil eden üç boyutlu bir vektör sağlar. Bu değeri, hareket algılama işlemi gerçekleştirmek için kullanabilirsiniz. Bu değer, ölü hesaplama kullanan bir atalet navigasyon sistemine giriş olarak da hizmet edebilir. 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);
Bu sensör, kavramsal olarak aşağıdaki ilişkiye göre ivme verileri sağlar:
linear acceleration = acceleration - acceleration due to gravity
Bu sensörü genellikle yer çekiminin etkisini hesaba katmadan ivme verileri elde etmek istediğinizde kullanırsınız. Örneğin, bu sensörü kullanarak arabanızın hızını görebilirsiniz. Doğrusal ivme sensöründe her zaman bir sapma olur. Bu sapmayı 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ı ve ardından üç eksenin tamamı için dengelemeleri okumasını isteyebilirsiniz. Daha sonra gerçek doğrusal ivmeyi elde etmek için bu dengeyi ivme sensörünün doğrudan okumalarından çıkarabilirsiniz.
Sensör koordinat sistemi, ivme ölçer tarafından kullanılanla aynıdır. Ölçü birimleri (m/sn2) de 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 gösterir. Cihaz, bir eksen (x, y veya z) etrafında θ açısıyla dönmüştür. Aşağıdaki kodda, varsayılan döndürme 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:

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

1.şekil Dönüş vektörü sensörü tarafından kullanılan koordinat sistemi.
Dönüş vektörünün üç öğesi, birim kuaterniyonun son üç bileşenine (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)) eşittir. Dönüş vektörünün öğeleri birimsizdir. x, y ve z eksenleri, ivme ölçer 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örel çarpımı olarak tanımlanır. Cihazın mevcut konumunda yere teğettir ve yaklaşık olarak doğuya doğru bakar.
- Y, cihazın mevcut konumunda yere teğettir ve jeomanyetik Kuzey Kutbu'na doğru yönelir.
- Z, gökyüzüne doğru bakar ve yer 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 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. Örneğin, 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şleyicisini 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 sayacı sensörünü kullanma
Adım sayacı sensörü, son yeniden başlatmadan bu yana sensör etkinleştirilmişken kullanıcının attığı adım sayısını sağlar. Adım sayacı, adım algılama sensörüne göre daha fazla gecikmeye (10 saniyeye kadar) ancak daha fazla 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 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ın çalıştığı cihazlarda pil ömrünü korumak için belirli bir aralıkta adım sayacı sensöründen geçerli 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 gelen verilerin gerçek zamanlı olarak alınmasını gerektirmiyorsa bu aralığı mümkün olduğunca uzun tutmanız gerekir.
Adım algılama sensörünü kullanma
Adım algılama sensörü, kullanıcı her adım attığında bir etkinliği 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ılama 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, cihazda uygulanan doğrusal ve dönme kuvvetleri hakkında uygulamanıza ham veriler sağlar. Bu sensörlerden gelen değerleri etkili bir şekilde kullanmak için ortamdaki yer çekimi gibi faktörleri filtrelemeniz gerekir. Gürültüyü azaltmak için değerlerin trendine bir düzeltme algoritması da uygulamanız 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'yi (API düzeyi 31) veya daha yeni bir sürümü hedefliyorsa bu sensörün kullanım sıklığı sınırlandırılır.
Kavramsal olarak, bir ivmeölçer, aşağıdaki ilişkiyi kullanarak sensöre uygulanan kuvvetleri (Fs) ölçerek bir cihaza uygulanan ivmeyi (Ad) belirler:

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

Bu nedenle, cihaz bir masanın üzerinde dururken (ve hızlanmıyorken) ivmeölçer, g = 9,81 m/s2 büyüklüğünde bir değer okur. Benzer şekilde, cihaz serbest düşüşteyken ve bu nedenle 9,81 m/sn2 hızla yere doğru hızlanırken ivmeölçer, g = 0 m/sn2 büyüklüğünde bir değer okur. Bu nedenle, cihazın gerçek ivmesini ölçmek için yerçekimi kuvvetinin katkısının ivmeölçer verilerinden çıkarılması gerekir. Bu, yüksek geçiren filtre uygulanarak elde edilebilir. Bunun aksine, yer çekimi kuvvetini izole etmek için alçak geçiren filtre kullanılabilir. Bunu nasıl yapabileceğiniz aşağıdaki örnekte 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ılmaktadır. Bu filtre sabiti, filtrenin sensör etkinliklerine eklediği gecikmeyi kabaca temsil eden bir zaman sabiti (t) ve sensörün etkinlik teslim hızı (dt) değerlerinden elde edilir. Kod örneğinde, gösterim amacıyla 0,8 alfa değeri kullanılmaktadı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 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ı alttan iterseniz (sizden uzaklaşacak şekilde) y yönündeki 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 ivmesine (+A m/sn2) eksi yer çekimi kuvvetine (-9,81 m/sn2) karşılık gelir.
- Sabit cihazın ivme değeri +9,81 olur. Bu değer, cihazın ivmesine (0 m/sn2 eksi yer çekimi kuvveti, yani -9,81 m/sn2) karşılık gelir.
Genel olarak, cihaz hareketini izliyorsanız ivme ölçer iyi bir sensördür. Android destekli hemen her telefonda ve tablette ivmeölçer bulunur. Bu sensör, diğer hareket sensörlerine kıyasla yaklaşık 10 kat daha az güç kullanır. Bir dezavantajı, 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 gerekebilmesidir.
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 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'yi (API düzeyi 31) veya daha yeni bir sürümü hedefliyorsa bu sensörün kullanım sıklığı sınırlandırılır.
Sensörün koordinat sistemi, ivme ölçer için kullanılanla aynıdır. Dönüş, saat yönünün tersine doğru pozitiftir. Yani, x, y veya z ekseninde pozitif bir konumdan orijinde konumlandırılmış bir cihaza bakan bir gözlemci, cihaz saat yönünün tersine dönüyormuş gibi görü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 yuvarlanma tanımıyla aynı değildir.
Genellikle, jiroskopun çıkışı, zaman adımı boyunca açıların değişimini açıklayan bir dönüşümü 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 kayma (yanlılık) için herhangi bir filtreleme veya düzeltme olmadan ham dönme verileri sağlar. Pratikte, jiroskop gürültüsü ve kayması, telafi edilmesi gereken hatalara yol açar. Sapmayı (önyargı) 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 kayması telafisi uygulanmaması dışında jiroskopa benzer. Fabrika kalibrasyonu ve sıcaklık telafisi, dönüş hızı için geçerli olmaya devam eder. Kalibre edilmemiş jiroskop, işleme sonrası ve yönlendirme 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 fazla ham sonuç sağlar ve bazı sapmalar içerebilir ancak ölçümleri, kalibrasyon yoluyla uygulanan düzeltmelerden daha az atlama içerir. Bazı uygulamalar, bu kalibre edilmemiş sonuçları daha sorunsuz ve güvenilir bulabilir. Ö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ının yanı sıra her eksen etrafındaki 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.