Android: ложное обнаружение акселерометра

У меня есть фрагмент кода для обнаружения движений акселерометра. Иногда он работает, правильно обнаруживая небольшие движения, но иногда он обнаруживает движения, когда я не использовал свое устройство. Есть ли проблемы со встроенным определением акселерометра на Android?

Я использую устройство HTC G-1. Мой фрагмент кода ниже. Как мне решить эту проблему, чтобы я мог обнаруживать небольшие движения устройства, но не обнаруживать ничего, когда устройство находится в режиме ожидания?

private static final int SHAKE_THRESHOLD = 50;

public void onSensorChanged(int sensor, float[] values) {

    if (sensor == SensorManager.SENSOR_ACCELEROMETER) {
        long curTime = System.currentTimeMillis();
        // only allow one update every 100ms.
        if ((curTime - lastUpdate) > 100) {
            long diffTime = (curTime - lastUpdate);
            lastUpdate = curTime;

            x = values[SensorManager.DATA_X];
            y = values[SensorManager.DATA_Y];
            z = values[SensorManager.DATA_Z];

            float speed = Math.abs(x+y+z - last_x - last_y - last_z) / diffTime * 10000;

            if (speed > SHAKE_THRESHOLD) { 
                long curTime = System.currentTimeMillis();
                long diff = (curTime - shakeTime);              
                shakeTime = curTime;

                if (myFlagIgnoreShakeDetection==true)  //Caused unneccessary accelerometer   
                                                       //notification looping when device is idle
                   return;

                // Doing something...
            }
         last_x = x;
         last_y = y;
         last_z = z;
        }

    }

}

person Getsy    schedule 27.10.2009    source источник
comment
Возможно, вы захотите выполнить правильное векторное сложение ускорений: рывок = Math.sqrt(Math.pow(x-last_x, 2) + Math.pow(y-last_y, 2) + Math.pow(z-last_z, 2) )/diffTime * 10000; В противном случае изменение ускорения всего на 0,29 м/с^2 приведет к срабатыванию вашего порога.   -  person peejaybee    schedule 27.10.2009
comment
Я изменил отступ в вашем фрагменте кода, чтобы лучше показать, где находятся открывающая и закрывающая фигурные скобки.   -  person gnovice    schedule 27.10.2009
comment
Еще одна проблема... где-то инициализированы lastUpdate, shakeTime, last_x, last_y и last_z? Какие у них начальные значения?   -  person gnovice    schedule 27.10.2009
comment
частный поплавок x, y, z; частный float last_x, last_y, last_z; долгое время встряхивания=-1; закрытый длинный lastUpdate = -1;   -  person Getsy    schedule 27.10.2009
comment
Наконец-то я смог понять, в чем причина проблемы, но нашел ее при тестировании на устройстве HTC, а не через код. Когда я какое-то время использую устройство, а затем помещаю его в режим ожидания, оно работает, как и ожидалось (без ложных событий) в сценарии. Сценарий таков: мне нужно немного подвигать устройство (немного сильно на моем столе) для простоя, тогда оно перестанет уведомлять о ложных событиях. В противном случае, если я ставлю устройство на стол без движения (очень медленно), то акселерометр продолжает уведомлять мое приложение, что вызывает ложные события. Любые предложения по моему коду сейчас?   -  person Getsy    schedule 27.10.2009
comment
Я исправил это, удалив оператор return в своем коде. Пожалуйста, обратитесь к моему коду выше, который показывает return [ if (myFlagIgnoreShakeDetection==true) ] внутри кода акселерометра, что вызывало ненужное зацикливание ложного уведомления акселерометра, когда устройство находится в режиме ожидания. Пожалуйста, будьте осторожны, код обнаружения акселерометра НЕ ДОЛЖЕН содержать внутри оператора возврата.   -  person Getsy    schedule 28.10.2009
comment
Если myFlagIgnoreShakeDetection является логическим значением, то часть ==true не нужна.   -  person gnovice    schedule 28.10.2009
comment
Может быть, это будет интересно, мой пример. Это работает довольно хорошо maephv.blogspot.com/2011/ 10/   -  person Maep    schedule 26.10.2011
comment
@Getsy, где вы устанавливаете значение логической переменной myFlagIgnoreShakeDetection, вы только проверяете ее на истинность   -  person varun    schedule 07.02.2014


Ответы (2)


