Подтвердить что ты не робот

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

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

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

EDIT после ответа Али в комментарии:

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

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

  • устройство на левой стороне

first positionfirst readings

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

second positionsecond readings

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

enter image description hereenter image description here

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Основываясь на ответе @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;
        } 
   }

Ответ 3

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

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

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

Хорошим учебником по матрице вращения является Рукопись Косинуса Matrix IMU: Theory. Удачи!

Ответ 4

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

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

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

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

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