安卓GPS坐标散乱问题

7
我有以下代码,看起来运行良好:
    // GPS Reader
    // Criteria
    Criteria criteria = new Criteria();
    //criteria.setAccuracy(Criteria.ACCURACY_COARSE); // Used when we can't get a GPS Fix
    criteria.setAccuracy(Criteria.ACCURACY_FINE); // Used when we can get a GPS Fix

    criteria.setAltitudeRequired(false);
    criteria.setBearingRequired(false);
    criteria.setCostAllowed(true);
    criteria.setPowerRequirement(Criteria.POWER_LOW);

    LocationListener locationListener = new MyLocationListener();
    LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    lm.requestLocationUpdates(lm.getBestProvider(criteria, true), 0, 0,
            locationListener);
然而,当我在Google地图上绘制我收集的数据时,GPS坐标有时非常分散,在我行走的某些路径上一切正常,突然间跳到一英里外的某个点,然后再跳回来。有没有什么方法可以解决这个问题?可能需要进行某种精度检查吗? 更新: Basically my problem looks like this as an example - GPS Jitter
更新2:
我本来不想设立赏金,但我认为最好完全理解这里发生了什么,并看看我的方法是否过度。尽管我有3米的精度,但我的坐标仍然存在抖动问题。现在这可能是由于可用卫星等原因。我不知道,但基本上我试图了解所有这些其他应用程序,特别是运动应用程序,如何在相同情况下获得如此平滑的读数。
我在Quora上找到了这个Does any running app have a feature of filtering GPS data to get more accurate tracking?。不幸的是,它没有对我的问题提供太多见解,除非你想使用卡尔曼滤波器,但肯定有更简单的方法,因为我怀疑大多数应用程序都没有实现这一点。
无论如何,如果有开发人员愿意分享他们正在使用的一些伪代码,那将非常感激。我的意思是,如果我被困在卡尔曼滤波器中,我就会这样做,但我肯定有更容易实现的算法,并希望学习这些算法以及如何实现它们,这些算法是比较合适的。

背景:这是一个移动式的行人应用程序。

相关的SO问题,我试图从中获取信息 如何从一系列GPS坐标创建平滑曲线 平滑gps数据:这是一个很好的开始,但我不确定我需要实现什么伪代码才能使最小二乘法适当地工作,以便我将拥有一个样条GPS数据,然后可以在类似谷歌地图的东西上查看以确认我正确地完成了它。我认为问题在于,如果我处理的是一般的X和Y数据而不是GEO坐标,我可以编写一些Matlab代码进行测试并继续进行。

更新3

收到的混乱GPS数据的图像 https://www.dropbox.com/s/ilsf8snao2no65e/gpsdata2.png

Code https://gist.github.com/4505688


2
你的功率需求和准确性似乎是相互矛盾的。唯一能够提供 ACCURACY_FINE 精度结果的服务提供者是 LocationManager.GPS_PROVIDER。为什么不直接使用它,而要创建像这样的标准:locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, MyLocationListener)? - Nitin Sethi
2
另外,它可能会散布在空旷的天空下/其他原因导致延迟的修复接收。 - Nitin Sethi
好的,我会回到那个设置上 - 因为最初我就是那样设置的,但认为使用标准会更好,明天再试一次。关于开阔天空的问题 - 在运行测试时我处在一个开阔天空的区域,但是当我运行像mapmywalk这样的程序时,却没有出现散射。 - eWizardII
好的,我已经实现了这个功能,然后记录了每个数据点的准确性。所有的结果都小于10米,但我仍然面临着之前的问题——尽管运动步数应用程序也使用GPS,但它们并没有出现这个问题。 - eWizardII
你的位置跳动了多少米?(散布) - AlexWien
大约是5-10米左右。奇怪的是,如果我使用像“位置测试”这样的简单应用程序,我可以清楚地看到它在Google地图上正确更新我的位置,只是不知道为什么在我的特定应用程序中会出现问题。我目前正在使用的代码在这里https://gist.github.com/4505688,当前设置为1000的mintime和0的mindistance。 - eWizardII
4个回答

