2012-01-24 5 views
14

He buscado un tutorial/una respuesta en el acelerómetro de sondeo más rápido con NDK pero todavía no he encontrado el solucionador. acabo de encontrar una documentación androiddevelopers here.acelerómetro de acceso (sondeo más rápido) a través de NativeActivity NDK

lo que necesito es una aceleración de sondeo de 100 muestras por segundo (100Hz), de manera predeterminada mi dispositivo (Samsung Galaxy SL i9003 con gingerbread 2.3.5) con SENSOR_DELAY_FASTEST predeterminado solo puede obtener 60 muestras de persecución (60Hz). Por lo tanto i intentó acceder sensor a través de NativeActivity con NDK mediante la generación .c archivos que trato de hacer en base a sensor.h y 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); 
       } 
      } 
     } 
    } 

} 

hasta ahora, he podido acceder a acelerómetro con NativeActivity, pero no hay cambios con el número de muestra que se tomó. incluso cuando cambio ASensorEventQueue_setEventRate lo suficientemente grande o pequeña, la aceleración registrada sigue siendo de alrededor de 60 muestras por segundo (1 muestra por 15 milisegundos)

¿Hay algún error en mi código? o algo con lo que me olvido?

gracias de antemano

+0

ha resuelto este problema? –

Respuesta

0

Usted probablemente está limitado por la velocidad del hardware acelerómetro en su dispositivo. Sin embargo, puede usar interpolation para obtener algunos puntos de datos adicionales.

8

También probé algunas cosas con la frecuencia de muestreo de los sensores. Yo uso un Galaxy Nexus. Si utilizo solo el Acc-Sensor, la frecuencia es muy baja (alrededor de 40Hz), pero si uso el Acc-Sensor más el magnético y el girosensor, la frecuencia de muestreo para cada sensor es de aproximadamente 100Hz. No tengo ninguna explicación de por qué sucede esto. Otra observación es que los valores pasados ​​a ASensorEventQueue_setEventRate no tienen ningún efecto. La frecuencia de muestreo es siempre la misma. El comportamiento es exactamente el mismo para SDK-Code.

Este es el código que he usado para la evaluación comparativa:

#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

¿Necesitaba crear una Actividad desde la cual ejecutar esto? Si es así, ¿podría publicar ese código? – Richard

+0

Lo siento, han pasado tres años desde que hice esto. Por lo que recuerdo, utilicé una GUI java de la cual llamé a las funciones JNI. Desafortunadamente no tengo código, pero creo que fue solo una llamada a la función. La parte más complicada fue configurar NDK en mi computadora (Eclipse). – steckl

+0

Lo descubrí, gracias. Probablemente actualizaré tu respuesta con algunos consejos sobre ella. – Richard

2

pregunta es un poco viejo, pero tal vez estos dos artículos ayudará a salir un poco de cualquier otra persona que se topa con esta pregunta y se pregunta por qué molestarse, o cómo para optimizar el ejemplo en el NDK un poco.

Estos dos artículos disposición corta los problemas y las posibles soluciones (pero sin solución de código completo)

Java interfaced sensor performance

Native Sampling Improvement

+1

Los enlaces han muerto. Intente copiar los materiales relevantes en su respuesta para que la información se pueda conservar. – Richard

1

Ésta es una vieja pregunta, pero dada la falta de documentación y artículos hacia fuera allí , Pensé que compartiría mi experiencia. Hice todas mis pruebas en un Nexus 5X. Tu dispositivo puede ser diferente.

El código original parece correcto. Lo que no es obvio a partir de la documentación es que sólo se puede establecer la tasa de eventos después permitiendo el sensor, y que ...

Si vuelve a activar el sensor (por ejemplo, después de onPause() y onResume()), necesita establecer la tasa de eventos nuevamente. Si tenía una "doble habilitación" como hice en mi código (enable()/setEventRate() en init(), pero solo enable() en onResume()), obtendrá la tasa de sondeo predeterminada.

Cuestiones relacionadas