Ускорение из системы координат устройства в абсолютную систему координат

С моего устройства Android я могу прочитать массив значений линейного ускорения (в системе координат устройства) и массив абсолютных значений ориентации (в системе координат Земли). Что мне нужно, это получить значения линейного ускорения в последней координате. система.

Как я могу конвертировать их?

РЕДАКТИРОВАТЬ после Али ответ в комментарии:

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

Но я только что сделал тест, в котором я положил телефон в разные позиции и получил ускорение по разным осям. Есть 3 пары картинок - первые показывают, как я установил устройство (извините за мой "мастерский навык" в Paint), а вторые показывают показания по данным, предоставленным линейным акк. датчик:

  1. устройство ставится на левую сторону

первая позицияпервые чтения

  1. устройство лежит на спине

вторая позициявторые чтения

  1. устройство стоя

А теперь - почему в третьем случае ускорение происходит вдоль оси Z (не Y), поскольку положение устройства не имеет значения?

4 ответа

Решение

Мне наконец удалось это решить! Итак, чтобы получить вектор ускорения в системе координат Земли, необходимо:

  1. получить матрицу вращения (float[16] так что это может быть использовано позже android.opengl.Matrix класс) из SensorManager.getRotationMatrix() (с помощью SENSOR.TYPE_GRAVITY а также SENSOR.TYPE_MAGNETIC_FIELD значения датчиков в качестве параметров),
  2. использование android.opengl.Matrix.invertM() на матрицу вращения, чтобы инвертировать его (не транспонировать!),
  3. использование Sensor.TYPE_LINEAR_ACCELERATION датчик для получения вектора линейного ускорения (по координатам устройства),
  4. использование android.opengl.Matrix.multiplyMV() умножить матрицу вращения на вектор линейного ускорения.

И вот оно у тебя! Я надеюсь, что сэкономлю драгоценное время для других.

Спасибо Эдварду Фальку и Али за подсказки!!

Основываясь на ответе @alex, вот фрагмент кода:

private float[] gravityValues = null;
private float[] magneticValues = null;

 @Override
    public void onSensorChanged(SensorEvent event) {
        if ((gravityValues != null) && (magneticValues != null) 
            && (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)) {

            float[] deviceRelativeAcceleration = new float[4];
            deviceRelativeAcceleration[0] = event.values[0];
            deviceRelativeAcceleration[1] = event.values[1];
            deviceRelativeAcceleration[2] = event.values[2];
            deviceRelativeAcceleration[3] = 0;

            // Change the device relative acceleration values to earth relative values
            // X axis -> East
            // Y axis -> North Pole
            // Z axis -> Sky

            float[] R = new float[16], I = new float[16], earthAcc = new float[16];

            SensorManager.getRotationMatrix(R, I, gravityValues, magneticValues);

            float[] inv = new float[16];

            android.opengl.Matrix.invertM(inv, 0, R, 0);
            android.opengl.Matrix.multiplyMV(earthAcc, 0, inv, 0, deviceRelativeAcceleration, 0);
           Log.d("Acceleration", "Values: (" + earthAcc[0] + ", " + earthAcc[1] + ", " + earthAcc[2] + ")");                

        } else if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
            gravityValues = event.values;
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            magneticValues = event.values;
        } 
   }

Согласно документации вы получаете линейное ускорение в системе координат телефона.

Вы можете преобразовать любой вектор из системы координат телефона в систему координат Земли, умножив его на матрицу вращения. Вы можете получить матрицу вращения из getRotationMatrix ().

(Возможно, уже есть функция, выполняющая это умножение для вас, но я не занимаюсь программированием для Android и не знаком с ее API.)

Хорошим учебником по матрице вращения является Направляющая косинусная матрица IMU: теория рукописи. Удачи!

Хорошо, во-первых, если вы пытаетесь выполнять инерциальную навигацию на Android, ваша работа для вас исключена. Дешевый маленький сенсор, используемый в смартфонах, просто недостаточно точен. Хотя, была проделана некоторая интересная работа по внутренней навигации на небольших расстояниях, например внутри здания. Вероятно, есть статьи на эту тему, которые вы можете найти. Google "Конференция разработчиков интерфейсов Motion", и вы можете найти что-то полезное - это конференция, которую Invensense организовал пару месяцев назад.

Во-вторых, нет, линейное ускорение в координатах устройства, а не в мировых координатах. Вам придется конвертировать себя, что означает знание трехмерной ориентации устройства.

Что вы хотите сделать, так это использовать версию Android, которая поддерживает виртуальные датчики TYPE_GRAVITY и TYPE_LINEAR_ACCELERATION. Вам понадобится устройство с гироскопами, чтобы получить достаточно точные и точные показания.

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

Итак, вы хотите настроить сенсорные приемники для TYPE_GRAVITY, TYPE_LINEAR_ACCELERATION и TYPE_MAGNETOMETER. Используйте данные гравитации и магнитометра в качестве входных данных для SensorManager. getRotationMatrix() для получения матрицы вращения, которая преобразует мировые координаты в координаты устройства или наоборот. В этом случае вам понадобится часть "наоборот". То есть преобразовать входное линейное ускорение в мировые координаты, умножив их на транспонирование матрицы ориентации.

Другие вопросы по тегам