Подтвердить что ты не робот

Ускоритель доступа (ускоренный опрос) через 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 = %f y = %f z=%f ", event.acceleration.x, event.acceleration.y, event.acceleration.z);
                }
            }
        }
    }

}

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

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

заблаговременно

4b9b3361

Ответ 1

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

Ответ 2

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

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

Работа с интерфейсом Java с интерфейсом

Улучшение первичной выборки

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

я также использую NDK, чтобы сделать тест, мой код

    **extern "C" JNIEXPORT jint JNICALL Java_com_xiangtianyu_sensorapplicationtest_sensortestcases_jnitest_JniSensorTest_testCreateSharedMemoryDirectChannel1(JNIEnv
*env,
                                                                        jobject instance) {
    // TODO
    int fakeValidFd = 1;


    return  ASensorManager_createSharedMemoryDirectChannel(nullptr, fakeValidFd, sizeof(ASensorEvent));

}

я также использую

включают

но когда я делаю свой проект, я получил эту ошибку

ошибка: неопределенная ссылка на 'ASensorManager_createSharedMemoryDirectChannel'

ты можешь мне помочь? благодарю вас