6
GPS数据本身容易出错。即使您已经正确设置了所有LocationManager(看起来是这样),您也会看到位置时不时会有抖动。
准确度
需要注意的一点是,GPS精度仅为您提供了根据接收到的GPS信号进行计算的估计值。系统误差可能会给您一个很好的精度数字(<10m),但仍然代表较大的位置误差。这就是为什么即使您的准确性非常好,您仍会看到抖动的原因。准确度测量对于消除非常大的误差(>100m)是很好的,但在较低级别上,它只是向您指示计算已收敛的迹象。
过滤
像许多其他东西一样,尽量少做过滤是最好的。准确性过滤器应该能够消除大误差,如果您最终得到一个很好的阈值,则可以获得平滑的数据。
如果您为运行应用程序设置位置更改阈值,还可以获得一些好处。例如,跑步者只能在一定时间内覆盖一定的距离,通过设置上限阈值(Usain Bolt Cutoff),您应该能够删除错误点。问题在于,如果您的第一个点是错误的,则会删除所有其他点。
卡尔曼滤波器
卡尔曼滤波器是一个很好的解决方案,我已经在正在开发的导航应用程序上实现了它。结果非常合理,甚至可以在GPS不好或不可用的情况下进行有限的死推测。不幸的是,我不能分享源代码,但如果您决定采用这种方法,我可以给您一些指导。最好的结果来自6 DoF过滤器,其中您计算加速度和速度,并使用它来估计位置。这不是最简单的解决方案,但我们已经从中看到了良好的结果。
最小二乘法
卡尔曼滤波器非常棒,因为它可以实时用于过滤位置。它跟踪自己的状态,您无需存储旧位置。但另一方面,如果您想要后处理路线,则最小二乘拟合是最佳选择(Kalman是从LSQ公式派生出来的)。我没有做太多后处理,但我怀疑我可以找到一些旧教科书。然而,理论应该是相同的。
大多数GPS设备都非常好,从我所见过的所有测试中,我很少看到您在示例中看到的抖动。但是,一个很大的优点以及我实施卡尔曼滤波器的原因是,您的行驶距离和速度计算更加准确。

问题在于,如果您的第一个点是错误的话,最终您将会删除所有其他点。这是一个经典问题,一直困扰着我。 - Richard Le Mesurier

4
您所获取的是因为您的标准将最佳提供商识别为NETWORK_PROVIDER。这并不确定您的位置,而是给出覆盖设备范围的基站的位置。因此,当您在任何建筑物外时,最好使用GPS_PROVIDER以获得精确的地理位置。您获取分散坐标的原因是因为您的设备进入另一个基站的范围,因此会发生位置跳跃。直接使用GPS_PROVIDER是您可以得到的最佳解决方案。

我应该补充一下,由于Nitin的建议,我已经按照以下方式仅使用GPS进行实现: // GPS Reader LocationListener locationListener = new MyLocationListener(); LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);但问题仍然存在。 - eWizardII
谢谢你的建议,不幸的是由于考试的原因我没有及时关注我的Stack Overflow问题。但基本上我从这个网址上找到了一些提示:https://dev59.com/b-o6XIcBkEYKwwoYSCpJ,另外我也仔细研究了另一个程序的实现方法:https://github.com/marcfasel/LocationMapper。我相信问题出在我使用了其他类来处理位置管理器,我重新实现了他们的方式,去掉了这个类,现在一切似乎都正常工作了。现在需要优化电池寿命。谢谢大家!:) - eWizardII
非常感谢。解释简单明了,解决了我的问题。我一度认为需要使用卡尔曼滤波等方法重新过滤传入的数据,但最终发现只是位置数据提供者选择的问题。太好了! - cedbeu
如果您使用Skobbler,请在调用requestLocationUpdates方法时,将NETWORK_PROVIDER和PASSIVE_PROVIDER禁用,并传入参数(true,false,false)。更多信息请参考SKCurrentPositionProvider文档:https://developer.skobbler.com/docs/android/2.1.0/com/skobbler/ngx/positioner/SKCurrentPositionProvider.html。 - cedbeu

2
一个简单的方法是丢弃任何旧的或不准确的数据,并保持经纬度的运行平均值。
private static final long WILDLY_OUT = 15;
private static final long TOO_OLD = 30000;
private static final long NO_SAMPLES = 5;

double lastLocationTime;

double calclongitude(Location location, double oldLongitude) {
    double newLongitude = oldLongitude;

    if (location.getAccuracy() < WILDLY_OUT) {
        newLongitude = (NO_SAMPLES * oldLongitude + location
                .getLongitude()) / (NO_SAMPLES + 1);
        lastLocationTime = System.currentTimeMillis();
    }

    if (lastLocationTime > TOO_OLD) {
        newLongitude = location.getLongitude();
    }

    return newLongitude;
}

同样的方法也适用于纬度。


2

请查看Reto Meier的这篇文章(包含代码),它会给您提供许多值得思考的信息。您至少应该设置最小距离和时间参数。

lm.requestLocationUpdates(lm.getBestProvider(criteria, true), 5000, 20,
        locationListener);

此外,您可以组合几个提供商,以获得目前最佳的坐标。祝你好运!

我会再次尝试设置条件,看看会得到什么结果。 - eWizardII
我实施了您的建议,但仍然遇到GPS散点问题 - 请参见以下图像 - https://www.dropbox.com/s/ilsf8snao2no65e/gpsdata2.png 蓝色路径是真实路径 - 但红色是GPS记录的路径。 - eWizardII
这些坐标的准确性如何?您能在地图上绘制它吗?如果您愿意,您可以将您的Skype发送给我,我认为我可以帮助您解决这个问题。 - Evos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接