Tổng quan về hướng điện thoại Android bao gồm la bàn


107

Tôi đã cố gắng tìm hiểu các cảm biến định hướng của Android trong một thời gian. Tôi nghĩ tôi đã hiểu nó. Sau đó, tôi nhận ra rằng tôi đã không. Bây giờ tôi nghĩ (hy vọng) tôi có cảm giác tốt hơn với nó một lần nữa nhưng tôi vẫn chưa phải là 100%. Tôi sẽ cố gắng giải thích sự hiểu biết chắp vá của tôi về nó và hy vọng mọi người sẽ có thể sửa chữa cho tôi nếu tôi sai một phần hoặc điền vào bất kỳ chỗ trống nào.

Tôi tưởng tượng tôi đang đứng ở 0 độ kinh độ (kinh tuyến gốc) và 0 độ vĩ độ (đường xích đạo). Vị trí này thực sự là ở biển ngoài khơi Châu Phi nhưng tôi chịu. Tôi giữ điện thoại trước mặt để phần dưới của điện thoại hướng vào chân tôi; Tôi đang quay mặt về phía Bắc (nhìn về phía Greenwich), do đó, phía bên tay phải của điện thoại hướng Đông về phía Châu Phi. Theo hướng này (có tham chiếu đến sơ đồ bên dưới) tôi có trục X hướng Đông, trục Z hướng Nam và trục Y hướng lên trời.

Giờ đây, các cảm biến trên điện thoại cho phép bạn xác định hướng (không phải vị trí) của thiết bị trong tình huống này. Phần này luôn làm tôi bối rối, có lẽ vì tôi muốn hiểu cách hoạt động của một thứ gì đó trước khi tôi chấp nhận rằng nó hoạt động bình thường. Có vẻ như chiếc điện thoại đã định hướng bằng cách sử dụng kết hợp hai kỹ thuật khác nhau.

Trước khi tôi hiểu được điều đó, hãy tưởng tượng bạn đang đứng trên mảnh đất tưởng tượng ở 0 độ vĩ độ và kinh độ đứng theo hướng đã đề cập ở trên. Cũng hãy tưởng tượng rằng bạn bị bịt mắt và đôi giày của bạn được cố định vào bùng binh sân chơi. Nếu ai đó xô bạn ở phía sau, bạn sẽ ngã về phía trước (về phía Bắc) và đưa cả hai tay ra để tránh ngã. Tương tự nếu ai đó xô bạn qua vai trái, bạn sẽ ngã xuống bên tay phải. Tai trong của bạn có "cảm biến lực hấp dẫn" (clip youtube) cho phép bạn phát hiện xem bạn đang rơi về phía trước / phía sau, hoặc trái / phải hoặc rơi xuống (hoặc lên !!). Do đó con người có thể phát hiện sự liên kết và xoay quanh các trục X và Z giống như điện thoại.

Bây giờ, hãy tưởng tượng ai đó đang xoay bạn 90 độ trên bùng binh để bạn đang quay mặt về hướng Đông. Bạn đang được xoay quanh trục Y. Trục này khác vì chúng ta không thể phát hiện ra nó về mặt sinh học. Chúng ta biết mình bị nghiêng một góc nào đó nhưng chúng ta không biết hướng liên quan đến cực Bắc từ trường của hành tinh. Thay vào đó chúng ta cần sử dụng một công cụ bên ngoài ... la bàn từ tính. Điều này cho phép chúng tôi xác định hướng đi của mình. Điều này cũng đúng với điện thoại của chúng tôi.

Giờ đây, điện thoại cũng có cảm biến gia tốc 3 trục. Tôi KHÔNG CÓý tưởng về cách chúng thực sự hoạt động nhưng cách tôi hình dung là tưởng tượng lực hấp dẫn như một 'cơn mưa' liên tục và đồng đều từ trên trời rơi xuống và tưởng tượng các trục trong hình trên như những ống có thể phát hiện lượng mưa chảy qua. Khi điện thoại được giữ thẳng đứng, tất cả nước mưa sẽ chảy qua ống Y. Nếu xoay dần điện thoại để màn hình của nó hướng lên bầu trời thì lượng mưa chảy qua Y sẽ giảm xuống 0 trong khi lượng mưa qua Z sẽ tăng đều cho đến khi lượng mưa chảy qua là lớn nhất. Tương tự, nếu bây giờ chúng ta nghiêng điện thoại vào mặt của nó, ống X cuối cùng sẽ thu được lượng mưa tối đa. Do đó tùy thuộc vào định hướng của điện thoại bằng cách đo lượng mưa chảy qua 3 ống mà bạn có thể tính toán được hướng.

