Android加速度计采样率/延迟稳定

时间:2014-04-25 20:42:11

标签: android accelerometer sampling

我正在尝试使用加速度计的数据和onTouch方法来检测水龙头的力量。

据我所知,加速度计的最快采样频率为200-202Hz,但这种可变性在尝试匹配onTouch事件的时间戳和加速度计数据的峰值时给我带来了问题。

有没有办法稳定加速度计的读数以避免这个问题?喜欢控制特定的线程或什么?

2 个答案:

答案 0 :(得分:2)

问题似乎是在Android中运行java代码的Dalvik JVM,优先处理进程,因此如果应用程序不像设备运行的任何其他东西那么重要,它将把它放在抱一下。我发现解决这个问题的一种方法是在NDK上使用C或C ++,它直接在操作系统上运行,并且不依赖于JVM。 这是我的C ++类的代码,你可以用Java调用它。

#include <jni.h>
#include <string.h>

#include <android/sensor.h>
#include <android/log.h>
#include <android/looper.h>

#define TAG "accelerondk"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)

#define LOOPER_ID 1


extern "C" {

void JNICALL Java_com_example_hellojni_PruebaHilo_startMonitoring(JNIEnv* env, jclass clazz) {
    ASensorManager* sensorManager = ASensorManager_getInstance();

    ALooper* looper = ALooper_forThread();
    if(looper == NULL)
        looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);

    ASensorRef accelerometerSensor = ASensorManager_getDefaultSensor(sensorManager,ASENSOR_TYPE_ACCELEROMETER);
    LOGI("accelerometerSensor: %s, vendor: %s", ASensor_getName(accelerometerSensor), ASensor_getVendor(accelerometerSensor));

    ASensorEventQueue* queue = ASensorManager_createEventQueue(sensorManager, looper, LOOPER_ID, NULL, NULL);

    ASensorEventQueue_enableSensor(queue, accelerometerSensor);
    ASensorEventQueue_setEventRate(queue, accelerometerSensor, (1000L/200)*1000);

    int ident;//identifier
    int events;
    while (1) {
        while ((ident=ALooper_pollAll(-1, NULL, &events, NULL) >= 0)) {
            // If a sensor has data, process it now.
            if (ident == LOOPER_ID) {
                ASensorEvent event;
                while (ASensorEventQueue_getEvents(queue, &event, 1) > 0) {
                    LOGI("accelerometer X = %f y = %f z= %f ", event.acceleration.x, event.acceleration.y, event.acceleration.z);
                }
            }
        }
    }
}
}

此示例为您提供200Hz采样率,具有非常非常小的变化(每秒提供一个或两个额外读数),可以使用代码消除。 开始使用NDK的一个好方法是本书“Android Native Development Kit Cookbook”。

https://www.packtpub.com/application-development/android-native-development-kit-cookbook

答案 1 :(得分:1)

如果要匹配硬件提供的时间(event.timestamp)和系统时间,可以通过调整时间来完成此操作。

通常时间不一样,但它们只是相差一个恒定的毫秒数。我建议你打印两次并比较它们。然后您将注意到偏移量是什么:

在我的问题中,Ormi734建议使用以下代码:

private long timeDiff = 0l; // this will be used to adjust the offset between the times
private boolean offsetDetermined = false;

@Override
public void onSensorChanged(SensorEvent event) {

    // just determine the offset once, since it should remain constant
    // you could also adjust it every n samples if it needs to be really accurate
    if (!offsetDetermined) {
        long MiliTime = System.currentTimeMillis();
        long NanoTime = event.timestamp;
        timeDiff = MiliTime - NanoTime / 1000000;

        log.info("Synchornizing sensor clock. Current time= " + MiliTime+ ", difference between clocks = " + timeDiff);

        offsetDetermined = true;
    }

    float x = event.values[0];
    float y = event.values[1];
    float z = event.values[2];
    long ts = event.timestamp / 1000000 + timeDiff;

    // do your stuff here   
}

Accelerometer logger: experiencing occasional long delays between frames