Android SensorEvent Постоянная метка времени
В настоящее время я пишу простое приложение для Android, чтобы рассчитать смещения устройств IMU. При этом я столкнулся с проблемой со значением event.timestamp
Используя код:
float dT = (event.timestamp-accel_timestamp)*NS2S;
из примера в Справочном руководстве по Android, чтобы вычислить матрицу вращения из кватерниона.
Когда я запускаю код с помощью Galaxy Nexus-S, я получаю dT 0,06~0,07 сек между измерениями, но когда я запускаю один и тот же код на LG Nexus 4 или Nexus 7, dT всегда равен 0. Я знаю вопрос Временная метка Android SensorEvent указывает на то, что временная метка Nexus 7 является временной меткой Unix, но разница между последовательными измерениями не всегда должна быть равна нулю. Как Nexus 4, так и Nexus 7 имеют одинаковый IMU, может ли это быть ошибкой при создании временной метки из IMU?
3 ответа
Вау, хорошо, это, безусловно, ошибка!
Временная метка каждого SensorEvent перезаписывается, как если бы это была статическая переменная...
Когда я записываю строку метки времени, когда происходит событие, все значения разные.
События хранятся в массиве без изменений.
Каждый SensorEvent в массиве теперь имеет одну и ту же временную метку, но массивы значений по-прежнему различны (т. Е. Они не являются одним и тем же объектом и содержат разную информацию... ЗА ИСКЛЮЧЕНИЕМ для временной метки).
Google / HTC, верните, пожалуйста, 3 часа моей жизни!
Я пойду подать отчет об ошибке, если никто не может объяснить это поведение. Это, конечно, не документировано в API.
А пока попробуйте это решение:
import android.hardware.Sensor;
import android.hardware.SensorEvent;
public class UnbrokenSensorEvent {
public long timestamp;
public float[] values;
public Sensor sensor;
public UnbrokenSensorEvent(SensorEvent event){
this.timestamp = event.timestamp;
this.values = event.values;
this.sensor = event.sensor;
}
}
Затем сделайте что-то вроде этого в вашем слушателе:
ArrayList<UnbrokenSensorEvent> results = new ArrayList<UnbrokenSensorEvent>();
public void onSensorChanged(SensorEvent event) {
results.add(new UnbrokenSensorEvent(event));
}
Рефакторинг должен быть довольно простым, поскольку SensorEvent и UnbrokenSensorEvent имеют одинаковые открытые поля. Если вам нужно использовать другие функциональные возможности SensorEvent, просто включите его в версию Unbroken.
Это взломано, но IMHO быстрый взлом всегда лучше, чем ждать обновления API!
Также обратите внимание на документацию по SensorSventListener onSensorChanged -method:
ПРИМЕЧАНИЕ. Приложению не принадлежит объект события, переданный в качестве параметра, и, следовательно, он не может его удерживать. Объект может быть частью внутреннего пула и может быть повторно использован платформой.
Найдено здесь: http://developer.android.com/reference/android/hardware/SensorEventListener.html
... что говорит о том, что не следует хранить ссылки на объекты SensorEvent.
Если вы скопировали фрагмент отсюда, обратите внимание, что в нем есть ошибка. Нужно заменить
private float timestamp;
в
private long timestamp;
В другом случае ваше дельта время всегда будет содержать странные значения