2012-01-24 2 views
14

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

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

} 

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

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

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

+0

Вы решаете эту проблему? –

ответ

0

Вы, вероятно, ограничены скоростью аппаратного акселерометра в устройстве. Однако вы можете использовать interpolation, чтобы получить дополнительные данные.

8

Я также пробовал несколько вещей с частотой дискретизации датчиков. Я использую 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; 
} 
+0

Вам нужно было создать мероприятие, из которого можно запустить это? Если да, не могли бы вы опубликовать этот код? – Richard

+0

Простите, прошло уже три года с тех пор, как я это сделал. Насколько я помню, я использовал java-GUI, с которого я назвал JNI-функции. К сожалению, у меня нет кода, но я думаю, что это был просто звонок. Самая сложная часть - установка NDK на моем компьютере (Eclipse). – steckl

+0

Я понял, спасибо. Я, вероятно, обнов свой ответ несколькими указателями. – Richard

2

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

Эти два коротких статей макета проблемы и возможные решения (но не полное решение исходного)

Java interfaced sensor performance

Native Sampling Improvement

+1

Ссылки умерли. Попробуйте скопировать соответствующие материалы в свой ответ, чтобы можно было сохранить информацию. – Richard

1

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

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

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

Смежные вопросы