Дополнительный фильтр (гироскоп + акселер) с Android - PullRequest
6 голосов
/ 26 сентября 2011

Недавно я провел некоторые исследования, чтобы использовать акселерометр + гироскоп, чтобы использовать эти сенсоры для отслеживания смартфона без помощи GPS (см. Этот пост) Внутренняя система позиционирования на основе гироскопа и акселерометра

Для этого мне понадобится моя ориентация (угол (шаг, крен и т.

public void onSensorChanged(SensorEvent arg0) {
    if (arg0.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
    {
        accel[0] = arg0.values[0];
         accel[1] = arg0.values[1];
   accel[2] = arg0.values[2];
   pitch = Math.toDegrees(Math.atan2(accel[1], Math.sqrt(Math.pow(accel[2], 2) + Math.pow(accel[0], 2))));

  tv2.setText("Pitch: " + pitch + "\n" + "Roll: " + roll);

   } else if (arg0.sensor.getType() == Sensor.TYPE_GYROSCOPE )
{
  if (timestamp != 0) {
  final float dT = (arg0.timestamp - timestamp) * NS2S;         
  angle[0] += arg0.values[0] * dT;
  filtered_angle[0] = (0.98f) * (filtered_angle[0] + arg0.values[0] * dT) + (0.02f)* (pitch);
   }        
   timestamp = arg0.timestamp;
 }
}

Здесь я пытаюсь отклонить (только для тестирования) от моего акселерометра (шага) от интеграции время впадины gyroscope_X, отфильтровав его с помощью дополнительного фильтра

Filter_angle [0] = (0,98f) * (Filter_angle [0] + gyro_x * dT) + (0,02f) * (шаг)

с dT начинаются более или менее 0,009 секунд

Но я не знаю почему, но мой угол не очень точен ... когда устройство расположено на столе ровно (экран направлен вверх)

Pitch (angle fromm accel) = 1.5 (average) 
Integrate gyro = 0 to growing (normal it's drifting) 
filtered gyro angle = 1.2

и когда я поднимаю телефон на 90 ° (см. Экран передо мной лицом к стене)

Pitch (angle fromm accel) = 86 (MAXIMUM) 
Integrate gyro = he is out ok its normal 
filtered gyro angle = 83 (MAXIMUM)

Значит, углы никогда не достигают 90 ??? Даже если я попытаюсь поднять телефон немного больше ... Почему он не идет до 90 °? Мой расчет неверен? или это качество сенсорной хрени?

Еще одна вещь, которая меня интересует, это то, что: с Android я не «считываю» значение датчика, но я получаю уведомление, когда они меняются. Проблема в том, что, как вы видите в коде, Accel и Gyro используют один и тот же метод .... поэтому, когда я вычисляю отфильтрованный угол, я возьму шаг ускорения за 0,009 секунды, нет? Это может быть источником моей проблемы?

Спасибо!

Ответы [ 4 ]

5 голосов
/ 26 сентября 2011

Я могу только повторить себя.

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

Что вы на самом деле можете сделать, так это отслеживать только ориентацию.

Бросок, подача и рыскание - зло, не используйте их. Проверьте видео, которое я уже рекомендовал , в 38: 25.

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

Подобные вопросы, которые могут вам пригодиться:

отслеживание небольших перемещений iphone без GPS
Какова реальная точность телефонных акселерометров при позиционировании?
как рассчитать движение телефона по вертикали от покоя?
iOS: точность движения в трехмерном пространстве
Как использовать акселерометр для измерения расстояния для разработки приложений для Android
Расстояние, пройденное акселерометром
Как узнать расстояние, пройденное с помощью гироскопа и акселерометра?

3 голосов
/ 15 мая 2013

Я написал учебное пособие по использованию дополнительного фильтра для отслеживания ориентации с помощью гироскопа и акселерометра: http://www.pieter -jan.com / node / 11 возможно, оно может вам помочь.

0 голосов
/ 09 августа 2014

Я пытался, и это даст вам угол 90 ...

filtered_angle = (filtered_angle / 83) * 90;
0 голосов
/ 05 сентября 2013

Я протестировал ваш код и обнаружил, что, вероятно, коэффициент масштабирования не соответствует.Преобразование шага в 0-пи дает лучший результат.В моем тесте отфильтрованный результат составляет ~ 90 градусов.

pitch = (float) Math.toDegrees(Math.atan2(accel[1], Math.sqrt(Math.pow(accel[2], 2) + Math.pow(accel[0],   2))));
pitch = pitch*PI/180.f;

filtered_angle = weight * (filtered_angle + event.values[0] * dT) + (1.0f-weight)* (pitch);
...