Как обнаружить ходьбу с Android-акселерометром

Я пишу приложение, и моя цель - обнаружить, когда пользователь идет. Я использую фильтр Kalman следующим образом:

float kFilteringFactor=0.6f;

        gravity[0] = (accelerometer_values[0] * kFilteringFactor) + (gravity[0] * (1.0f - kFilteringFactor));
        gravity[1] = (accelerometer_values[1] * kFilteringFactor) + (gravity[1] * (1.0f - kFilteringFactor));
        gravity[2] = (accelerometer_values[2] * kFilteringFactor) + (gravity[2] * (1.0f - kFilteringFactor));

        linear_acceleration[0] = (accelerometer_values[0] - gravity[0]);
        linear_acceleration[1] = (accelerometer_values[1] - gravity[1]);
        linear_acceleration[2] = (accelerometer_values[2] - gravity[2]);

        float magnitude = 0.0f;
        magnitude = (float)Math.sqrt(linear_acceleration[0]*linear_acceleration[0]+linear_acceleration[1]*linear_acceleration[1]+linear_acceleration[2]*linear_acceleration[2]);
        magnitude = Math.abs(magnitude);
if(magnitude>0.2)
  //walking

Массив гравитации [] инициализируется 0s.

Я могу обнаружить, когда пользователь идет или нет (глядя на величину величины вектора ускорения), но моя проблема в том, что когда пользователь не идет, и он перемещает телефоны, кажется, что он идет.

Я использую правильный фильтр?

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

Ответы

Ответ 1

Google предоставляет API для этого под названием DetectedActivity, который можно получить с помощью ActivityRecognitionApi. Доступ к этим документам можно получить здесь и здесь.

DetectedActivity имеет метод public int getType(), чтобы получить текущую активность пользователя, а также public int getConfidence(), которая возвращает значение от 0 до 100. Чем выше значение, возвращаемое getConfidence(), тем более определен API что пользователь выполняет возвращенную активность.

Вот постоянное резюме того, что возвращается getType():

  • int IN_VEHICLE Устройство находится в автомобиле, таком как автомобиль.
  • int ON_BICYCLE Устройство находится на велосипеде.
  • int ON_FOOT Устройство находится на пользователе, который идет или работает.
  • int RUNNING Устройство находится у пользователя, который работает.
  • int STILL Устройство все еще (не перемещается).
  • int TILTING Угол устройства относительно силы тяжести значительно изменился.
  • int UNKNOWN Невозможно обнаружить текущую активность.
  • int WALKING Устройство находится на пользователе, который идет.

Ответ 2

Моя первая интуиция заключалась в том, чтобы запустить анализ БПФ в истории датчиков и посмотреть, какие частоты имеют высокие величины при ходьбе.

По сути, он видит, что ходьба "звучит", обрабатывая входные данные датчика акселерометра, такие как микрофон, и видя громкие частоты при ходьбе (другими словами, на какой частоте происходит самое большое ускорение).

Я бы предположил, что вы будете искать высокую величину на некоторой низкой частоте (например, скорость шагов) или, может быть, что-то еще. Было бы интересно посмотреть данные.

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

Ответ 3

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

В этом приложении был использован следующий код https://play.google.com/store/apps/details?id=com.tartakynov.robotnoise

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){
            return;
        }
        final float z = smooth(event.values[2]); // scalar kalman filter                               
        if (Math.abs(z - mLastZ) > LEG_THRSHOLD_AMPLITUDE)
        {
            mInactivityCount = 0;
            int currentActivity = (z > mLastZ) ? LEG_MOVEMENT_FORWARD : LEG_MOVEMENT_BACKWARD;                  
            if (currentActivity != mLastActivity){
                mLastActivity = currentActivity;
                notifyListeners(currentActivity);
            }                   
        } else {
            if (mInactivityCount > LEG_THRSHOLD_INACTIVITY) {
                if (mLastActivity != LEG_MOVEMENT_NONE){
                    mLastActivity = LEG_MOVEMENT_NONE;
                    notifyListeners(LEG_MOVEMENT_NONE);                                 
                }
            } else {
                mInactivityCount++;
            }
        }
        mLastZ = z;
    }

Ответ 4

EDIT: я не думаю, что это достаточно точно, так как при обычной ходьбе среднее ускорение будет около 0. Самое большее, что вы можете сделать, - это ускорение измерения, когда кто-то начинает ходить или останавливается (но, как вы сказали, трудно фильтровать это из устройства, перемещаемого кем-то стоящим в одном месте)

Итак... то, что я написал раньше, вероятно, не сработает:

Вы можете "предсказать", движется ли пользователь, отбрасывая, когда пользователь не движется (очевидно), И первые два варианта, которые мне приходят в голову:
Проверьте, не скрыт ли телефон, с помощью датчика приближения и освещенности (опция). Этот метод менее точен, но проще.
Контролируя непрерывность движения, если телефон движется более чем на 10 секунд, и движение не презрительно, вы считаете, что он идет. Я знаю, что это тоже не перфекционизм, но, кстати, трудно использовать какое-либо позиционирование... почему бы вам просто не использовать LocationManager?

Ответ 5

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

Вы измеряете горизонтальное ускорение и обновляете значение скорости с его помощью. Скорость будет дрейфовать со временем, но вам нужно сохранять сглаженную скользящую среднюю скорость за время шага, и до тех пор, пока она не дрейфует больше, чем, скажем, половина скорости ходьбы за 3 колебания, тогда она идет, но только если она первоначально за короткое время поднялся до скорости ходьбы, то есть, возможно, за полсекунды или 2 колебаний.
Все это должно примерно покрыть это. Конечно, немного ai поможет сделать вещи проще или сложнее, но удивительно точными, если вы рассмотрите все это как входные данные для NN. Т.е. предварительная обработка.