Вопрос

Я некоторое время пытался разобраться в датчиках ориентации Android.Я думал, что понял это.Потом я понял, что нет.Теперь я думаю (надеюсь), что снова чувствую это лучше, но я все еще не на 100%.Я постараюсь объяснить свое неоднородное понимание этого, и, надеюсь, люди смогут меня поправить, если я ошибаюсь в некоторых частях или заполню какие-либо пробелы.

Я представляю, что стою на отметке 0 градусов долготы (нулевой меридиан) и 0 градусов широты (экватор).На самом деле это место находится в море у побережья Африки, но будьте терпеливы.Я держу телефон перед лицом так, чтобы нижняя часть телефона была направлена ​​к моим ногам;Я смотрю на север (смотрю в сторону Гринвича), поэтому правая сторона телефона указывает на восток, в сторону Африки.В этой ориентации (со ссылкой на диаграмму ниже) ось X указывает на восток, ось Z указывает на юг, а ось Y указывает на небо.

Теперь датчики телефона позволяют определить ориентацию (а не местоположение) устройства в такой ситуации.Эта часть меня всегда смущала, вероятно, потому, что я хотел понять, как что-то работает, прежде чем признать, что это просто работает.Похоже, что телефон определяет свою ориентацию, используя комбинацию двух разных методов.

Прежде чем я перейду к этому, представьте, что вы снова стоите на воображаемом участке земли на 0 градусов широты и долготы и стоите в указанном выше направлении.Представьте также, что вам завязали глаза и ваши туфли прикреплены к кольцевой игровой площадке.Если кто-то толкнет вас в спину, вы упадете вперед (в сторону севера) и выставите обе руки, чтобы предотвратить падение.Точно так же, если кто-то толкнет вас в левое плечо, вы упадете на правую руку.В вашем внутреннем ухе есть «гравитационные датчики». (клип на ютубе) которые позволяют вам определить, падаете ли вы вперед/назад, влево/вправо или вниз (или вверх!!).Таким образом, люди могут обнаружить выравнивание и вращение вокруг тех же осей X и Z, что и телефон.

Теперь представьте, что кто-то развернул вас на кольцевой развязке на 90 градусов, так что вы теперь смотрите на восток.Вас вращают вокруг оси Y.Эта ось отличается тем, что мы не можем обнаружить ее биологически.Мы знаем, что находимся под определенным углом, но не знаем направления относительно северного магнитного полюса планеты.Вместо этого нам нужно использовать внешний инструмент...магнитный компас.Это позволяет нам определить, в каком направлении мы смотрим.То же самое и с нашим телефоном.

Теперь в телефоне есть и 3-х осевой акселерометр.У меня есть НЕТ Я имею представление о том, как они на самом деле работают, но я представляю себе гравитацию как постоянный и равномерный «дождь», падающий с неба, и представляю оси на рисунке выше как трубки, которые могут определять количество проходящего через них дождя.Когда телефон стоит вертикально, вся вода будет течь через Y-образную трубку.Если телефон постепенно повернуть так, чтобы его экран был обращен к небу, количество дождя, проходящего через Y, уменьшится до нуля, а громкость через Z будет постепенно увеличиваться до тех пор, пока через него не пройдет максимальное количество дождя.Точно так же, если мы теперь опрокинем телефон на бок, X-трубка в конечном итоге соберет максимальное количество дождя.Поэтому в зависимости от ориентации телефона, измеряя количество дождя, проходящего через три трубки, вы можете рассчитать ориентацию.

В телефоне также имеется электронный компас, который ведет себя как обычный компас — его «виртуальная стрелка» указывает на магнитный север.Android объединяет информацию с этих двух датчиков, чтобы при каждом SensorEvent из TYPE_ORIENTATION генерируется values[3] массив имеет
значения[0]:Азимут - (компас направляется к востоку от магнитного севера)
значения[1]:Наклон, вращение вокруг оси X (телефон наклоняется вперед или назад)
значения[2]:Крен, вращение вокруг оси Y (телефон наклоняется на левую или правую сторону)

