代码之家  ›  专栏  ›  技术社区  ›  Ronnie

安卓罗盘噪声算法

  •  9
  • Ronnie  · 技术社区  · 16 年前

    我正试图过滤掉魔法手机中方位/罗盘传感器发出的噪音。

    有些读数似乎是90-180度,有很多抖动。我尝试过不同的方法,但成功率有限,所以我想知道是否有人可以推荐一种算法来过滤这种噪声以获得稳定的输出。

    Mads

    7 回复  |  直到 9 年前
        1
  •  15
  •   db_    16 年前

    你需要低通滤波器。有解释和简单的算法 wikipedia

        2
  •  4
  •   Rahul Sainani    9 年前

    这真的很晚了,但它可能会帮助像我这样的人提出这个问题。

    使用类型旋转矢量传感器。无需使用低通滤波器或计算最后x个传感器值的平均值。

    下面是一些代码:

    private float[] mMatrixR = new float[9];
    private float[] mMatrixValues = new float[3];
    
    @Override
    public void onSensorChanged(SensorEvent event) {
        switch (event.sensor.getType()) {
            case Sensor.TYPE_ROTATION_VECTOR:
    
                // Get rotation matrix
                SensorManager.getRotationMatrixFromVector(mMatrixR, event.values);
    
                SensorManager.getOrientation(mMatrixR, mMatrixValues);
    
                // Use this value in degrees
                mAzimuth = Math.toDegrees(mMatrixValues[0]);
    
        }
    

    我发现这些值非常快速和平滑,并在我的应用程序中使用它们。我使用加速度计和磁强计作为备份,以防设备中不存在旋转型矢量,它是一种基于软件的传感器(传感器融合),使用磁强计、加速度计和陀螺仪(如果存在)。

        3
  •  3
  •   Jeremy Logan    16 年前

    我只是用一个较慢的更新时间来消除大部分噪音。我不确定Android是否有内置的过滤器,但它似乎稳定了很多。类似:

    mSensorManager.registerListener( 
        mSensorListener, 
        mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), 
        // SENSOR_DELAY_UI, instead of SENDOR_DELAY_FASTEST (or similar)
        //    seems to iron out a lot of the jitter
        SensorManager.SENSOR_DELAY_UI
    );
    

    SensorManager 提供:

    • SENSOR_DELAY_FASTEST :尽快获取传感器数据
    • SENSOR_DELAY_GAME :适合游戏的费率
    • SENSOR_DELAY_NORMAL :适合屏幕方向更改的速率(默认)
    • SENSOR_DELAY_UI :适合用户界面的速率
        4
  •  2
  •   Loopo    16 年前

    你试过什么?你每秒能读取多少读数?

    我建议用最后x个读数的平均值来消除“抖动”,并扔掉任何与当前方向完全不同的读数,以阻止任何疯狂的值“跳跃”。 根据你得到的读数和平均值,你的应用程序可能会失去响应能力。

    以下链接可能有用。 http://www.chem.uoa.gr/applets/appletsmooth/appl_smooth2.html

        5
  •  1
  •   Mark Bessey    16 年前

    如果你确实得到了大量完全错误的值,你可能不想只是平均它们。你可以先尝试应用一个中值过滤器——取n个样本,计算中值,然后抛出任何超过+的值——一些阈值。之后可以应用平滑过滤器。

        6
  •  0
  •   jap1968    14 年前

    如果你的读数是“90-180度”,那么要么你需要校准你的罗盘,要么你的传感器有故障。

    当然,磁传感器有很多抖动,但这种噪声的“标准偏差”大约是4度。你可以选择各种数学滤波器(低通,卡尔曼)和算法(平均,下降假读数)来应用于测量,可以给你可接受的结果。

        7
  •  0
  •   giannileuani    13 年前

    你使用的是:

    List<Sensor> sens = mySensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
    

    您可能注册了两个单独的传感器手柄,它们都指向您的OnSensorChanged方法。现在,在我的onsensorchanged方法中,我将根据供应商名称将轴承值发送给主方法或辅助方法。因此,请尝试以下代码:

        Sensor sen = e.sensor;
        double bearing = 0;
        if (sen.getType()==Sensor.TYPE_ORIENTATION) {
            bearing = e.values[SensorManager.DATA_X];
        }
        if (sen.getVendor().equals(sensorVendors[0])) {
            myCompassView.setBearing(bearing);
        } else {
            myCompassView.setSecondaryBearing(bearing);
        }