2009-12-10 103 views
8

我想滤除我魔术手机中方向/指南针传感器的噪音。Android罗盘噪声算法

一些读数似乎是90-180度,并且有很多微动。我尝试过不同的事情,并取得了有限的成功,所以我想知道是否有人可以推荐一种算法来过滤这种噪音以获得稳定的输出。

BR,Mads

回答

14

您需要低通滤波器。有说明和简单算法wikipedia

+7

有关如何实现低通滤波器的示例,请参阅Thom Nichols的优秀博客文章 - 第1部分(http://blog.thomnichols.org/2011/08/smoothing-sensor-data-with-a-low - 通过过滤器)和第2部分(http://blog.thomnichols.org/2012/06/smoothing-sensor-data-part-2) – 2014-06-13 19:08:06

+0

@JimJeffers这个实现是简单和辉煌的,接受了很多。谢谢 ! – Shlublu 2016-05-05 09:36:20

2

你试过了什么?你每秒得到多少读数?

我会建议沿着最后X次读数的平均值来排除“摇晃”,并丢弃任何与当前方向大不相同的读数,以阻止任何疯狂的“跳跃”值。 根据您获得的读数数量以及您所做的平均数量,您的应用可能会失去响应能力。

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

1

如果您确实得到了大量完全错误的值,那么您可能不想对它们进行平均。你可以尝试先应用一个中值滤波器 - 取N个样本,计算中位数,并丢弃超过+ - 某个阈值的任何值。之后您可以应用平滑过滤器。

3

我摆脱了大部分的噪音,只是使用较慢的更新时间。我不确定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:适合用户界面的速率
0

如果您的读数是“90-180度off”,那么您需要校准您的指南针,或者您的传感器发生故障。

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

0

你使用:

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

你可能会注册它们都被定向到您的onSensorChanged方法2个独立的传感器手柄。现在,在我的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); 
    } 
4

这真的很晚,但它可能会帮助像我这样的人谁来到这个问题。

使用类型旋转矢量传感器。无需使用低通滤波器或计算最后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]); 

    } 

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