Sensor gerakan

Platform Android menyediakan beberapa sensor yang memungkinkan Anda memantau gerakan perangkat.

Sensor kemungkinan arsitektur bervariasi berdasarkan jenis sensor:

  • Gravitasi, akselerasi linier, vektor rotasi, gerakan signifikan, langkah penghitung, dan sensor detektor langkah berbasis perangkat keras atau berbasis software.
  • Sensor akselerometer dan giroskop selalu berbasis hardware.

Sebagian besar perangkat Android memiliki akselerometer, dan banyak lagi yang menyertakan giroskop. Ketersediaan sensor berbasis software jauh lebih variabel karena sering kali bergantung pada satu atau lebih sensor perangkat keras untuk mendapatkan layanan otomatis dan data skalabel. Tergantung pada perangkatnya, sensor berbasis perangkat lunak ini dapat memperoleh data baik dari akselerometer dan magnetometer atau dari giroskop.

Sensor gerakan berguna untuk memantau pergerakan perangkat, seperti kemiringan, guncangan, rotasi, atau ayunan. Gerakannya biasanya merupakan refleksi dari input langsung pengguna (misalnya, pengguna yang mengarahkan mobil dalam game atau pengguna mengendalikan bola dalam game), tetapi juga bisa menjadi cerminan dari lingkungan fisik tempat perangkat berada (misalnya, bergerak bersama Anda saat mengemudi mobil Anda). Dalam kasus pertama, Anda memantau gerakan yang relatif terhadap bingkai referensi perangkat atau kerangka referensi aplikasi Anda; dalam kasus kedua, Anda memantau gerakan relatif terhadap kerangka referensi dunia. Sensor gerakan sendiri biasanya tidak digunakan untuk memantau posisi perangkat, tetapi juga dapat digunakan dengan sensor lain, seperti sensor medan geomagnetik, untuk menentukan posisi perangkat relatif terhadap bingkai referensi dunia (lihat Sensor Posisi untuk informasi tertentu).

Semua sensor gerakan menampilkan array nilai sensor multi-dimensi untuk setiap SensorEvent. Misalnya, selama peristiwa sensor tunggal, akselerometer akan menampilkan data gaya akselerasi untuk ketiga sumbu koordinat, dan giroskop menampilkan laju rotasi data untuk ketiga sumbu koordinat. Nilai data ini ditampilkan dalam array float (values) bersama SensorEvent lainnya parameter. Tabel 1 merangkum sensor gerak yang tersedia di platform Android.

Tabel 1. Sensor gerakan yang didukung di platform Android.

