Acelerómetro (acceso rápido) mediante NativeActivity NDK

He buscado un tutorial / una respuesta en el acelerómetro de sondeo más rápido con NDK, pero no encontró solver todavía. Acaba de encontrar una documentación androiddevelopers aquí .

Lo que necesito es la aceleración de sondeo de 100 muestras por segundo (100Hz), por defecto mi dispositivo (Samsung Galaxy SL i9003 con pan de jengibre 2.3.5) con el defecto SENSOR_DELAY_FASTEST sólo puede obtener unas 60 muestras persecond (60Hz). Por lo tanto, traté de acceder a sensor a través de NativeActivity con NDK mediante la generación de archivos. C que intento hacer basado en 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 = %fy = %fz=%f ", event.acceleration.x, event.acceleration.y, event.acceleration.z); } } } } } 

Hasta ahora, he podido acceder al acelerómetro con NativeActivity, pero no hay cambio con el número de muestra que había tomado. Incluso cuando cambio ASensorEventQueue_setEventRate lo suficientemente grande o lo suficientemente pequeño la aceleración registrada todavía alrededor de 60 muestras por segundo (1 muestras por 15 milisegundos)

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

gracias por adelantado

También intenté algunas cosas con la velocidad de muestreo de los sensores. Yo uso un Galaxy Nexus. Si utilizo sólo el Acc-Sensor la frecuencia es muy baja (alrededor de 40Hz), pero si utilizo el Acc-Sensor más el magnético y el giro-sensor 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 efecto. La tasa de muestreo es siempre la misma. El comportamiento es exactamente el mismo para SDK-Code.

Aquí está el código que usé para el benchmarking:

 #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; } 

La pregunta es un poco vieja pero quizás estos dos artículos ayudarán hacia fuera un pedacito para cualquier persona que tropieza en esta pregunta y las maravillas por qué molestan, o cómo optimizar el ejemplo en el NDK un pedacito.

Estos dos artículos cortos de diseño de los problemas y soluciones potenciales (pero ninguna solución de fuente completa)

Java interconectado rendimiento del sensor

Mejoramiento Nativo de Muestreo

Esta es una vieja pregunta, pero dada la falta de documentación y artículos por ahí, pensé que compartiría mi experiencia. Hice todas mis pruebas en un Nexus 5X. Es posible que su dispositivo sea diferente.

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

Si vuelve a habilitar el sensor (por ejemplo, después de OnPause () y onResume ()), debe volver a configurar la tasa de eventos. Si tuviera una "habilitación doble" como lo hice en mi código (enable () / setEventRate () en init (), pero sólo enable () en onResume ()), obtendrá la frecuencia de sondeo predeterminada.

Probablemente esté limitado por la velocidad del hardware del acelerómetro en su dispositivo. Sin embargo, puede utilizar la interpolación para obtener algunos puntos de datos adicionales.

  • ¿Puede guardar / ver un archivo de vídeo y los datos del sensor simultáneamente?
  • ¿Cómo reemplazar adecuadamente Sensor.TYPE_ORIENTATION (que ahora está obsoleto)?
  • Android: Problemas al calcular la orientación del dispositivo
  • Edición de Pitch and Roll de Android
  • Valor de retorno falso inesperado de android.hardware.SensorManager.registerListener en Android 4.3
  • ¿Qué hace SampleRate.MS16, MS32, MS128 stand para cuando está asociado con oyentes de sensor?
  • Sensores para teléfonos móviles
  • Diferentes valores entre los sensores TYPE_ACCELEROMETER / TYPE_MAGNETIC_FIELD y TYPE_ORIENTATION
  • UnregisterListener no funciona con PROXIMITY_SCREEN_OFF_WAKE_LOCK
  • ¿Cómo voy a detectar el sensor de movimiento en el receptor de radiodifusión?
  • Android - Cómo acercarse al algoritmo de detección de caídas
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.