Ikhtisar orientasi ponsel Android termasuk kompas

107

Saya telah mencoba untuk memahami sensor orientasi Android untuk sementara waktu. Saya pikir saya mengerti. Kemudian saya menyadari bahwa saya tidak melakukannya. Sekarang saya pikir (harapan) saya memiliki perasaan yang lebih baik untuk itu lagi tetapi saya masih belum 100%. Saya akan mencoba menjelaskan pemahaman saya yang tambal sulam tentang itu dan semoga orang-orang dapat mengoreksi saya jika saya salah dalam beberapa bagian atau mengisi kekosongan.

Saya membayangkan saya berdiri di 0 derajat bujur (garis bujur utama) dan 0 derajat lintang (ekuator). Lokasi ini sebenarnya berada di laut lepas pantai Afrika tapi tahan dengan saya. Saya memegang telepon saya di depan wajah saya sehingga bagian bawah telepon mengarah ke kaki saya; Saya menghadap Utara (melihat ke arah Greenwich) jadi oleh karena itu sisi kanan telepon mengarah ke Timur menuju Afrika. Dalam orientasi ini (dengan mengacu pada diagram di bawah), saya memiliki sumbu X mengarah ke Timur, sumbu Z mengarah ke Selatan dan sumbu Y mengarah ke langit.

Sekarang sensor di ponsel memungkinkan Anda untuk mengetahui orientasi (bukan lokasi) perangkat dalam situasi ini. Bagian ini selalu membuat saya bingung, mungkin karena saya ingin memahami bagaimana sesuatu bekerja sebelum saya menerima bahwa itu berhasil. Tampaknya ponsel ini mengetahui orientasinya menggunakan kombinasi dua teknik berbeda.

Sebelum saya membahasnya, bayangkan kembali berdiri di atas sebidang tanah imajiner pada garis lintang dan bujur 0 derajat berdiri ke arah yang disebutkan di atas. Bayangkan juga bahwa Anda ditutup matanya dan sepatu Anda dipasang di bundaran taman bermain. Jika seseorang mendorong Anda dari belakang, Anda akan jatuh ke depan (ke arah Utara) dan mengulurkan kedua tangan untuk mematahkan kejatuhan Anda. Demikian pula jika seseorang mendorong bahu kiri Anda, Anda akan jatuh ke tangan kanan. Telinga bagian dalam Anda memiliki "sensor gravitasi" (klip youtube) yang memungkinkan Anda mendeteksi jika Anda jatuh ke depan / belakang, atau jatuh ke kiri / kanan atau jatuh (atau ke atas !!). Oleh karena itu, manusia dapat mendeteksi penyelarasan dan rotasi di sekitar sumbu X dan Z yang sama dengan telepon.

Sekarang bayangkan seseorang sekarang memutar Anda 90 derajat di bundaran sehingga Anda sekarang menghadap ke Timur. Anda sedang diputar di sekitar sumbu Y. Sumbu ini berbeda karena kita tidak dapat mendeteksinya secara biologis. Kita tahu bahwa kita memiliki sudut dalam jumlah tertentu tetapi kita tidak tahu arah hubungannya dengan kutub Utara magnet planet. Sebagai gantinya kita perlu menggunakan alat eksternal ... kompas magnet. Ini memungkinkan kita untuk memastikan arah mana yang kita hadapi. Hal yang sama berlaku dengan telepon kita.

Sekarang ponsel ini juga memiliki akselerometer 3 sumbu. Saya tidak punyaSaya membayangkan bagaimana sebenarnya mereka bekerja tetapi cara saya memvisualisasikannya adalah membayangkan gravitasi sebagai 'hujan' yang konstan dan seragam jatuh dari langit dan membayangkan sumbu pada gambar di atas sebagai tabung yang dapat mendeteksi jumlah hujan yang mengalir. Saat telepon diangkat ke atas, semua hujan akan mengalir melalui 'tabung' Y. Jika telepon diputar secara bertahap sehingga layarnya menghadap ke langit, jumlah hujan yang mengalir melalui Y akan berkurang menjadi nol sedangkan volume melalui Z akan terus meningkat hingga jumlah maksimum hujan yang mengalir masuk. Demikian pula jika kita sekarang memiringkan ponsel ke sisinya, tabung X pada akhirnya akan mengumpulkan jumlah hujan maksimal. Oleh karena itu, tergantung pada orientasi ponsel dengan mengukur jumlah hujan yang mengalir melalui 3 tabung, Anda dapat menghitung orientasinya.

