101

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

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

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

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

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

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

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

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

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

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

B = Coordinate system used by the SensorEvent API.

C = SensorManager.getOrientation (..) метод фигура

Так я понимаю, что А представляет собой «мировую систему координат», который я полагаю, относится к тому, местоположения на планете даны как (широта, долгота) coupl e с опцией (высота). X - координата "easting", Y - координата "northing". Z указывает на небо и представляет собой высоту.

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

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

+25

Мне очень понравился этот вопрос. Я не могу ответить, но мне это нравится. –

+4

Тим, ты когда-нибудь получал ответ? Я тоже царапаю голову. Это один из самых плохо документированных API, которые я когда-либо видел. –

+0

Не боюсь. Мне пришлось двигаться дальше. Когда-нибудь я вернусь к этому вопросу. – Tim

ответ

24

Возможно, вы захотите проверить статью One Screen Turn Deserves Another. Это объясняет, почему вам нужна матрица вращения.

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

В приложениях, которые не заблокированы в одной ориентации, система координат экрана изменяется при повороте устройства. Таким образом, когда устройство повернуто из режима просмотра по умолчанию, система координат датчика больше не совпадает с системой координат экрана. Матрица вращения в этом случае используется для преобразования 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]); 
     } 
    } 
} 
+4

просто упомяните, что азимут, подача и бросок НЕ такие же, как выходят из устаревшего сенсора OrientationSensor. 'ориентация [0] = ориентация [0]> = 0?ориентация [0] + 360; 'будет нормализовать азимут и' if (ориентация [1] <= -90) { \t \t \t Ориентация [1] + = (-2 * (90 + ориентация [1 ])); \t \t} иначе, если (ориентация [1]> = 90) { \t \t \t ориентацию [1] + = (2 * (90 - ориентацию [1])); \t \t} 'будет нормализовать шаг –

+0

@RafaelT и нормализовать рулон? Или это не имеет никакого смысла? – Matthias

+0

@RafaelT: Ваша нормализация азимута, кажется, влияет: значения идут от [-180,180] до [0, 360]. Но значения шага, которые я получаю, уже находятся в [-90,90], поэтому нормализация, которую вы предлагаете, не имеет никакого эффекта. – Matthias

0

Посмотрите на это (или запутанные человек еще больше!): Stackoverflow.com: Q.5202147

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

+0

Я посмотрю. спасибо – Tim

3

Roll - это функция силы тяжести, рулон 90 градусов ставит всю тяжесть в регистр x.

Шаг такой же, шаг 90 градусов помещает весь компонент силы тяжести в регистр y.

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

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

0

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

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

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

Смежные вопросы