Поэтому я думаю (то есть я не знаю), что причина, по которой Android выдает азимут (азимут компаса), а не показания третьего акселерометра, заключается в том, что пеленг компаса просто более полезен.Я не уверен, почему они объявили устаревшим этот тип датчика, поскольку теперь кажется, что вам нужно зарегистрировать прослушиватель в системе для SensorEvents типа TYPE_MAGNETIC_FIELD.События value[] массив необходимо передать в SensorManger.getRotationMatrix(..) метод для получения матрицы вращения (см. ниже), которая затем передается в метод SensorManager.getOrientation(..) метод.Кто-нибудь знает, почему команда Android устарела? Sensor.TYPE_ORIENTATION?Это вопрос эффективности?Именно это подразумевается в одном из комментариев к подобному вопрос но вам все равно необходимо зарегистрировать другой тип прослушивателя в разработка/образцы/Compass/src/com/example/android/compass/CompassActivity.java пример.

Теперь я хотел бы поговорить о матрице вращения.(Вот где я больше всего не уверен), поэтому выше, у нас есть три фигуры из документации Android, мы назовем их A, B и C.

A = фигура метода SensorManger.getRotationMatrix(..), представляющая мировую систему координат.

Б = Система координат, используемая API SensorEvent.

C = Рисунок метода SensorManager.getOrientation(..)

Насколько я понимаю, A представляет собой «мировую систему координат», которая, как я полагаю, относится к тому, как местоположения на планете задаются в виде пары (широта, долгота) с необязательным (высота).Х - это "восточный" координата, Y - это "север" координировать.Z указывает на небо и представляет высоту.

Система координат телефонов, показанная на рисунке Б, является фиксированной.Его ось Y всегда указывает вверх.Матрица вращения постоянно рассчитывается телефоном и позволяет сопоставлять их.Так прав ли я, полагая, что матрица вращения преобразует систему координат B в C?Поэтому, когда вы звоните SensorManager.getOrientation(..) метод, который вы используете values[] массив со значениями, соответствующими рисунку C.Когда телефон направлен в небо, матрица вращения является единичной матрицей (математический эквивалент матрицы 1), что означает, что сопоставление не требуется, поскольку устройство выровнено по мировой системе координат.

Хорошо.Думаю, мне лучше остановиться сейчас.Как я уже говорил, я надеюсь, что люди скажут мне, где я напортачил или помог людям (или еще больше запутал людей!)

Это было полезно?

Решение

Вы можете проверить Один поворот экрана заслуживает другого статья. Это объясняет, зачем вам нужна матрица вращения.

Короче говоря, датчики телефона всегда используют одну и ту же систему координат, даже когда устройство повернуто.

В приложениях, которые не заблокированы в одной ориентации, система координат экрана меняется при повороте устройства. Таким образом, когда устройство повернуто из режима просмотра по умолчанию, система координат датчика больше не совпадает с системой координат экрана. Матрица вращения в этом случае используется для преобразования A в C (B всегда остается фиксированной).

Вот фрагмент кода, чтобы показать вам, как его можно использовать.

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

Другие советы

Крен является функцией силы тяжести: крен на 90 градусов переносит всю силу тяжести в регистр X.

Шаг тот же: шаг вверх на 90 градусов помещает всю составляющую силы тяжести в регистр Y.

Рыскание/курс/азимут не влияет на гравитацию, оно ВСЕГДА находится под прямым углом к ​​гравитации, поэтому независимо от того, в какую сторону вы смотрите, гравитация будет неизмерима.

Вот поэтому для оценки нужен компас, может в этом есть смысл?

Посмотри на это: Stackoverflow.com: Q.5202147

Вы, кажется, в основном правы до 3 диаграмм A, B, c. После этого вы запутались.

У меня была эта проблема, поэтому я наметил, что происходит в разных направлениях. Если устройство установлено ландшафтным способом, например, в автомобиле «Степень» от компаса, кажется, составляет от 0 до 275 (идущий по часовой стрелке) выше 269 (между западом и севером) оно считается от -90 до 0, то тогда Нападающие от 0 до 269. 270 становится -90

Все еще в ландшафте, но с устройством, лежащим на спине, мой датчик дает 0-360. и в портретном режиме он работает 0-360, лежащий на спине и стоящий в портрете.

Надеюсь, это поможет кому -то

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top