Ponsel ini juga memiliki kompas elektronik yang berperilaku seperti kompas biasa - "jarum virtual" -nya mengarah ke utara magnet. Android menggabungkan informasi dari dua sensor ini sehingga setiap kali a SensorEventdari TYPE_ORIENTATIONdihasilkan, values[3]larik memiliki
nilai [0]: Azimuth - (kompas yang mengarah ke timur utara magnet)
[1]: Pitch, rotasi di sekitar sumbu x (adalah ponsel condong ke depan atau ke belakang)
nilai [2]: Roll, rotasi di sekitar sumbu y (apakah ponsel condong ke kiri atau kanan)

Jadi saya pikir (yaitu saya tidak tahu) alasan Android memberikan azimuth (arah kompas) daripada membaca akselerometer ketiga adalah karena arah kompas lebih berguna. Saya tidak yakin mengapa mereka menghentikan jenis sensor ini karena sekarang tampaknya Anda perlu mendaftarkan listener dengan sistem untuk SensorEventtipe s TYPE_MAGNETIC_FIELD. value[]Larik peristiwa perlu dimasukkan ke dalam SensorManger.getRotationMatrix(..)metode untuk mendapatkan matriks rotasi (lihat di bawah) yang kemudian diteruskan ke dalam SensorManager.getOrientation(..)metode. Adakah yang tahu mengapa tim Android tidak lagi digunakan Sensor.TYPE_ORIENTATION? Apakah ini hal efisiensi? Itulah yang tersirat di salah satu komentar untuk pertanyaan serupa tetapi Anda masih perlu mendaftarkan jenis pendengar yang berbeda dipengembangan / sampel / Kompas / src / com / contoh / android / kompas / CompassActivity.java contoh.

Sekarang saya ingin berbicara tentang matriks rotasi. (Di sinilah saya paling tidak yakin) Jadi di atas kami memiliki tiga angka dari dokumentasi Android, kami akan menyebutnya A, B dan C.

A = Gambar metode SensorManger.getRotationMatrix (..) dan mewakili sistem koordinat Dunia

B = Sistem koordinat yang digunakan oleh SensorEvent API.

C = Angka metode SensorManager.getOrientation (..)

Jadi pemahaman saya adalah bahwa A mewakili "sistem koordinat dunia" yang saya anggap mengacu pada cara lokasi di planet ini diberikan sebagai pasangan (lintang, bujur) dengan opsional (ketinggian). X adalah koordinat "arah timur" , Y adalah koordinat "arah utara" . Z menunjuk ke langit dan melambangkan ketinggian.

Sistem koordinat telepon ditunjukkan pada gambar B adalah tetap. Sumbu Y-nya selalu menunjuk ke atas. Matriks rotasi terus dihitung oleh telepon dan memungkinkan pemetaan di antara keduanya. Jadi, apakah saya benar dalam berpikir bahwa matriks rotasi mengubah sistem koordinat B menjadi C? Jadi ketika Anda memanggil SensorManager.getOrientation(..)metode, Anda menggunakan values[]larik dengan nilai yang sesuai dengan gambar C.Ketika telepon mengarah ke langit, matriks rotasi adalah matriks identitas (matriks matematis yang setara dengan 1) yang berarti tidak diperlukan pemetaan karena perangkat sejajar dengan sistem koordinat dunia.

Baik. Saya pikir saya lebih baik berhenti sekarang. Seperti yang saya katakan sebelumnya, saya berharap orang akan memberi tahu saya di mana saya telah mengacaukan atau membantu orang (atau membingungkan orang lebih jauh!)

Tim
sumber
25
Saya sangat suka pertanyaan ini. Saya tidak bisa menjawabnya tapi saya menyukainya.
Oktavianus A. Damiean
4
Tim, apakah kamu pernah mendapat jawaban? Aku juga menggaruk-garuk kepalaku. Ini adalah salah satu API yang paling buruk didokumentasikan yang pernah saya lihat.
Pierre-Luc Paour
Tidak terlalu, aku takut. Saya harus pindah. Suatu hari nanti saya akan kembali ke masalah ini.
Tim
1
Di sini saya memiliki pertanyaan yang sama, hampir? Dan Responnya, solusinya juga. Mempublikasikan kode saya di Github.
hal yang sama saya ingin tahu, saya telah menerapkan kompas pada perangkat android dan berfungsi dengan baik jika saya mengambil bantuan dari internet itu berfungsi dengan baik tetapi hal yang membingungkan adalah ... Misalkan perangkat saya diletakkan di permukaan tanah ke arahku dan mengarah ke utara sekarang aku mengambil ponselku dan meletakkannya secara vertikal di atas kepalaku tanpa dan wajah masih menghadapku. Pertama-tama jarum harus mengubah arahnya dan mengapa. Sesuai saya berpikir itu seharusnya tidak karena saya belum mengubah arah saya tetapi itu berubah di aplikasi saya dan semua aplikasi lain yang telah saya unduh. Adakah yang bisa menjelaskan mengapa?
Syed Raza Mehdi