Вот несколько несоответствий кода...

  • Может возникнуть проблема с обновлением last_x, last_y и last_z. Я считаю, что они должны быть включены внутри оператора if ((curTime - lastUpdate) > 100) {. Другими словами, они обновляются каждый раз при вызове onSensorChanged, а не каждые 100 миллисекунд. Вероятно, вам следует переместить обновление этих трех переменных в фигурную скобку над ними.

  • В строке, где вы вычисляете speed, формула заканчивается ... / diffTime * 10000; Вы хотите умножить только diffTime на 10000 или весь результат? Поскольку / и * обычно имеют одинаковый приоритет оператора в большинстве известных мне языков (например, Java), ваше уравнение будет оцениваться слева направо , разделив сначала на diffTime затем умножив результат на 10000.

    Я предполагаю, что вы имеете в виду просто умножить diffTime на 10000, тем самым разделив окончательный результат на эту сумму. Это разница между делением на 10000 и умножением на 10000, что означает, что вы, вероятно, получаете значения для speed, которые на 10 ^ 8 больше, чем должны, что приводит к срабатыванию вашего порога, даже когда устройство находится в режиме ожидания. Вам нужно заключить умножение в круглые скобки, например ... / (diffTime * 10000);, чтобы оно было выполнено до деления.

    Кроме того, если вы собираетесь масштабировать diffTime от миллисекунд до секунд, коэффициент масштабирования должен быть равен 1000.

person gnovice    schedule 27.10.2009
comment
извините за путаницу. Он есть внутри if ((curTime - lastUpdate) › 100) { only. На самом деле я пропустил } (закрывающая фигурная скобка) в последней строке моего кода. Я пытался использовать предложение Mr.peejaybee, но все же это не работает должным образом. Иногда, если он обнаруживает акселерометр, даже когда устройство находится в режиме ожидания, это вызывает ложное уведомление, и я не могу выполнить свой код, как я ожидал. - person Getsy; 27.10.2009
comment
@unknown: Если вы пропустили } в конце своего кода, то этих трех строк нет внутри оператора if, который проверяет время. Обратите внимание, что у вас есть две открывающие фигурные скобки (по одной для каждого оператора if) и две закрывающие скобки, следующие за вторым оператором if, так что три строки, которые обновляются в конце, находятся вне первого оператора if. - person gnovice; 27.10.2009
comment
@gnovice, да, ОП определенно нужно обновить last_x и т. Д. Внутри обновления, если тест. - person Bob Cross; 27.10.2009
comment
Я продолжал так (пожалуйста, посмотрите мой код, обновленный, как вы предложили), все еще не работает. Я постоянно получаю акселерометр, даже когда устройство не используется. - person Getsy; 27.10.2009
comment
Почему если (датчик == SensorManager.SENSOR_ACCELEROMETER) и если (скорость › SHAKE_THRESHOLD) вызываются, даже когда устройство находится в режиме ожидания? - person Getsy; 27.10.2009
comment
@unknown: Вы обратились ко второму пункту, который я добавил выше? Это может быть дымящийся пистолет. - person gnovice; 27.10.2009
comment
Если скорость с плавающей запятой = Math.abs(x+y+z - last_x - last_y - last_z) / (diffTime * 1000); с акселерометром ничего не работает. Даже не обнаруживая, что работало по крайней мере какое-то время. Давайте посмотрим, как я могу это решить? - person Getsy; 27.10.2009
comment
@unknown: Есть несколько вещей, которые вам нужно попробовать сейчас: вам нужно также масштабировать результат Math.abs(...), чтобы получить его в определенных единицах (метры, см, мм)? Вам нужно перенастроить SHAKE_THRESHOLD? Вам нужно использовать правильное добавление векторов, как предложил peejaybee? - person gnovice; 27.10.2009
comment
Наконец-то я смог понять, в чем причина проблемы, но нашел ее при тестировании на устройстве HTC, а не через код. Когда я какое-то время использую устройство, а затем помещаю его в режим ожидания, оно работает, как и ожидалось (без ложных событий) в сценарии. Сценарий таков: мне нужно немного подвигать устройство (немного сильно на моем столе) для простоя, тогда оно перестанет уведомлять о ложных событиях. В противном случае, если я ставлю устройство на стол без движения (очень медленно), то акселерометр продолжает уведомлять мое приложение, что вызывает ложные события. Любые предложения по моему коду сейчас? - person Getsy; 27.10.2009
comment
Я исправил это, удалив оператор return в своем коде. Пожалуйста, обратитесь к моему коду выше, который показывает return [ if (myFlagIgnoreShakeDetection==true) ] внутри кода акселерометра, что вызывало ненужное зацикливание ложного уведомления акселерометра, когда устройство находится в режиме ожидания. Пожалуйста, будьте осторожны, код обнаружения акселерометра НЕ ДОЛЖЕН содержать внутри оператора возврата. - person Getsy; 28.10.2009
comment
Эти дополнительные строки, возможно, было бы полезно показать в исходном сообщении. Возможно, вы бы быстрее решили свою проблему. ;) - person gnovice; 28.10.2009
comment
@gnovice Эй, не могли бы вы проверить этот вопрос, пожалуйста?... Я думаю, ты можешь мне помочь - person Skizo-ozᴉʞS; 25.01.2016

Лично я в своей библиотеке дополненной реальности использую скользящее среднее для обновлений:

float kFilteringFactor = (float)0.05;    
rollingZ = (float) ((rawZValue * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor)));

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

rawZValue — это необработанное значение, поступающее с акселерометра.

person haseman    schedule 27.10.2009
comment
Что делает RollingZ? Можете ли вы предоставить немного больше? - person Getsy; 28.10.2009
comment
Haseman, Как бы вы изменили код на основе вашего предложения? Это было бы большим подспорьем для меня, чтобы легко понять. - person Getsy; 28.10.2009
comment
Я исправил это, удалив оператор return в своем коде. Пожалуйста, обратитесь к моему коду выше, который показывает return [ if (myFlagIgnoreShakeDetection==true) ] внутри кода акселерометра, что вызывало ненужное зацикливание ложного уведомления акселерометра, когда устройство находится в режиме ожидания. Пожалуйста, будьте осторожны, код обнаружения акселерометра НЕ ДОЛЖЕН содержать внутри оператора возврата. - person Getsy; 28.10.2009
comment
Лично я вношу переменную rollZ в свой набор дополненной реальности в качестве фактических значений. rawZValue в вашем коде будет value[SensorManager.DATA_Z]; Я написал об этом статью здесь: devx.com/wireless/Article/ 43005/0/стр./2 - person haseman; 28.10.2009