平滑的GPS数据

Al.*_*Al. 141 gps smoothing

我正在使用GPS数据,每秒获取值并在地图上显示当前位置.问题是有时(特别是当精度很低时)值变化很大,使当前位置在地图中的远点之间"跳跃".

我想知道一些简单的方法来避免这种情况.作为第一个想法,我考虑过准确地丢弃超过一定阈值的值,但我想还有其他一些更好的方法.程序执行此操作的常用方法是什么?

Chr*_*uin 74

您正在寻找的是卡尔曼滤波器.它经常用于平滑导航数据.它不一定是微不足道的,你可以做很多调整,但它是一种非常标准的方法并且效果很好.有一个KFilter库可用,它是一个C++实现.

我的下一个后备将是最小方块拟合.卡尔曼滤波器将考虑速度平滑数据,而最小二乘拟合方法将仅使用位置信息.尽管如此,实施和理解它仍然更简单.看起来GNU科学图书馆可能会实现这一点.

  • http://kalman.sourceforge.net/index.php这里是卡尔曼滤波器的C++实现. (2认同)

Sto*_*lly 74

这是一个简单的卡尔曼滤波器,可以用于这种情况.它来自我在Android设备上所做的一些工作.

一般卡尔曼滤波器理论都是关于向量的估计,其中估计的准确性由协方差矩阵表示.但是,为了估计Android设备上的位置,一般理论简化为一个非常简单的情况.Android位置提供商将位置指定为纬度和经度,以及指定为以米为单位的单个数字的精度.这意味着,代替协方差矩阵,卡尔曼滤波器的精度可以通过单个数来测量,即使卡尔曼滤波器中的位置是由两个数字测量的.此外,纬度,经度和米实际上是所有不同单位的事实可以忽略,因为如果你将比例因子放入卡尔曼滤波器将它们全部转换为相同的单位,那么这些比例因子在转换结果时最终会被取消回到原来的单位.

代码可以改进,因为它假设当前位置的最佳估计是最后已知的位置,并且如果有人正在移动它应该可以使用Android的传感器来产生更好的估计.该代码具有单个自由参数Q,以米/秒表示,其描述了在没有任何新位置估计的情况下精度衰减的速度.较高的Q参数意味着精度衰减得更快.卡尔曼滤波器通常在精度衰减比预期快一点时效果更好,因此对于使用Android手机走动我发现Q = 3米每秒工作正常,即使我通常走得比这慢.但是如果乘坐快车,显然应该使用更大的数字.

public class KalmanLatLong {
    private final float MinAccuracy = 1;

    private float Q_metres_per_second;    
    private long TimeStamp_milliseconds;
    private double lat;
    private double lng;
    private float variance; // P matrix.  Negative means object uninitialised.  NB: units irrelevant, as long as same units used throughout

    public KalmanLatLong(float Q_metres_per_second) { this.Q_metres_per_second = Q_metres_per_second; variance = -1; }

    public long get_TimeStamp() { return TimeStamp_milliseconds; }
    public double get_lat() { return lat; }
    public double get_lng() { return lng; }
    public float get_accuracy() { return (float)Math.sqrt(variance); }

    public void SetState(double lat, double lng, float accuracy, long TimeStamp_milliseconds) {
        this.lat=lat; this.lng=lng; variance = accuracy * accuracy; this.TimeStamp_milliseconds=TimeStamp_milliseconds;
    }

