(请阅读最后的更新3)我正在开发一个应用程序,它不断地与设备的传感器一起工作,与Accelerometer和Magnetic传感器一起工作以检索设备的方向(目的是提到这里)。换句话说,我的应用程序需要实时了解设备的定位(然而,这是不可能的,所以要尽可能快,但要和可能的一样快!)如Reto Meier在专业的Android 4应用程序开发中所提到的
加速度计每秒能更新数百次.
我不能丢失传感器报告的任何数据,我还想对这些数据执行耗时的操作(检索方向,然后进行计算.)。我决定用LinkedBlockingQueue来解决我的问题
public void startSensors() {
LinkedBlockingQueue<float[][]> array=new LinkedBlockingQueue();
sensorListenerForOrientation = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
aValues = (event.values.clone());
else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mValues = (event.values.clone());
if (aValues != null && mValues != null) {
try {
array.put(new float[][] { aValues, mValues });
} catch (InterruptedException e) {
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
Sensor aSensor = sm.getSensorList(Sensor.TYPE_ACCELEROMETER).get(
sm.getSensorList(Sensor.TYPE_ACCELEROMETER).size() - 1);
Sensor mSensor = sm.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).get(
sm.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).size() - 1);
sm.registerListener(sensorListenerForOrientation, aSensor,
SensorManager.SENSOR_DELAY_FASTEST);
sm.registerListener(sensorListenerForOrientation, mSensor,
SensorManager.SENSOR_DELAY_FASTEST);
executor.execute(new Runnable() {
@Override
public void run() {
doCalculations();
}
});
}和
public void doCalculations() {
for (;;) {
float[][] result = null;
try {
result = array.take();
} catch (InterruptedException e) {
}
float[] aValues, mValues;
aValues = result[0];
mValues = result[1];
int[] degrees=getOrientation(aValues,mValues);
Log.e("",String.valueOf(degrees[0]));
//other calculations...
}
}现在我拿起我的设备,向右旋转大约90度,然后快速地返回到第一个位置(例如1.5秒),但是当我看到在设备中注册的方向时,例如:0,1,2,3,4,5.,40,39,38,37,....,0
我只想说,,我不能在我的结果中看到一个很大的学位域。基于我所做的和我研究过的,我可以确定我没有丢失任何数据,传感器报告的任何新数据都记录了。
有什么办法吗?!
致以问候!
更新1:,我用我的设备做了另一个实验,得到了令人震惊的结果!如果我以90度(不到1秒)的速度旋转我的设备,我可以在我的结果中看到所有的度: 0,1,2,3,....,89,90 (例如),但是如果我将它旋转90度,然后将它旋转回它的第一个位置,结果将是0,1,2,...,36,37,36,...2,1,0(例如)...really混淆!
更新2:我更新了doCalculations()方法,以便更清楚地了解我所做的事情
更新3:我想也许我们可以用另一种方式解决这个问题!我对这段代码有明确的目的。请看一下 这。我已经提到了将要发生的事情,我需要发现一个特定的动作动作。所以,也许我所选择的方法(上面的技术)并不是解决这个问题的好方法。也许通过使用其他传感器或者用其他方式使用相同的传感器来检测这个手势更好。你觉得呢?
发布于 2013-09-22 01:01:33
你的代码看起来很合理。一个很大的未知是传感器和传感器融合在你的设备中有多好。快速角度变化读数依赖于角加速度的积分,或者是一个带有磁性数据的物理陀螺仪来使结果与地球完全一致。磁性数据受周围环境的影响。如果你的设备有低质量的感应器,或者你的环境中有磁场干扰,那么你所看到的错误是完全有可能的。大型金属结构和磁性设备(如电动机,甚至荧光灯镇流器)可以使磁场空白或造成任意误差。对于正常的用途,一个设备只需要一个加速度计,以准确地确定哪种方式下降,所以屏幕翻转是准确的。这只需要在设备不动时才能工作,因为陀螺仪不起作用。如果你有一部带有传感器的手机或平板电脑--因此没有陀螺仪或不准确的陀螺仪--你就看到了设备的局限性。这些不稳定的值是其他证据,表明你的设备质量很低,或者你处在一个地球磁场被扭曲的位置。在外面和外面的另一个(最好是昂贵的)设备上尝试这个程序,看看你得到了什么。
发布于 2013-09-18 00:36:28
因此,看起来您正在为标准的“生产者-消费者”问题寻找高吞吐量、低延迟的解决方案。基本上,这个想法非常简单:减少数据处理开销,并行处理数据。建议如下:
1.使用“低延迟”库
这些解决方案中的任何一个都将使您节省大量CPU周期。

2.明智地处理数据
每次你提交一份工作时都会有开销。批处理可能真的很有帮助。

连续处理数据。注意,executor.execute将消耗大量资源。几个长寿的消费者可能会有所帮助。
3.最后,使用微优化技术。
例如,摆脱if-else-if而支持switch。
跟踪所有的性能,以确定好的和坏的解决方案。实验。
编码愉快。
发布于 2013-09-18 15:00:27
我的想法是:请尝试以下几点:
public void startSensors() {
final Stack<Runnable> mStack = new Stack<Runnable>();
sensorListenerForOrientation = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
aValues = (event.values.clone());
else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mValues = (event.values.clone());
if (aValues != null && mValues != null) {
mStack.push(new Calculater(new float[][] { aValues, mValues });
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
Sensor aSensor = sm.getSensorList(Sensor.TYPE_ACCELEROMETER).get(
sm.getSensorList(Sensor.TYPE_ACCELEROMETER).size() - 1);
Sensor mSensor = sm.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).get(
sm.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).size() - 1);
sm.registerListener(sensorListenerForOrientation, aSensor,
SensorManager.SENSOR_DELAY_FASTEST);
sm.registerListener(sensorListenerForOrientation, mSensor,
SensorManager.SENSOR_DELAY_FASTEST);
new Thread() {
public void run() {
while(true)
{
try {
Runnable r = mStack.pop();
r.run();
} catch(Exception ex){}
}
}
}.start();
}
private class Calculater implements Runnable {
float[][] theValues;
public Calculater(float[][] values) {
theValues = values;
}
public void run() {
int[] degrees= getOrientation(theValues[0], theValues[1]);
Log.e("",String.valueOf(degrees[0]));
}
}https://stackoverflow.com/questions/18786694
复制相似问题