Android удаляет гравитацию из показаний акселерометра

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

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

Не могли бы вы мне помочь? Мой код должен быть примерно таким:

public void onSensorChanged(SensorEvent sensorEvent) {
    float vals[] = sensorEvent.values;
    float accelerationX = filterGravity(vals[0]);
    float accelerationY = filterGravity(vals[1]);
    float accelerationZ = filterGravity(vals[2]);
}

Какой код я должен поместить в метод filterGravity()?


person Gabriel    schedule 02.08.2011    source источник


Ответы (4)


Для базового решения вам понадобится фильтр нижних частот. Другие подходы, такие как фильтр Калмана, довольно сложны в отношении математика позади. Простой пример для Android: один щелчок от ссылки на http://developer.android.com/reference/android/hardware/SensorEvent.html#values.

Проще говоря, фильтр нижних частот строит средневзвешенное значение из всех ваших исторических значений. Если у вас, например, коэффициент фильтрации 0,1, это означает, что 10% вашего текущего значения добавляются к предыдущему среднему значению: newMeanValue = 10% currentValue + 90% oldMeanValue. Это означает, что даже если есть резкий пик, он будет медленно увеличивать ваше среднее значение из-за 10%.

person Kay    schedule 02.08.2011
comment
@Kay Извините, я хотел проголосовать за ваш ответ. Пожалуйста, добавьте точку к вашему последнему предложению (или отредактируйте), чтобы мой отрицательный голос стал положительным. Прости... - person Ali; 28.09.2011
comment
@Ali: точка добавлена, без проблем :-) - person Kay; 29.09.2011
comment
@Kay Сайт должен поддерживать такую ​​функцию отмены. Возможно, я подниму его на metastackoverflow. - person Ali; 30.09.2011
comment
@Ali meta.stackexchange.com/questions/19940/ Статус отклонен, но я только что проголосовал за него. Может быть, однажды это осуществится. - person Kay; 30.09.2011

Линейное ускорение — это то, что вам нужно. Проверьте Sensor.TYPE_LINEAR_ACCELERATION здесь.

person Ali    schedule 02.08.2011
comment
Большое Вам спасибо. Это решит мою проблему. Однако это поддерживается только начиная с уровня API 9. Есть ли способ реализовать это в более ранних версиях API? - person Gabriel; 02.08.2011
comment
@ Габриэль Боюсь, что нет. За этим стоит сложная математика, объединяющая данные акселерометра, гироскопа и компаса. Вот интересное видео о слиянии датчиков: youtube.com/watch?v=C7JQ7Rpwn2k. - person Ali; 02.08.2011

Если у вас нет телефона с TYPE_LINEAR_ACCELERATION, вы застряли с TYPE_ACCELERATION, который не может отделить гравитацию (наклон) от линейного ускорения.

Одним из вариантов является применение фильтра нижних частот. Другой подход заключается в использовании слияния датчиков при наличии гироскопа. Оба подхода имеют свои преимущества и недостатки.

У меня есть много рабочих примеров в проекте с открытым исходным кодом Acceleration Explorer.

person Kaleb    schedule 25.07.2013
comment
Привет, Калеб, в настоящее время я работаю над java-приложением, аналогичным вашему Android-приложению FusedLinearAcceleration, с той разницей, что я не могу использовать виртуальные датчики Android для вычисления гравитации. Я портировал некоторые методы из sensorManager, но не могу найти алгоритм для получения вектора гравитации. Я обнаружил, что этого можно добиться с помощью кватернионов, и изменил/записал что-то вроде этого: Бресиу/c0a69552881b8df34a2e. Но это дает плохие результаты - гравитация компенсируется только по оси z (остальный код основан на вашем приложении). Есть подсказки, что может быть не так? Мой код: goo.gl/5jmlvY - person Bresiu; 02.07.2014
comment
@Bresiu: единственный виртуальный датчик, который использует FusedLinearAcceleration, — это Sensor.TYPE_GRAVITY, и вы можете изменить его на Sensor.TYPE_ACCELERATION. Однако, если у вас есть устройство с гироскопом, следует реализовать Sensor.TYPE_GRAVITY. Вы можете посмотреть эту статью в блоге (kircherelectronics.com/blog/index.php/11-android/sensors/), в котором подробно описывается опубликованный вами код (и мой код). Это может помочь, поскольку охватывает вектор гравитации. Имейте в виду, что если вы пытаетесь измерить что-либо во время динамического ускорения (например, автомобиля), это потребует модификации. - person Kaleb; 02.07.2014
comment
У меня есть устройство с гироскопом, акселерометром и магнитометром, поэтому я ищу сочетание датчиков для достижения наилучших результатов. Я видел другие ваши приложения, и FusedLinear кажется наиболее точным. буду дальше искать... - person Bresiu; 03.07.2014
comment
FusedLinearAcceleration настолько хорош, насколько это возможно. Очень сложно отличить наклон/статическое ускорение от динамического/линейного ускорения. Поскольку акселерометр компенсирует дрейф гироскопов каким-то слиянием (обычно дополнительным фильтром), динамическое/линейное ускорение может вызвать ошибочную компенсацию дрейфа в гироскопе. Петли обратной связи являются проблемой для всех слияний датчиков. У Sensor.TYPE_LINEAR_ACCELERATION тоже есть эта проблема. Это бесполезно для измерения динамического/линейного ускорения. - person Kaleb; 03.07.2014

Не совсем уверен, что вы пытаетесь сделать, но если вы ищете величину (которая даст результат от 0 до 1), тогда все, что вам нужно сделать, это разделить результат на 10.

public void onSensorChanged(SensorEvent sensorEvent) {
float vals[] = sensorEvent.values;
float accelerationX = (vals[0]/10);
float accelerationY = (vals[1]/10);
float accelerationZ = (vals[2]/10);

}

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

person Chris    schedule 02.08.2011