    /// <summary>
    /// Kalman filter processing for lattitude and longitude
    /// </summary>
    /// <param name="lat_measurement_degrees">new measurement of lattidude</param>
    /// <param name="lng_measurement">new measurement of longitude</param>
    /// <param name="accuracy">measurement of 1 standard deviation error in metres</param>
    /// <param name="TimeStamp_milliseconds">time of measurement</param>
    /// <returns>new state</returns>
    public void Process(double lat_measurement, double lng_measurement, float accuracy, long TimeStamp_milliseconds) {
        if (accuracy < MinAccuracy) accuracy = MinAccuracy;
        if (variance < 0) {
            // if variance < 0, object is unitialised, so initialise with current values
            this.TimeStamp_milliseconds = TimeStamp_milliseconds;
            lat=lat_measurement; lng = lng_measurement; variance = accuracy*accuracy; 
        } else {
            // else apply Kalman filter methodology

            long TimeInc_milliseconds = TimeStamp_milliseconds - this.TimeStamp_milliseconds;
            if (TimeInc_milliseconds > 0) {
                // time has moved on, so the uncertainty in the current position increases
                variance += TimeInc_milliseconds * Q_metres_per_second * Q_metres_per_second / 1000;
                this.TimeStamp_milliseconds = TimeStamp_milliseconds;
                // TO DO: USE VELOCITY INFORMATION HERE TO GET A BETTER ESTIMATE OF CURRENT POSITION
            }

            // Kalman gain matrix K = Covarariance * Inverse(Covariance + MeasurementVariance)
            // NB: because K is dimensionless, it doesn't matter that variance has different units to lat and lng
            float K = variance / (variance + accuracy * accuracy);
            // apply K
            lat += K * (lat_measurement - lat);
            lng += K * (lng_measurement - lng);
            // new Covarariance  matrix is (IdentityMatrix - K) * Covarariance 
            variance = (1 - K) * variance;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Horacio,我知道你为什么这么认为,但不是!在数学上,这里的不确定性是由维纳过程(见http://en.wikipedia.org/wiki/Wiener_process)建模的,并且在维纳过程中,方差随时间线性增长.变量`Q_metres_per_second`对应于维基百科文章"相关过程"部分中的变量`sigma`.`Q_metres_per_second`是标准偏差,以米为单位测量,因此米而不是米/秒是它的单位.它对应于经过1秒后分布的标准偏差. (4认同)
  • 我尝试了这种方法和代码,但它最终缩短了总距离.让它太不精确了. (3认同)
  • @Koray如果您没有准确信息,那么您就不能使用卡尔曼滤波器.这对于卡尔曼滤波器试图做的事情来说是完全基础的. (2认同)
  • 哇,@DanielKanaan,这是对我快 10 年前的一个答案的评论!您当然可以尝试动态 q_meters_per_second,但如果您不小心,可能会导致结果不稳定。此外,在一种情况下效果很好的方法在另一种情况下可能不太好,因此在您感兴趣的所有情况下进行测试很重要。正如我 10 年前所说,比预期更大的 q_meters_per_second 通常效果很好。祝你好运! (2认同)

vil*_*ren 11

这可能有点晚了......

我为Android 编写了这个KalmanLocationManager,它包含了两个最常见的位置提供商,网络和GPS,kalman过滤数据,并向一个LocationListener(像两个'真正的'提供商)提供更新.

我主要用它来读取读数之间的"内插" - 例如每100毫秒接收一次更新(位置预测)(而不是一秒钟的最大gps速率),这使我在动画我的位置时有更好的帧速率.

实际上,它使用三个卡尔曼滤波器,每个维度:纬度,经度和高度.无论如何,他们是独立的.

这使矩阵数学更容易:我使用3个不同的2x2矩阵,而不是使用一个6x6状态转换矩阵.实际上在代码中,我根本不使用矩阵.解决了所有方程式,所有值都是基元(双精度).

源代码正在运行,并且有一个演示活动.对不起在某些地方缺少javadoc,我会赶上来.


Ale*_*ien 8

您不应该每次从位置变化计算速度.GPS可能有不准确的位置,但它具有准确的速度(超过5公里/小时).所以使用GPS位置标记的速度.而且你当然不应该这样做,尽管它大部分时间都有效.

已交付的GPS位置已经过卡尔曼滤波,您可能无法改进,在后期处理中通常您没有像GPS芯片那样的信息.

你可以平滑它,但这也会引入错误.

只需确保在设备静止时移除位置,这将移除跳跃位置,某些设备/配置不会移除.

  • 你能提供一些参考资料吗? (4认同)
  • "已交付的GPS位置已经卡尔曼滤波,您可能无法改进".如果你可以指出一个为现代智能手机确认这一点的来源(例如),那将非常有用.我自己也看不到它的证据.即使对设备的原始位置进行简单的卡尔曼滤波也强烈暗示它不是真的.原始位置不规则地跳舞,而过滤位置通常靠近真实(已知)位置. (4认同)
  • 站立不动时"跳来跳去"不是唯一的错误来源.还有信号反射(例如来自山脉),其中位置跳跃.我的GPS芯片(例如Garmin Dakota 20,SonyEricsson Neo)还没有将其过滤掉...而真正的笑话是GPS信号的高程值与气压不相结合.这些值未被过滤,或者我不希望看到未过滤的值. (2认同)

ojb*_*ass 5

使用较少数学/理论的一种方法是一次采样 2、5、7 或 10 个数据点,并确定哪些是异常值。与卡尔曼滤波器相比,一种不太准确的异常值测量方法是使用以下算法获取点之间的所有成对距离,并丢弃与其他点最远的那个。通常,这些值会替换为最接近您要替换的外围值的值

例如

在五个采样点 A、B、C、D、E 处进行平滑处理

ATOTAL = 距离总和 AB AC AD AE

BTOTAL = 距离总和 AB BC BD BE

CTOTAL = 距离总和 AC BC CD CE

DTOTAL = 距离总和 DA DB DC DE

ETOTAL = 距离总和 EA EB EC DE

如果 BTOTAL 最大,如果 BD = min { AB, BC, BD, BE }

这种平滑确定了异常值,并且可以通过使用 BD 的中点而不是点 D 来增加平滑位置线。您的里程可能会有所不同,并且存在更严格的数学解决方案。


Pet*_*one 5

我通常使用加速度计。在短时间内突然改变位置意味着高加速度。如果加速度计遥测中没有反映出这一点,那几乎可以肯定是由于用于计算位置的“最佳三颗”卫星的变化(我将其称为GPS远距传输)。

当资产处于静止状态并由于GPS传送而跳来跳去时,如果逐步计算质心,则实际上是在与越来越多的壳体相交,从而提高了精度。

为此,当资产处于静止状态时,您必须根据速度,航向以及线性和旋转(如果有陀螺仪)加速度数据估算其可能的下一个位置和方向。这或多或少是著名的K滤波器所做的。您可以在AHRS上以约$ 150的价格在硬件中获得整个东西,其中包含GPS模块以外的所有东西,并带有用于连接一个人的插孔。板载自己的CPU和Kalman过滤器。结果稳定并且相当不错。惯性制导具有很高的抗抖动能力,但会随时间漂移。GPS容易抖动,但不会随时间漂移,实际上是使GPS相互补偿。