Sensor Data peristiwa sensor Deskripsi Satuan ukuran
TYPE_ACCELEROMETER SensorEvent.values[0] Gaya akselerasi di sepanjang sumbu x (termasuk gravitasi). m/d2
SensorEvent.values[1] Gaya akselerasi di sepanjang sumbu y (termasuk gravitasi).
SensorEvent.values[2] Gaya akselerasi di sepanjang sumbu z (termasuk gravitasi).
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] Akselerasi terukur di sepanjang sumbu X tanpa kompensasi bias. m/d2
SensorEvent.values[1] Akselerasi terukur di sepanjang sumbu Y tanpa kompensasi bias.
SensorEvent.values[2] Akselerasi terukur di sepanjang sumbu Z tanpa kompensasi bias.
SensorEvent.values[3] Akselerasi terukur di sepanjang sumbu X dengan estimasi kompensasi bias.
SensorEvent.values[4] Akselerasi terukur di sepanjang sumbu Y dengan estimasi kompensasi bias.
SensorEvent.values[5] Akselerasi terukur di sepanjang sumbu Z dengan estimasi kompensasi bias.
TYPE_GRAVITY SensorEvent.values[0] Gaya gravitasi di sepanjang sumbu x. m/d2
SensorEvent.values[1] Gaya gravitasi di sepanjang sumbu y.
SensorEvent.values[2] Gaya gravitasi di sepanjang sumbu z.
TYPE_GYROSCOPE SensorEvent.values[0] Laju rotasi di sekitar sumbu x. rad/s
SensorEvent.values[1] Laju rotasi di sekitar sumbu y.
SensorEvent.values[2] Laju rotasi di sekitar sumbu z.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] Laju rotasi (tanpa kompensasi drift) di sekitar sumbu x. rad/s
SensorEvent.values[1] Laju rotasi (tanpa kompensasi drift) di sekitar sumbu y.
SensorEvent.values[2] Laju rotasi (tanpa kompensasi drift) di sekitar sumbu z.
SensorEvent.values[3] Estimasi drift di sekitar sumbu x.
SensorEvent.values[4] Estimasi drift di sekitar sumbu y.
SensorEvent.values[5] Estimasi drift di sekitar sumbu z.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] Gaya akselerasi di sepanjang sumbu x (tidak termasuk gravitasi). m/d2
SensorEvent.values[1] Gaya akselerasi di sepanjang sumbu y (tidak termasuk gravitasi).
SensorEvent.values[2] Gaya akselerasi di sepanjang sumbu z (tidak termasuk gravitasi).
TYPE_ROTATION_VECTOR SensorEvent.values[0] Komponen vektor rotasi sepanjang sumbu x (x * sin(θ/2)). Tanpa unit
SensorEvent.values[1] Komponen vektor rotasi sepanjang sumbu y (y * sin(θ/2)).
SensorEvent.values[2] Komponen vektor rotasi di sepanjang sumbu z (z * sin(θ/2)).
SensorEvent.values[3] Komponen skalar dari vektor rotasi ((cos(pertunjukan/2)).1
TYPE_SIGNIFICANT_MOTION T/A T/A T/A
TYPE_STEP_COUNTER SensorEvent.values[0] Jumlah langkah yang diambil pengguna sejak reboot terakhir saat sensor diaktifkan. Langkah
TYPE_STEP_DETECTOR T/A T/A T/A

1 Komponen skalar adalah nilai opsional.

Sensor vektor rotasi dan sensor gravitasi adalah sensor yang paling sering digunakan untuk gerakan deteksi dan pemantauan model. Sensor vektor rotasi sangat serbaguna dan dapat digunakan untuk berbagai tugas terkait gerakan, seperti mendeteksi {i>gesture<i}, memantau perubahan sudut, dan memantau perubahan orientasi relatif. Misalnya, sensor vektor rotasi ideal jika Anda mengembangkan game, aplikasi augmented reality, kompas 2 dimensi atau 3 dimensi, atau aplikasi stabilisasi kamera. Dalam kebanyakan kasus, menggunakan sensor ini adalah pilihan yang lebih baik daripada menggunakan akselerometer dan sensor medan geomagnetik atau sensor orientasi.

Sensor Proyek Open Source Android

Proyek Open Source Android (AOSP) menyediakan tiga sensor gerakan berbasis software: sensor gravitasi sensor, sensor akselerasi linear, dan sensor vektor rotasi. Sensor ini diperbarui di Android 4.0 dan kini menggunakan giroskop perangkat (selain sensor lainnya) untuk meningkatkan stabilitas dan tingkat tinggi. Jika ingin mencoba sensor ini, Anda dapat mengidentifikasinya menggunakan metode getVendor() dan metode getVersion() (vendornya adalah Google LLC; nomor versinya adalah 3). Mengidentifikasi sensor-sensor ini berdasarkan vendor dan nomor versi diperlukan karena sistem Android menganggap ketiga sensor ini sebagai sensor. Misalnya, jika produsen perangkat menyediakan sensor gravitasi mereka sendiri, model AOSP sensor gravitasi muncul sebagai sensor gravitasi sekunder. Ketiga sensor ini bergantung pada giroskop: jika perangkat tidak memiliki giroskop, sensor ini tidak akan muncul dan tidak muncul yang tersedia untuk digunakan.

Gunakan sensor gravitasi

Sensor gravitasi menyediakan vektor tiga dimensi yang menunjukkan arah dan besaran gravitasi. Biasanya, sensor ini digunakan untuk menentukan orientasi relatif perangkat di ruang angkasa. Kode berikut menunjukkan cara mendapatkan instance sensor gravitasi default:

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

Satuan sama dengan yang digunakan oleh akselerasi sensor (m/s2), dan sistem koordinatnya sama dengan yang digunakan oleh sensor akselerasi.

Catatan: Saat perangkat dalam keadaan istirahat, output sensor gravitasi harus identik dengan akselerometer.

Gunakan akselerometer linear

Sensor akselerasi linear menyediakan vektor tiga dimensi yang mewakili akselerasi di sepanjang setiap sumbu perangkat, tidak termasuk gravitasi. Anda dapat menggunakan nilai ini untuk melakukan deteksi gestur. Nilai ini juga dapat berfungsi sebagai input sistem navigasi inersia, yang menggunakan perhitungan mati. Kode berikut menunjukkan cara mendapatkan instance sensor akselerasi linear default:

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

Secara konseptual, sensor ini memberi Anda data akselerasi sesuai dengan yang berikut hubungan:

linear acceleration = acceleration - acceleration due to gravity

Anda biasanya menggunakan sensor ini ketika ingin mendapatkan data akselerasi tanpa pengaruh gravitasi. Misalnya, Anda dapat menggunakan sensor ini untuk melihat seberapa cepat mobil Anda berjalan. Garis sensor akselerasi selalu memiliki offset, yang harus Anda hapus. Cara paling sederhana untuk melakukan ini adalah untuk membuat langkah kalibrasi ke dalam aplikasi Anda. Selama kalibrasi, Anda dapat meminta pengguna untuk mengatur perangkat di atas meja, lalu membaca offset untuk ketiga sumbu. Anda kemudian dapat menguranginya dengan offset dari pembacaan langsung sensor akselerasi untuk mendapatkan dan percepatan.

Koordinat sensor sistem sama dengan yang digunakan oleh sensor akselerasi, sama seperti satuan ukuran (m/d2).

Gunakan sensor vektor rotasi

Vektor rotasi merepresentasikan orientasi perangkat sebagai kombinasi sudut dan sumbu, di mana perangkat telah diputar melalui sudut ditunjukkan di sekitar sumbu (x, y, atau z). Hal berikut kode ini menunjukkan cara mendapatkan instance sensor vektor rotasi default:

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

Tiga elemen vektor rotasi dinyatakan sebagai berikut:

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

Di mana besarnya vektor rotasi sama dengan sin(bergantian/2), dan arah vektor rotasi sama dengan arah sumbu rotasi.

Gambar 1. Sistem koordinat yang digunakan oleh sensor vektor rotasi.

Tiga elemen vektor rotasi sama dengan tiga komponen terakhir dari suatu unit kuarternion (cos( komunitas / 2), x*sin(( ) /2), y*sin(( ), z*sin (( ) / 2)). Elemen vektor rotasi adalah tanpa unit. Sumbu x, y, dan z ditentukan dengan cara yang sama seperti sensor akselerasi. Referensi sistem koordinat didefinisikan sebagai basis ortonormal langsung (lihat gambar 1). Sistem koordinat ini memiliki karakteristik berikut:

  • X didefinisikan sebagai produk vektor Y x Z. Bentuk ini bersinggungan dengan ke tanah di lokasi perangkat saat ini dan menunjuk sekitar Timur.
  • Y bersinggungan dengan tanah di lokasi perangkat saat ini dan menunjuk ke arah geomagnetik Kutub Utara.
  • Z menunjuk ke arah langit dan tegak lurus dengan bidang tanah.

Untuk aplikasi contoh yang menunjukkan cara menggunakan sensor vektor rotasi, lihat RotationVectorDemo.java.

Gunakan sensor gerak yang signifikan

Sensor gerakan yang signifikan memicu suatu peristiwa setiap kali gerakan signifikan terdeteksi dan maka sistem itu mati sendiri. {i>Motion <i}yang signifikan adalah {i>motion <i}yang dapat menyebabkan perubahan dalam lokasi pengguna; misalnya berjalan, bersepeda, atau duduk di dalam mobil yang bergerak. Kode berikut menunjukkan cara mendapatkan instance sensor gerakan signifikan default dan cara mendaftarkan peristiwa pemroses:

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

Untuk informasi selengkapnya, lihat TriggerEventListener.

Gunakan sensor penghitung langkah

Sensor penghitung langkah menyediakan jumlah langkah yang diambil pengguna sejak reboot terakhir saat sensor diaktifkan. Penghitung langkah memiliki lebih banyak latensi (hingga 10 detik) tetapi lebih dibandingkan sensor detektor langkah.

Catatan: Anda harus menyatakan ACTIVITY_RECOGNITION izin agar aplikasi Anda dapat menggunakan sensor ini pada perangkat yang menjalankan Android 10 (level API 29) atau yang lebih tinggi.

Kode berikut menunjukkan cara mendapatkan instance langkah default sensor penghitung:

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

Untuk menghemat baterai pada perangkat yang menjalankan aplikasi Anda, Anda harus menggunakan Class JobScheduler untuk mengambil nilai saat ini dari sensor penghitung langkah pada interval tertentu. Meskipun berbagai jenis aplikasi memerlukan interval pembacaan sensor yang berbeda, Anda harus membuat interval ini selama mungkin kecuali aplikasi Anda memerlukan data real-time dari sensor.

Gunakan sensor pendeteksi langkah

Sensor langkah detektor memicu suatu peristiwa setiap kali pengguna melangkah. Latensinya adalah diharapkan berdurasi di bawah 2 detik.

Catatan: Anda harus menyatakan ACTIVITY_RECOGNITION izin agar aplikasi Anda dapat menggunakan sensor ini pada perangkat yang menjalankan Android 10 (level API 29) atau yang lebih tinggi.

Kode berikut menunjukkan cara mendapatkan instance langkah default sensor detektor:

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

Bekerja dengan data mentah

Sensor berikut memberi aplikasi Anda data mentah tentang linear dan gaya rotasi yang diterapkan ke perangkat. Untuk menggunakan nilai-nilai dari sensor-sensor ini secara efektif, Anda perlu memfilter faktor-faktor dari lingkungan, seperti gravitasi. Anda mungkin juga perlu menerapkan algoritma penghalusan tren nilai untuk mengurangi derau.

Gunakan akselerometer

Sensor akselerasi mengukur akselerasi yang diterapkan pada perangkat, termasuk gaya gravitasi. Kode berikut ini menunjukkan cara mendapatkan instance sensor akselerasi default:

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

Catatan: Jika aplikasi Anda menargetkan Android 12 (API level 31) atau lebih tinggi, sensor ini pembatasan kapasitas.

Secara konseptual, sensor akselerasi menentukan akselerasi yang diterapkan ke perangkat (Ad) dengan mengukur gaya yang diterapkan pada sensor itu sendiri (Fs) menggunakan hubungan berikut:

A_D=-(1/massa)∑F_S

Namun, gaya gravitasi selalu mempengaruhi percepatan yang diukur menurut hubungan berikut:

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

Karena alasan ini, ketika perangkat diletakkan di atas meja (dan tidak berakselerasi), akselerometer membaca magnitudo g = 9,81 m/s2. Demikian pula, bila perangkat berada jatuh bebas sehingga dipercepat dengan cepat ke tanah pada 9,81 m/s2, akselerometer membaca magnitudo g = 0 m/s2. Oleh karena itu, untuk mengukur percepatan nyata perangkat, kontribusi gaya gravitasi harus dihilangkan dari data akselerometer. Ini dapat dilakukan dengan menerapkan filter high-pass. Sebaliknya, low-pass filter dapat digunakan untuk mengisolasi gaya gravitasi. Contoh berikut menunjukkan cara melakukan ini:

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

Catatan: Anda dapat menggunakan berbagai teknik untuk memfilter data sensor. Contoh kode di atas menggunakan konstanta filter sederhana (alfa) untuk membuat filter low-pass. Filter ini berasal dari konstanta waktu (t), yang merupakan representasi kasar dari latensi yang filter ditambahkan ke kejadian sensor, dan laju pengiriman peristiwa (dt) sensor. Contoh kode menggunakan nilai alfa 0,8 untuk tujuan demonstrasi. Jika Anda menggunakan metode pemfilteran ini, Anda mungkin perlu memilih nilai alfa yang berbeda.

Akselerometer menggunakan koordinat sensor standar sistem. Dalam praktiknya, ini berarti bahwa kondisi berikut berlaku saat perangkat diletakkan datar di atas meja dalam orientasi naturalnya:

  • Jika Anda mendorong perangkat ke sisi kiri (sehingga bergerak ke kanan), nilai akselerasi x bernilai positif.
  • Jika Anda mendorong perangkat ke bagian bawah (sehingga menjauh dari Anda), nilai akselerasi y adalah positif.
  • Jika Anda mendorong perangkat ke arah langit dengan akselerasi A m/s2, nilai akselerasi z sama dengan A + 9,81, yang sesuai dengan percepatan perangkat (+A m/d2) dikurangi gaya gravitasi (-9,81 m/d2).
  • Perangkat yang diam akan memiliki nilai akselerasi sebesar +9,81, yang sesuai dengan percepatan perangkat (0 m/s2 dikurangi gaya gravitasi, yaitu -9,81 m/d2).

Secara umum, akselerometer adalah sensor yang baik untuk digunakan jika Anda memantau gerakan perangkat. Hampir setiap handset dan tablet berbasis Android memiliki akselerometer, dan menggunakan sekitar 10 kali daya yang lebih kecil dibandingkan sensor gerakan lainnya. Satu kelemahannya adalah Anda mungkin harus menerapkan filter low-pass dan high-pass untuk menghilangkan gaya gravitasi dan mengurangi derau.

Gunakan giroskop

Giroskop mengukur laju rotasi dalam rad/s di sekitar x, y, dan sumbu z. Kode berikut menunjukkan cara mendapatkan instance giroskop default:

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

Catatan: Jika aplikasi Anda menargetkan Android 12 (API level 31) atau lebih tinggi, sensor ini pembatasan kapasitas.

Sistem koordinat sensor sama dengan yang digunakan untuk sensor akselerasi. Rotasi bernilai positif dalam berlawanan arah jarum jam; yaitu, seorang pengamat yang melihat dari beberapa lokasi positif pada sumbu x, y, atau z di perangkat yang diposisikan pada asal akan melaporkan rotasi positif jika perangkat tampak berputar berlawanan arah jarum jam. Ini adalah matematis standar dari rotasi positif dan tidak sama dengan definisi untuk {i>roll <i}yang digunakan oleh sensor orientasi.

Biasanya, output giroskop terintegrasi dari waktu ke waktu untuk menghitung rotasi yang menggambarkan perubahan sudut pada penunjuk waktu. Contoh:

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

Giroskop standar menyediakan data rotasi mentah tanpa pemfilteran atau koreksi apa pun untuk kebisingan dan penyimpangan (bias). Dalam praktiknya, kebisingan dan penyimpangan giroskop akan menghasilkan kesalahan yang perlu kompensasi. Anda biasanya menentukan penyimpangan (bias) dan kebisingan dengan memantau sensor lain, seperti seperti sensor gravitasi atau akselerometer.

Gunakan giroskop yang tidak dikalibrasi

Giroskop yang tidak dikalibrasi mirip dengan giroskop, kecuali jika tidak ada kompensasi giroskop yang diterapkan pada laju rotasi. Kalibrasi pabrik dan kompensasi suhu masih diterapkan pada laju rotasi. Metrik yang tidak dikalibrasi giroskop berguna untuk data orientasi pascapemrosesan dan peleburan. Secara umum, gyroscope_event.values[0] akan dekat dengan uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]. Yaitu,

calibrated_x ~= uncalibrated_x - bias_estimate_x

Catatan: Sensor yang tidak dikalibrasi memberikan lebih banyak hasil mentah dan dapat menyertakan beberapa bias, tetapi pengukurannya berisi lebih sedikit lompatan dari koreksi yang diterapkan untuk kalibrasi. Beberapa aplikasi mungkin lebih memilih hasil yang tidak dikalibrasi ini karena lebih lancar dan lebih dapat diandalkan. Misalnya, jika aplikasi mencoba melakukan fusi sensornya sendiri, memperkenalkan kalibrasi sebenarnya dapat mendistorsi hasil.

Selain laju rotasi, giroskop yang tidak dikalibrasi juga memberikan perkiraan yang bergerak di sekitar setiap sumbu. Kode berikut menunjukkan cara mendapatkan instance default giroskop yang tidak dikalibrasi:

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

Contoh kode lainnya

Tujuan Contoh BatchStepSensor menunjukkan lebih lanjut penggunaan API yang dibahas di halaman ini.

Anda juga harus membaca