Датчик Android: getRotationMatrix () возвращает неправильные значения, почему? - PullRequest
3 голосов
/ 06 ноября 2011

Прошло несколько дней с тех пор, как я начал использовать эту функцию, и пока не удалось получить действительные результаты.

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

Чтение Android-разработчиков кажется, что используя getRotationMatrix () я получаю R = матрицу вращения.

Итак, если я хочу A (вектор ускорения в мировой системе) из A '(вектор ускорения в телефонной системе), я должен сделать просто:

  A=R*A'

Но я не могу понять, почему у вектора A ВСЕГДА первый и второй компоненты равны нулю (пример: +0,00; -0,00; +6,43)

Мой текущий код похож на это:

  public void onSensorChanged(SensorEvent event) {
     synchronized (this) {   
        switch(event.sensor.getType()){
        case Sensor.TYPE_ACCELEROMETER:
            accelerometervalues = event.values.clone();
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            geomagneticmatrix =event.values.clone();
            break;
        }
        if (geomagneticmatrix != null && accelerometervalues != null) {
            float[] Rs = new float[16];
            float[] I = new float[16];
            SensorManager.getRotationMatrix(Rs, I, accelerometervalues, geomagneticmatrix);
            float resultVec[] = new float[4];
            float relativacc[]=new float [4];
                relativacc[0]=accelerationvalues[0];
                relativacc[1]=accelerationvalues[1];
                relativacc[2]=accelerationvalues[2];
                relativacc[3]=0;
            Matrix.multiplyMV(resultVec, 0, Rs, 0, relativacc, 0);

            //resultVec[] is the vector acceleration relative to world coordinates system..but doesn't WORK!!!!!

        }
      }
   }

Этот вопрос очень похож на этот Преобразование данных акселерометра из координат устройства в координаты реального мира , но там я не могу найти решение ... Я перепробовал все способы ..

Пожалуйста, помогите мне, мне нужна помощь !!!

UPDATE:

Теперь мой код ниже, я пытался объяснить матричный продукт, но ничего не изменилось:

            float[] Rs = new float[9];
            float[] I = new float[9];
            SensorManager.getRotationMatrix(Rs, I, accelerationvalues, geomagneticmatrix);
            float resultVec[] = new float[4];

            resultVec[0]=Rs[0]*accelerationvalues[0]+Rs[1]*accelerationvalues[1]+Rs[2]*accelerationvalues[2];
            resultVec[1]=Rs[3]*accelerationvalues[0]+Rs[4]*accelerationvalues[1]+Rs[5]*accelerationvalues[2];
            resultVec[2]=Rs[6]*accelerationvalues[0]+Rs[7]*accelerationvalues[1]+Rs[8]*accelerationvalues[2];

Вот пример чтения данных и результат:

Rs separated by " " Rs[0] Rs[1]....Rs[8]
Av separated by " " accelerationvalues[0] ...accelerationvalues[2]
rV separated by " " resultVec[0] ...resultVec[2]

Data from CAT manager

Как вы можете заметить, компоненты на осях x и y в реальном мире равны нулю (вокруг), даже если вы двигаетесь со скоростью телефона. Вместо этого относительный вектор ускорения правильно определяет каждое движение !!!

РЕШЕНИЕ Ошибки в нумераторах относятся к умножению чисел с плавающей запятой, которое отличается от двойного умножения. Это сводится к тому, что матрица вращения не стоит, если телефон , даже если с той же ориентацией, ускоряется. Поэтому невозможно перевести вектор ускорения в абсолютные координаты при движении ... Это сложно, но это реальность.

Ответы [ 4 ]

5 голосов
/ 08 ноября 2011

Finnaly я нашел ответ:

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

FYI вектор ориентации сделан из данных магнитометра И вектора силы тяжести. Это вызывает серьезную проблему: преобразование относительного соотношения требует ориентации, магнитного поля И гравитации, но мы знаем гравитацию только в том случае, если телефон остановлен относительно, поэтому мы возвращаемся, чтобы начать.

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

Матрицы, возвращаемые этой функцией, имеют смысл только тогда, когда Устройство не свободно падает и не близко к магнитному северу. Если устройство ускоряется или находится в сильном магнитном поле, возвращенные матрицы могут быть неточными.

В чужом мире совершенно бесполезен ... Вы можете доверять этой вещи, выполняя простой эксперимент на столе с Android Senor или что-то вроде этого.

1 голос
/ 06 ноября 2011

Вы должны отследить эту арифметическую ошибку, прежде чем беспокоиться о вращении, ускорении или чем-либо еще.

Вы подтвердили, что

resultVec[0]=Rs[0]*accelerationvalues[0];

дает вам

Rs[0]: 0.24105562
accelerationValues[0]: 6.891896
resultVec[0]: 1.1920929E-7

Итак, еще раз, упрощаем . Попробуйте это:

Rs[0] = 0.2;
resultVec[0] = Rs[0] * 6.8

EDIT:
Последний дал resultVec[0]=1.36, поэтому давайте попробуем это:

Rs[0] = 0.2;
accelerationValues[0] = 6.8
resultVec[0] = Rs[0] * accelerationValues[0];
0 голосов
/ 06 декабря 2011

Я разработал несколько приложений, которые используют датчики Android , поэтому я отвечаю на один из ваших вопросов в соответствии с моим опытом:

Но я не могу понятьпочему вектор A ВСЕГДА имеет первый и второй ноль компонента (пример: +0,00; -0,00; +6,43)

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

Правильным решением будет метод onAccuracyChanged () предоставление правильной информации о состоянии датчика.Он должен возвращать состояние SensorManager.SENSOR_STATUS_UNRELIABLE, но вместо этого он постоянно возвращает SensorManager.SENSOR_STATUS_ACCURACY_HIGH на всех физических устройствах, которые я тестировал до сих пор.При правильной реализации метода onAccuracyChanged () вы можете игнорировать плохие показания или попросить пользователя подождать, пока инициализируется датчик.

0 голосов
/ 06 ноября 2011

Если вы сделаете суммы, используя напечатанные значения, которые вы добавили, я получу

`(0.00112, -0.0004, 10)`

что не так мало, как у вас. Поэтому возникает арифметическая ошибка!

Может быть проблема в том, что вы используете accelerationvalues[] в последнем блоке, а accelerometervalues[] позже?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...