gps - 流畅的 GPS 数据

标签 gps smoothing

我正在处理 GPS 数据,每秒获取值并在 map 上显示当前位置。问题在于,有时(特别是当精度较低时)这些值变化很大,使得当前位置在 map 中的远距离点之间“跳跃”。

我想知道一些足够简单的方法来避免这种情况。作为第一个想法,我考虑以超过特定阈值的精度丢弃值,但我想还有其他一些更好的方法可以做到。程序执行此操作的通常方式是什么?

最佳答案

这是一个简单的卡尔曼滤波器,可以用于这种情况。它来 self 在 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;
        }
    }
}

关于gps - 流畅的 GPS 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1134579/

相关文章:

没有jquery的javascript淡化文本onmouseover

android - 如何找到特定路线上两点之间的距离?

c# - 用C#制作GIS/GPS导航软件需要什么工具

java - SensorEvent.timestamp 和 Location.getElapsedRealtimeNanos() 时间戳延迟偏移

matlab - 如何在 MATLAB 中平滑旋转 3D 图?

css - 如何使 CSS 渐变看起来平滑?

iphone - iPhone GPS 能否为正在运行的应用程序提供准确的速度?

android - 根据地球上当前时间和位置计算太阳光方向

python - 平滑二值图像的边缘

c++ - 平滑一个总是更新的值?