2012-01-24 1 views
14

나는 폴링 가속도계에 대한 학습서/답변을 NDK로 더 빨리 찾았지만 아직 해결 방법을 찾지 못했습니다. 방금 안드로이드 개발자 문서 here을 발견했습니다.NativeActivity NDK를 통한 액세스 (더 빠른 폴링) 가속도계

초당 100 샘플 (100Hz)의 폴링 가속이 필요합니다. 기본적으로 SENSOR_DELAY_FASTEST가 기본 인 내 장치 (진저 브레드 2.3.5가있는 삼성 Galaxy SL i9003)는 약 60 샘플 (60Hz) 만 수신 할 수 있습니다. 그러므로 나는 기반으로 만들려고 파일을이 .c 생성하여 NDK와 NativeActivity를 통해 센서에 액세스하려고 sensor.h 및 looper.h :

#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 
#define SAMP_PER_SEC 100 //i've changed to 120, even 10, but nothing happen 

void Java_azka_web_ndk_AcceleroNDKActivity_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/SAMP_PER_SEC)*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("aaaaaaa accelerometer X = %f y = %f z=%f ", event.acceleration.x, event.acceleration.y, event.acceleration.z); 
       } 
      } 
     } 
    } 

} 

지금까지, 내가와 가속도계에 액세스 할 수있었습니다 NativeActivity, 그러나 샘플 번호가 변경된 것은 없습니다. ASensorEventQueue_setEventRate를 충분히 크게 또는 작게해도 초당 약 60 샘플 (15 밀리 초당 1 샘플)이 기록됩니다.

내 코드에는 어떤 실수가 있습니까? 또는 내가 잊어 버린 무엇인가?

미리 감사드립니다.

+0

이 문제는 해결 되었습니까? –

답변

0

기기의 가속도계 하드웨어 속도에 따라 제한 될 수 있습니다. 그러나 일부 추가 데이터 포인트를 얻으려면 interpolation을 사용할 수 있습니다.

8

또한 센서의 샘플 속도로 몇 가지 사항을 시도했습니다. 나는 Galaxy Nexus를 사용한다. Acc 센서 만 사용하는 경우 주파수는 매우 낮습니다 (약 40Hz). Acc 센서와 자기 센서 및 자이로 센서를 함께 사용하면 각 센서의 샘플 속도는 약 100Hz입니다. 왜 이러한 일이 발생하는지에 대한 설명이 없습니다. 또 다른 관찰은 ASensorEventQueue_setEventRate에 전달 된 값이 아무 효과가 없다는 것입니다. 샘플 속도는 항상 동일합니다. 동작은 SDK 코드와 완전히 동일합니다. 여기

내가 벤치마킹을 위해 사용되는 코드입니다 :

#include <string.h> 
#include <jni.h> 
#include <android/sensor.h> 
#include <android/looper.h> 
#include <android/log.h> 
#include <time.h> 
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "TestJNIActivity", __VA_ARGS__)) 
#define LOOPER_ID 1 
#define SAMP_PER_SEC 100 

ASensorEventQueue* sensorEventQueue; 

int accCounter = 0; 
int64_t lastAccTime = 0; 

int gyroCounter = 0; 
int64_t lastGyroTime = 0; 

int magCounter = 0; 
int64_t lastMagTime = 0; 

/* This is a trivial JNI example where we use a native method 
* to return a new VM String. See the corresponding Java source 
* file located at: 
* 
* apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java 
*/ 

static int get_sensor_events(int fd, int events, void* data); 

struct tm* start; 
struct tm* finish; 


jstring 
Java_de_tum_ndktest_TestJNIActivity_stringFromJNI(JNIEnv* env, jobject thiz) 
{ 
    LOGI("stringFromJNI"); 
    return (*env)->NewStringUTF(env,"Hello from JNI !"); 
} 

void 
Java_de_tum_ndktest_TestJNIActivity_sensorValue(JNIEnv* env, jobject thiz) { 

    ASensorEvent event; 
    int events, ident; 
    ASensorManager* sensorManager; 
    const ASensor* accSensor; 
    const ASensor* gyroSensor; 
    const ASensor* magSensor; 
    void* sensor_data = malloc(1000); 

    LOGI("sensorValue() - ALooper_forThread()"); 

    ALooper* looper = ALooper_forThread(); 

    if(looper == NULL) 
    { 
     looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 
    } 

    sensorManager = ASensorManager_getInstance(); 

    accSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER); 
    gyroSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_GYROSCOPE); 
    magSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_MAGNETIC_FIELD); 



    sensorEventQueue = ASensorManager_createEventQueue(sensorManager, looper, 3, get_sensor_events, sensor_data); 

    ASensorEventQueue_enableSensor(sensorEventQueue, accSensor); 
    ASensorEventQueue_enableSensor(sensorEventQueue, gyroSensor); 
    ASensorEventQueue_enableSensor(sensorEventQueue, magSensor); 

    //Sampling rate: 100Hz 
    int a = ASensor_getMinDelay(accSensor); 
    int b = ASensor_getMinDelay(gyroSensor); 
    int c = ASensor_getMinDelay(magSensor); 
    LOGI("min-delay: %d, %d, %d",a,b,c); 
    ASensorEventQueue_setEventRate(sensorEventQueue, accSensor, 100000); 
    ASensorEventQueue_setEventRate(sensorEventQueue, gyroSensor, 100000); 
    ASensorEventQueue_setEventRate(sensorEventQueue, magSensor, 100000); 

    LOGI("sensorValue() - START"); 
} 