Jawaban:

26

Anda mungkin ingin melihat artikel One Screen Turn Deserves Another . Ini menjelaskan mengapa Anda membutuhkan matriks rotasi.

Singkatnya, sensor ponsel selalu menggunakan sistem koordinat yang sama, bahkan saat perangkat diputar.

Dalam aplikasi yang tidak dikunci ke satu orientasi, sistem koordinat layar berubah saat Anda memutar perangkat. Jadi, ketika perangkat diputar dari mode tampilan defaultnya, sistem koordinat sensor tidak lagi sama dengan sistem koordinat layar. Matriks rotasi dalam hal ini digunakan untuk mengubah A ke C (B selalu tetap).

Berikut cuplikan kode untuk menunjukkan kepada Anda bagaimana itu dapat digunakan.

SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);

// Register this class as a listener for the accelerometer sensor
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                    SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
                    SensorManager.SENSOR_DELAY_NORMAL);

//...
// The following code inside a class implementing a SensorEventListener
// ...

float[] inR = new float[16];
float[] I = new float[16];
float[] gravity = new float[3];
float[] geomag = new float[3];
float[] orientVals = new float[3];

double azimuth = 0;
double pitch = 0;
double roll = 0;

public void onSensorChanged(SensorEvent sensorEvent) {
    // If the sensor data is unreliable return
    if (sensorEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
        return;

    // Gets the value of the sensor that has been changed
    switch (sensorEvent.sensor.getType()) {  
        case Sensor.TYPE_ACCELEROMETER:
            gravity = sensorEvent.values.clone();
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            geomag = sensorEvent.values.clone();
            break;
    }

    // If gravity and geomag have values then find rotation matrix
    if (gravity != null && geomag != null) {

        // checks that the rotation matrix is found
        boolean success = SensorManager.getRotationMatrix(inR, I,
                                                          gravity, geomag);
        if (success) {
            SensorManager.getOrientation(inR, orientVals);
            azimuth = Math.toDegrees(orientVals[0]);
            pitch = Math.toDegrees(orientVals[1]);
            roll = Math.toDegrees(orientVals[2]);
        }
    }
}
Oktavianus A. Damiean
sumber
4
sebutkan saja bahwa azimuth, pitch and roll TIDAK sama dengan yang keluar dari OrientationSensor yang sudah usang. orientation[0] = orientation[0] >= 0 ? orientation[0]: orientation[0] + 360;akan menormalkan azimuth dan if (orientation[1] <= -90) { orientation[1] += (-2*(90+orientation[1])); } else if(orientation[1] >= 90){ orientation[1] += (2*(90 - orientation[1])); }akan menormalkan nada
Rafael T
@ RafaelT dan untuk menormalkan gulungan? Atau apakah itu tidak masuk akal?
Matthias
@RafaelT: Normalisasi azimuth Anda tampaknya memengaruhi: nilai berubah dari [-180.180] menjadi [0, 360]. Tetapi nilai nada yang saya dapatkan sudah di [-90,90] jadi normalisasi yang Anda usulkan tidak berpengaruh.
Matthias
Apa maksudnya jika setelah memeriksa (gravitasi! = Null && geomag! = Null), nilai geomag selalu 0, bagaimanapun cara saya memindahkan tablet? Mungkinkah tablet tanpa sensor geomag?
Lanjutan
3

Gulungan adalah fungsi gravitasi, gulungan 90 derajat memasukkan semua gravitasi ke register x.

Pitchnya sama, pitch 90 derajat menempatkan semua komponen gravitasi ke dalam register y.

Yaw / Heading / azimuth tidak berpengaruh pada gravitasi, itu SELALU pada sudut yang benar terhadap gravitasi, maka bagaimanapun cara Anda menghadap gravitasi tidak akan terukur.

Inilah mengapa Anda membutuhkan kompas untuk menilai, mungkin itu masuk akal?

Craig
sumber
0

Saya mengalami masalah ini jadi saya memetakan apa yang terjadi di arah yang berbeda. Jika perangkat dipasang dalam mode lanskap, misalnya di dalam mobil, pasang 'derajat' dari kompas tampaknya berjalan dari 0-275 (searah jarum jam) di atas 269 (antara barat dan utara) itu dihitung mundur dari -90 ke 0, kemudian maju dari 0 ke 269. 270 menjadi -90

Masih dalam lanskap tetapi dengan perangkat berbaring di punggungnya, sensor saya memberikan 0-360. dan dalam mode potret, ia menjalankan 0-360 baik berbaring telentang dan berdiri dalam potret.

Harapan yang membantu seseorang

bob putus asa
sumber