我正在尝试使用加速度计的数据和onTouch方法来检测水龙头的力量。
据我所知,加速度计的最快采样频率为200-202Hz,但这种可变性在尝试匹配onTouch事件的时间戳和加速度计数据的峰值时给我带来了问题。
有没有办法稳定加速度计的读数以避免这个问题?喜欢控制特定的线程或什么?
答案 0 :(得分:2)
问题似乎是在Android中运行java代码的Dalvik JVM,优先处理进程,因此如果应用程序不像设备运行的任何其他东西那么重要,它将把它放在抱一下。我发现解决这个问题的一种方法是在NDK上使用C或C ++,它直接在操作系统上运行,并且不依赖于JVM。 这是我的C ++类的代码,你可以用Java调用它。
#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
extern "C" {
void JNICALL Java_com_example_hellojni_PruebaHilo_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/200)*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("accelerometer X = %f y = %f z= %f ", event.acceleration.x, event.acceleration.y, event.acceleration.z);
}
}
}
}
}
}
此示例为您提供200Hz采样率,具有非常非常小的变化(每秒提供一个或两个额外读数),可以使用代码消除。 开始使用NDK的一个好方法是本书“Android Native Development Kit Cookbook”。
https://www.packtpub.com/application-development/android-native-development-kit-cookbook
答案 1 :(得分:1)
如果要匹配硬件提供的时间(event.timestamp)和系统时间,可以通过调整时间来完成此操作。
通常时间不一样,但它们只是相差一个恒定的毫秒数。我建议你打印两次并比较它们。然后您将注意到偏移量是什么:
在我的问题中,Ormi734建议使用以下代码:
private long timeDiff = 0l; // this will be used to adjust the offset between the times
private boolean offsetDetermined = false;
@Override
public void onSensorChanged(SensorEvent event) {
// just determine the offset once, since it should remain constant
// you could also adjust it every n samples if it needs to be really accurate
if (!offsetDetermined) {
long MiliTime = System.currentTimeMillis();
long NanoTime = event.timestamp;
timeDiff = MiliTime - NanoTime / 1000000;
log.info("Synchornizing sensor clock. Current time= " + MiliTime+ ", difference between clocks = " + timeDiff);
offsetDetermined = true;
}
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
long ts = event.timestamp / 1000000 + timeDiff;
// do your stuff here
}
Accelerometer logger: experiencing occasional long delays between frames