由于移动设备特别像android开发的流行。其中一个特定方向或者领域就是gps位置服务相关的开发。以arcgis android环境为例
研究一下gps采集点的精度问题, 对于民用类的gps,像手机,平板等设备。
我们可以测试,如果调用手机的gps功能,获取Location对象。同一个位置取到的点,并不相同。
精度可能在2米 5米 10米等范围浮动,但是对于这些设备,我们很难提高它的精度怎么办呢。
软件人员常用的办法就是一个时间段内的平均值统计。最简单的代码如下:
import com.esri.core.geometry.Point;
public class GpsUtil {
public static Point getAvg(List<Point> listPoints) {
int count = 0;
double xAll = 0d, yAll = 0d;
for (Point p : listPoints) {
double x = p.getX();
double y = p.getY();
xAll = xAll + x;
yAll = yAll + y;
count = count + 1;
}
double xAvg = xAll / count;
double yAvg = yAll / count;
return new Point(xAvg, yAvg);
}
}
但是上面算法太简单, 如果gps采集的点出现了奇异点怎么办呢,比如采集了10个点比较好,误差不过2、3米。忽然有个点出现了10米(也有可能偏00米都有)以上的误差,那取到的
平均值也就不准了。 为了去除奇异点,我们设计一个算法,找出偏离平均值最大的移除。 对于左边来说,可以认为有两个点是可能的奇异点
就是最大点 和最小点是奇异点。 如果移除这两个可能的点,再计算均值,gps偏移可以得到一定的纠正。
当然如果站在高楼大厦下等地点,由于卫星信号受影响,可能永远偏100多米,纠正也没有意义.
移除 最高最低分的代码如下:
public static Point getAvg(List<Point> listPoints) {
int count = 0;
double xAll = 0d, yAll = 0d;
for (int i = 0; i < listPoints.size(); i++) {
double x = p.getX();
double y = p.getY();
xAll = xAll + x;
yAll = yAll + y;
count = count + 1;
if (x > maxX) {
maxX = x;
maxIdx = i;
}
if (y > maxY) {
maxY = y;
mayIdx = i;
}
if (x < mixX) {
mixX = x;
mixIdx = i;
}
if (y < mixY) {
mixY = y;
miyIdx = i;
}
}
double xAvg = xAll / count;
double yAvg = yAll / count;
double maxX = xAvg;
double maxY = yAvg;
double mixX = xAvg;
double mixY = yAvg;
int maxIdx = -1, mayIdx = -1;
int mixIdx = -1, miyIdx = -1;
int maxNeedIdx=-1,minNeedIdx=-1;
if(Math.abs(xAvg-maxX)> Math.abs(yAvg-maxY)){
maxNeedIdx=maxIdx;
}else{
maxNeedIdx=mayIdx;
}
if(Math.abs(xAvg-mixX)> Math.abs(yAvg-mixY)){
minNeedIdx=mixIdx;
}else{
minNeedIdx=miyIdx;
}
if (maxNeedIdx > minNeedIdx) {
if(maxNeedIdx>=0)
listPoints.remove(maxNeedIdx);
if(minNeedIdx>=0)
listPoints.remove(minNeedIdx);
} else if (maxNeedIdx == minNeedIdx) {
if(maxNeedIdx>=0)
listPoints.remove(maxNeedIdx);
} else {
if(minNeedIdx>=0)
listPoints.remove(minNeedIdx);
if(maxNeedIdx>=0)
listPoints.remove(maxNeedIdx);
}
return getAvg0(listPoints);
}