Дополнительный фильтр (гироскоп + ускорение) с Android

Недавно я провел некоторое исследование, чтобы использовать как акселерометр, так и гироскоп, чтобы использовать эти сенсоры для отслеживания смартфона без помощи 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 через время, фильтруя его с помощью дополнительного фильтра.

filtered_angle[0] = (0.98f) * (filtered_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 секунды раньше, нет? Это может быть источником моей проблемы?

Спасибо !


person Alexis    schedule 26.09.2011    source источник
comment
возможный дубликат системы внутреннего позиционирования на основе гироскопа и акселерометра   -  person Potatoswatter    schedule 01.07.2012


Ответы (4)


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

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

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

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

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

Похожие вопросы, которые могут быть вам полезны:

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

person Ali    schedule 26.09.2011
comment
Спасибо за вашу помощь, и извините, что повторяю ваши вещи.. Действительно, учебник gentlnav действительно хорош! Я только что быстро прочитал его, и он довольно хорошо объясняет DCM. Я собираюсь прочитать его более внимательно. Я нашел аналогичный вопрос в stackoverflow, где вы говорите о том же учебнике и говорите, что используете его для распознавания движения человека. Значит, вам удалось добиться хорошей ориентации с помощью DCM? stackoverflow.com/questions/5314217/ Спасибо - person Alexis; 26.09.2011
comment
@Alexis Нет проблем, удачи! Да, у меня есть реализация на C++, но написать собственную на Java для Android несложно. Возможно, есть существующие приложения, к сожалению, я не знаю ни одного. Достаточно ли для вашего приложения просто ориентации? - person Ali; 26.09.2011
comment
Поскольку это всего лишь проект для моей школы, мне просто было интересно узнать, возможно ли это... после большого количества чтений я узнал, что это не так :) или если это далеко впереди моего понимания математики... Так что я просто собираюсь немного измениться и попробовать поиграть с гироскопом + ускорение, чтобы только ориентироваться :) - person Alexis; 26.09.2011
comment
Я только что обнаружил, что: diydrones.com/profiles/blogs/a-simple-deadreckoning он использует DCM + счисление пути для отслеживания самолета (он дважды интегрирует, чтобы получить положение, но я не понял, как он исправляет результат) - person Alexis; 28.09.2011
comment
@ Alexis Я не проверял детали, но мне кажется, что его алгоритм основан на GPS, а IMU используется для заполнения пробелов. Да, вы можете сделать это с помощью фильтра Калмана, но в своем вопросе вы говорите, что у вас нет / не используется GPS. - person Ali; 28.09.2011
comment
@ Али, спасибо за объяснение, не могли бы вы помочь мне с этим вопросом? stackoverflow.com/questions/27137239/ - person Arash; 26.11.2014

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

person Pieter-Jan    schedule 15.05.2013

Я тестирую ваш код и обнаружил, что, вероятно, масштабный коэффициент не соответствует. Преобразование шага в 0-pi дает лучший результат. В моем тесте отфильтрованный результат составляет ~ 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);
person yee.hoo.dev    schedule 05.09.2013

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

filtered_angle = (filtered_angle / 83) * 90;
person Arfan Mirza    schedule 09.08.2014