static int get_sensor_events(int fd, int events, void* data) { 
    ASensorEvent event; 
    //ASensorEventQueue* sensorEventQueue; 
    while (ASensorEventQueue_getEvents(sensorEventQueue, &event, 1) > 0) { 
     if(event.type == ASENSOR_TYPE_ACCELEROMETER) { 
       //LOGI("accl(x,y,z,t): %f %f %f %lld", event.acceleration.x, event.acceleration.y, event.acceleration.z, event.timestamp); 
       if(accCounter == 0 || accCounter == 1000) 
        { 
        LOGI("Acc-Time: %lld (%f)", event.timestamp,((double)(event.timestamp-lastAccTime))/1000000000.0); 
        lastAccTime = event.timestamp; 
        accCounter = 0; 
        } 

       accCounter++; 
     } 
     else if(event.type == ASENSOR_TYPE_GYROSCOPE) { 
       //LOGI("accl(x,y,z,t): %f %f %f %lld", event.acceleration.x, event.acceleration.y, event.acceleration.z, event.timestamp); 
       if(gyroCounter == 0 || gyroCounter == 1000) 
        { 

        LOGI("Gyro-Time: %lld (%f)", event.timestamp,((double)(event.timestamp-lastGyroTime))/1000000000.0); 
        lastGyroTime = event.timestamp; 
        gyroCounter = 0; 
        } 

       gyroCounter++; 
     } 
     else if(event.type == ASENSOR_TYPE_MAGNETIC_FIELD) { 
       //LOGI("accl(x,y,z,t): %f %f %f %lld", event.acceleration.x, event.acceleration.y, event.acceleration.z, event.timestamp); 
       if(magCounter == 0 || magCounter == 1000) 
        { 
        LOGI("Mag-Time: %lld (%f)", event.timestamp,((double)(event.timestamp-lastMagTime))/1000000000.0); 
        lastMagTime = event.timestamp; 
        magCounter = 0; 
        } 

       magCounter++; 
     } 

    } 
    //should return 1 to continue receiving callbacks, or 0 to unregister 
    return 1; 
} 
+0

이 작업을 실행할 Activity를 생성해야합니까? 그렇다면이 코드를 게시 할 수 있습니까? – Richard

+0

죄송합니다. 제가 이것을 한 지 3 년이 지났습니다. 내가 아는 한, JNI 함수라고 불리는 java-GUI를 사용했다. 불행하게도 나는 코드를 가지고 있지 않지만 단지 funcion-call이라고 생각한다. 가장 복잡한 부분은 내 컴퓨터 (Eclipse)에서 NDK를 설정하는 것이 었습니다. – steckl

+0

나는 그것을 고맙게 생각했다. 아마 그것에 대한 몇 가지 포인터를 사용하여 답변을 업데이트 할 것입니다. – Richard

2

질문은 조금 오래된하지만 어쩌면이 두 기사는이 질문에 실수를 한단다과 기사 다른 사람에 대한 약간을 도움이 될 것입니다 왜 귀찮게하거나 방법 NDK의 예제를 약간 최적화 할 수 있습니다.

이이 짧은 기사

는 문제와 잠재적 인 솔루션 (하지만 완전한 소스 솔루션)

Java interfaced sensor performance

Native Sampling Improvement

+1

링크가 끊어졌습니다. 정보가 보존 될 수 있도록 관련 자료를 답안에 복사하십시오. – Richard

1

이 오래된 질문이지만, 거기에 문서 및 기사의 부족 주어진 레이아웃 나는 내 경험을 나누겠다고 생각했다. Nexus 5X에 대한 모든 테스트를 수행했습니다. 장치가 다를 수 있습니다.

원본 코드가 올바르게 보입니다. 어떤 문서에서 명확하지 않다 당신은 그 센서를 가능하게 후 이벤트 속도 을 설정하고 수 있다는 것입니다 ...

당신이 경우 onPause()와 onResume 후 센서 (말을 다시 활성화()), 이벤트 속도를 다시 설정해야합니다. init()에서 enable()/setEventRate()를 사용했지만 onResume()에서 enable()과 똑같이 "double enable"을 사용하면 기본 폴링 속도를 얻게됩니다.

관련 문제