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

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

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

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

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

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

  1. Устройство на левой стороне

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

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

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

  1. Устройство

Введите описание изображения здесьВведите описание изображения здесь

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

Solutions Collecting From Web of "Ускорение системы координат устройства в абсолютную систему координат"

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

  1. Получить ротационную матрицу ( float[16] чтобы ее можно было использовать позже классом android.opengl.Matrix ) из SensorManager.getRotationMatrix() (используя SENSOR.TYPE_MAGNETIC_FIELD датчиков SENSOR.TYPE_GRAVITY и SENSOR.TYPE_MAGNETIC_FIELD качестве параметров),
  2. Используйте android.opengl.Matrix.invertM() на матрице вращения, чтобы инвертировать ее (не транспонировать!),
  3. Используйте датчик Sensor.TYPE_LINEAR_ACCELERATION , чтобы получить вектор линейного ускорения (в Sensor.TYPE_LINEAR_ACCELERATION устройства sys.),
  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.)

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

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

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

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

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

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