Điện thoại cũng có một la bàn điện tử hoạt động như một la bàn bình thường - "kim ảo" của nó chỉ về phía bắc từ tính. Android kết hợp thông tin từ hai cảm biến này để bất cứ khi nào một SensorEventtrong số TYPE_ORIENTATIONđược tạo ra, values[3]mảng có
các giá trị [0]: Phương vị - (la bàn mang phía đông của nam từ)
các giá trị [1]: Pitch, xoay quanh trục x (là điện thoại nghiêng về phía trước hoặc phía sau)
các giá trị [2]: Cuộn, xoay quanh trục y (điện thoại nghiêng về phía bên trái hoặc bên phải)

Vì vậy, tôi nghĩ (tức là tôi không biết) lý do Android cung cấp cho phương vị (vòng bi la bàn) thay vì đọc của gia tốc kế thứ ba là vòng bi la bàn hữu ích hơn. Tôi không chắc tại sao họ không dùng loại cảm biến này nữa vì bây giờ có vẻ như bạn cần đăng ký một bộ lắng nghe với hệ thống cho SensorEventloại cảm biến TYPE_MAGNETIC_FIELD. value[]Mảng của sự kiện cần được chuyển vào SensorManger.getRotationMatrix(..)phương thức để nhận ma trận xoay (xem bên dưới), sau đó được chuyển vào SensorManager.getOrientation(..)phương thức. Có ai biết tại sao nhóm Android không dùng nữa không Sensor.TYPE_ORIENTATION? Nó có phải là một điều hiệu quả? Đó là những gì được ngụ ý trong một trong các nhận xét cho một câu hỏi tương tự nhưng bạn vẫn cần đăng ký một loại trình nghe khác trongphát triển / mẫu / La bàn / src / com / example / android / la bàn / CompassActivity.java ví dụ.

Bây giờ tôi muốn nói về ma trận xoay. (Đây là điểm tôi không chắc chắn nhất) Vì vậy, ở trên chúng tôi có ba số liệu từ tài liệu Android, chúng tôi sẽ gọi chúng là A, B và C.

A = SensorManger.getRotationMatrix (..) hình phương thức và đại diện cho hệ tọa độ của Thế giới

B = Hệ thống tọa độ được API SensorEvent sử dụng.

Hình phương thức C = SensorManager.getOrientation (..)

Vì vậy, hiểu biết của tôi là A đại diện cho "hệ tọa độ của thế giới" mà tôi cho là đề cập đến cách các vị trí trên hành tinh được đưa ra dưới dạng một cặp (vĩ độ, kinh độ) với một (độ cao) tùy chọn. X là tọa độ "làm dịu" , Y là tọa độ "đông bắc" . Z chỉ lên bầu trời và đại diện cho độ cao.

Hệ tọa độ điện thoại được thể hiện trong hình B là cố định. Trục Y của nó luôn hướng ra đỉnh. Ma trận xoay đang được điện thoại tính toán liên tục và cho phép ánh xạ giữa chúng. Vì vậy, tôi có đúng khi nghĩ rằng ma trận quay biến đổi hệ tọa độ B thành C không? Vì vậy, khi bạn gọi SensorManager.getOrientation(..)phương thức, bạn sử dụng values[]mảng có các giá trị tương ứng với hình C. Khi điện thoại hướng lên trời, ma trận xoay là ma trận nhận dạng (ma trận toán học tương đương với 1) có nghĩa là không cần ánh xạ vì thiết bị được căn chỉnh với hệ tọa độ của thế giới.

Đồng ý. Tôi nghĩ tôi nên dừng lại ngay bây giờ. Giống như tôi đã nói trước đây, tôi hy vọng mọi người sẽ cho tôi biết tôi đã làm sai chỗ nào hoặc giúp đỡ mọi người (hoặc mọi người còn bối rối hơn nữa!)


25
Tôi thực sự thích câu hỏi này. Tôi không thể trả lời nó nhưng tôi thích nó.
Octavian A. Damiean,

4
Tim, bạn đã bao giờ nhận được câu trả lời chưa? Tôi cũng đang vò đầu bứt tai. Đây là một trong những API được ghi chép kém nhất mà tôi từng thấy.
Pierre-Luc Paour

Tôi không thực sự sợ. Tôi đã phải tiếp tục. Một ngày nào đó tôi sẽ quay lại vấn đề này.
Tim

1
Ở đây tôi có cùng một câu hỏi, gần như? Và Đáp án, giải pháp nữa. Made công mã của tôi tại Github.

