我的传感器监测技术出了什么问题?

Soh*_*eil 11 java android blockingqueue orientation-changes android-sensors

(请在最后阅读更新3)我正在开发一个应用程序,它不断与设备的传感器一起工作,AccelerometerMagnetic传感器一起工作以检索设备的方向(这里提到的目的).换句话说,我的应用程序需要知道设备的实时方位(然而,这是永远不可能的,所以尽可能快地代替,但真正以最快的速度可能!).正如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();
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

    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...
                     }
                                }
Run Code Online (Sandbox Code Playgroud)

现在我拿起​​我的设备并将其旋转大约90度到右侧,然后将其返回到第一位置快速(例如1.5秒),但我会考虑在设备中注册的方向我看到的例子:0,1 ,2,3,4,5- .......,40,39,38,37,...,0

我只想说我在结果中看不到大的度数范围.根据我所做的和我研究的内容,我可以确定我没有丢失任何数据,传感器报告的任何新数据都会记录下来.

任何想法,解决方案?!

问候!

更新1:我用我的设备做了另一个实验并获得了令人震惊的结果!如果我将设备快速旋转90度(小于一秒),我可以看到我的结果中的所有度数:0,1,2,3,....,89,90(例如)但是如果我旋转90度,然后将其旋转回第一个位置,结果将是0,1,2,...,36,37,36,...... 2,1,0(例如)......真的令人困惑!

更新2:我更新了doCalculations()方法,以便更清楚我所做的事情

更新3:我想也许我们可以用另一种方式解决问题!我对此代码有明确的目的.请看看这个.我已经提到将要发生的事情,我需要检测一个特定的移动手势.所以也许我选择的整个方式(上面的技术)不是解决这个问题的好方法.也许最好通过使用其他传感器或以其他方式使用相同的传感器来检测该手势.你怎么看?

Ren*_*nov 7

因此,您似乎正在尝试为标准的"生产者 - 消费者"问题找到高吞吐量低延迟解决方案.基本上这个想法很简单:减少数据处理开销,并行处理数据.建议如下:

1.使用"低延迟"库

  • javolution.org - 是一个实时库,旨在使Java或Java-Like/C++应用程序更快,更具时间可预测性.它包括Android支持.
  • mentaqueue - 是一个基于Disruptor思想的超快速,无垃圾,无锁,双线程(生产者 - 消费者)队列.Android支持未定义(它看起来应该可以工作).
  • 破坏者 - 另一个闪电般快速的图书馆
  • trove - 为Java提供高速常规和原始集合.

任何这些解决方案都可以让您节省大量的CPU周期.

在此输入图像描述

2.明智地处理数据

每次提交工作都会产生管理费用.批处理可能非常有用.

在此输入图像描述

持续处理数据.注意,executor.execute会消耗很多.一些长寿的消费者可能会有所帮助.

3.最后,使用微优化技术

例如,摆脱if-else-if赞成switch.

始终跟踪性能,以确定好的和坏的解决方案.实验.

快乐的编码.


Gen*_*ene 2

你的代码看起来很合理。一个很大的未知数是您的设备中的传感器和传感器融合有多好。快速角度变化读数依赖于角加速度的积分或混合有磁性数据的物理陀螺仪,以使结果与地球绝对对齐。磁性数据受周围环境的影响。如果您的设备具有低质量的传感器或您的环境中存在磁场干扰,则完全有可能看到您所看到的错误类型。大型金属结构和磁性设备(例如电机甚至荧光灯镇流器)可能会消隐磁场或引入任意误差。对于正常使用,设备只需要一个加速计来准确确定哪个方向向下,因此屏幕翻转是准确的。仅当设备不移动时,陀螺仪不起作用,这才需要工作。如果您的手机或平板电脑带有仅用于此目的的传感器 - 因此没有陀螺仪或不准确 - 您就会看到设备限制。不稳定的值是您的设备质量低下和/或您位于地球磁场扭曲的位置的其他证据。在户外的另一台(最好是昂贵的)设备上尝试该程序,看看会得到什么。