Ускоритель доступа (ускоренный опрос) через NativeActivity NDK

Я искал учебник / ответ на опрос акселерометра быстрее с NDK, но еще не нашел решателя. Просто нашел здесь документацию разработчика androiddevelopers.

То, что мне нужно, – это ускорение опроса около 100 выборок в секунду (100 Гц), по умолчанию мое устройство (Samsung Galaxy SL i9003 с пряниками 2.3.5) с по умолчанию SENSOR_DELAY_FASTEST может получить только около 60 отсчетов в секунду (60 Гц). Поэтому я попытался получить доступ к датчику через NativeActivity с помощью NDK, создав файлы .c, которые я пытаюсь сделать на основе 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 = %fy = %fz=%f ", event.acceleration.x, event.acceleration.y, event.acceleration.z); } } } } } 

До сих пор мне удалось получить доступ к акселерометру с помощью NativeActivity, но никаких изменений с номером образца не было. Даже когда я изменяю ASensorEventQueue_setEventRate достаточно большим или достаточно маленьким, ускорение записывает еще около 60 выборок в секунду (1 образец на 15 milisec)

Есть ли ошибки в моем коде? Или что-то, что я забыл?

заранее спасибо

Solutions Collecting From Web of "Ускоритель доступа (ускоренный опрос) через NativeActivity NDK"

Я также пробовал несколько вещей с частотой дискретизации датчиков. Я использую Galaxy Nexus. Если я использую только Acc-Sensor, частота очень низкая (около 40 Гц), но если я использую Acc-Sensor плюс магнитный и гиро-сенсор, частота дискретизации для каждого датчика составляет около 100 Гц. У меня нет объяснений, почему это происходит. Другое замечание состоит в том, что значения, переданные в 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; } 

Вопрос немного устарел, но, возможно, эти две статьи немного помогут кому-либо, кто споткнется на этот вопрос, и задается вопросом, зачем беспокоиться, или как немного оптимизировать пример в NDK.

В этих двух кратких статьях рассматриваются проблемы и возможные решения (но не полное исходное решение)

Производительность сенсорного интерфейса Java

Усовершенствование выборки

Это старый вопрос, но, учитывая отсутствие документации и статей, я решил поделиться своим опытом. Я провел все тесты на Nexus 5X. Возможно, ваше устройство отличается.

Исходный код выглядит правильно. Что не очевидно из документации, так это то, что вы можете установить только скорость события после включения датчика, и что …

Если вы снова включите датчик (скажем, после onPause () и onResume ()) вам нужно снова установить частоту событий. Если у вас было «двойное включение», как это было в моем коде (enable () / setEventRate () в init (), но только enable () в onResume ()), вы получите ставку опроса по умолчанию.

Вероятно, вы ограничены скоростью аппаратуры акселерометра на вашем устройстве. Тем не менее, вы можете использовать интерполяцию для получения дополнительных точек данных.