【问题标题】:Android accelerometer sampling rate/delay stabilizationAndroid 加速度计采样率/延迟稳定
【发布时间】:2014-04-25 20:42:10
【问题描述】:

我正在尝试通过使用来自加速度计的数据和 onTouch 方法来检测敲击的力度。

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

有没有办法稳定加速度计的读数来避免这个问题?比如控制特定线程什么的?

【问题讨论】:

    标签: android accelerometer sampling


    【解决方案1】:

    问题似乎是 Java 代码在 android 中运行的 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

    【讨论】:

      【解决方案2】:

      如果您想匹配硬件提供的时间(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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-18
        相关资源
        最近更新 更多