điều tương tự mà tôi đang băn khoăn, tôi đã triển khai la bàn trên thiết bị Android và đang hoạt động bình thường nếu tôi nhờ sự trợ giúp từ internet, nó hoạt động tốt nhưng điều khó hiểu là ... Giả sử thiết bị của tôi được đặt trên mặt đất về phía tôi và nó chỉ về phía bắc, bây giờ tôi cầm điện thoại di động lên và đặt nó thẳng đứng trên đầu mà không có và mặt vẫn hướng về phía tôi. Đầu tiên kim có nên đổi hướng hay không và tại sao. Theo tôi nghĩ thì điều đó không nên xảy ra vì tôi chưa thay đổi hướng đi của mình nhưng nó đang thay đổi trong ứng dụng của tôi và tất cả các ứng dụng khác mà tôi đã tải xuống. Bất cứ ai có thể giải thích tại sao?
Syed Raza Mehdi

Câu trả lời:


26

Bạn có thể muốn xem bài viết Một màn hình Turn Deserves Another . Nó giải thích tại sao bạn cần ma trận xoay.

Tóm lại, các cảm biến của điện thoại luôn sử dụng cùng một hệ tọa độ, ngay cả khi thiết bị được xoay.

Trong các ứng dụng không bị khóa theo một hướng, hệ thống tọa độ màn hình sẽ thay đổi khi bạn xoay thiết bị. Do đó, khi thiết bị được xoay từ chế độ xem mặc định của nó, hệ tọa độ cảm biến không còn giống như hệ tọa độ màn hình. Ma trận xoay trong trường hợp này được sử dụng để biến đổi A thành C (B luôn cố định).

Đây là đoạn mã cho bạn biết cách sử dụng đoạn mã.

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

4
chỉ cần đề cập rằng góc phương vị, cao độ và cuộn KHÔNG giống như xuất hiện từ OrientationSensor không được dùng nữa. orientation[0] = orientation[0] >= 0 ? orientation[0]: orientation[0] + 360;sẽ chuẩn hóa góc phương vị và if (orientation[1] <= -90) { orientation[1] += (-2*(90+orientation[1])); } else if(orientation[1] >= 90){ orientation[1] += (2*(90 - orientation[1])); }sẽ chuẩn hóa cao độ
Rafael T

@RafaelT và để chuẩn hóa cuộn? Hay điều đó không có ý nghĩa gì?
Matthias

@RafaelT: Việc chuẩn hóa góc phương vị của bạn dường như đã ảnh hưởng: các giá trị đi từ [-180,180] đến [0, 360]. Nhưng các giá trị cao độ tôi nhận được đã ở [-90,90] nên việc chuẩn hóa bạn đề xuất không có tác dụng.
Matthias

Điều đó có nghĩa là gì nếu sau khi kiểm tra (vity! = Null && geomag! = Null), giá trị của geomag luôn là 0, bất kể tôi di chuyển máy tính bảng như thế nào? Có thể là một máy tính bảng không có cảm biến thẻ địa lý?
Nâng cao

3

Cuộn là một hàm của trọng lực, cuộn 90 độ dồn toàn bộ trọng lực vào thanh ghi x.

Pitch cũng giống như vậy, cao độ 90 độ đặt tất cả các thành phần của trọng lực vào thanh ghi y.

Góc nghiêng / Góc nghiêng / góc phương vị không ảnh hưởng đến trọng lực, nó LUÔN ở góc vuông với trọng lực, do đó, bất kể bạn đang đối mặt với trọng lực theo hướng nào cũng sẽ không thể đo lường được.

Đây là lý do tại sao bạn cần một la bàn để đánh giá, có lẽ điều đó có ý nghĩa?



0

Tôi đang gặp sự cố này nên tôi đã vạch ra những gì sẽ xảy ra theo các hướng khác nhau. Nếu thiết bị được gắn theo kiểu ngang, ví dụ: trong ô tô, hãy gắn 'độ' từ la bàn dường như chạy từ 0-275 (theo chiều kim đồng hồ) trên 269 (giữa tây và bắc) nó sẽ đếm ngược từ -90 đến 0, sau đó chuyển tiếp từ 0 đến 269. 270 trở thành -90

Vẫn ở chế độ ngang nhưng với thiết bị nằm ngửa, cảm biến của tôi cho kết quả 0-360. và ở chế độ dọc, nó chạy 0-360 cả khi nằm ngửa và đứng ở chế độ dọc.

Hy vọng điều đó sẽ giúp ai đó

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.