当我们处理gps设备传过来的数据时,最让人头疼的事情莫过于设备定位异常所传输的异常点了,我们习惯的叫它为飘点。这些数据是设备层面的异常,目前没有什么有效的方法来减少设备发送的飘点。但是我们可以通过程序来过滤掉这些点。
原理
获取时间范围内(默认一天)设备的连续gps信息。遍历这些信息,计算两个相邻点的距离,这个距离要根据实际情况确定若距离大于可容忍距离。则证明该两个相邻点其中有一个点异常根据3的原理,我们将正常的轨迹通过异常点切分为若干个小的轨迹(d1,d2,d3)找出若干个小轨迹分段中最常的一个将其视为合法轨迹(这里如果合法轨迹都是飘点,那使用的设备也没啥使用的意义了)将5找出的合法轨迹的起始点和结束点均作为起点,向整条轨迹的两侧遍历,计算两点之间的距离,若距离大于可容忍距离,则过滤该点。图示
代码
/**
*获得合法轨迹的list起止下标
*计算两点距离的工具类(LocationConvertUtils)自行百度
*实体中用到的信息就是经纬度和时间,我这里时间用的是毫秒的时间戳
*/
private String getSafeIndex(List
int start=0;
int end=0;
List
CarriskAlarmVO dangerBefore = null;
for(int i=1;i CarriskAlarmVO dangerVo = gpsList.get(i); if(dangerBefore == null){ dangerBefore = gpsList.get(i-1); } double disKM = LocationConvertUtils.getGPSDistanceKM(dangerVo.getGpslng(),dangerVo.getGpslat(),dangerBefore.getGpslng(),dangerBefore.getGpslat()); long time = Math.abs(dangerVo.getGpsts()-dangerBefore.getGpsts()); double speed = disKM*1000*3600/time; if(speed>200){ if(end>start){ indexList.add(end+"-"+start); } start=i; } end =i; dangerBefore = dangerVo; } if(end>start){ indexList.add(end+"-"+start); } int maxIndx = 0; int max = 0; for(int i=0;i int tmpEnd = Integer.valueOf(indexList.get(i).split("-")[0]); int tmpStart = Integer.valueOf(indexList.get(i).split("-")[1]); if(tmpEnd-tmpStart>max){ max = tmpEnd-tmpStart; maxIndx = i; } } return indexList.get(maxIndx); } 找出飘点 private void removeErrorPoint( List String safeInxs = getSafeIndex(gpsList); int startIndex = Integer.valueOf(safeInxs.split("-")[1]); int endIndex = Integer.valueOf(safeInxs.split("-")[0]); if(startIndex==0 && endIndex==gpsList.size()-1){ return;//轨迹正常 } List CarriskAlarmVO safeVo = gpsList.get(startIndex); for(int i=startIndex-1;i>-1;i--){ CarriskAlarmVO dangerVo = gpsList.get(i); double disKM = LocationConvertUtils.getGPSDistanceKM(dangerVo.getGpslng(),dangerVo.getGpslat(),safeVo.getGpslng(),safeVo.getGpslat()); long time = Math.abs(dangerVo.getGpsts()-safeVo.getGpsts()); double speed = disKM*1000*3600/time; if(speed>200){ deleteList.add(dangerVo.getId()); }else{ safeVo = dangerVo; } } safeVo = gpsList.get(endIndex); for(int i = endIndex+1;i CarriskAlarmVO dangerVo = gpsList.get(i); double disKM = LocationConvertUtils.getGPSDistanceKM(dangerVo.getGpslng(),dangerVo.getGpslat(),safeVo.getGpslng(),safeVo.getGpslat()); long time = Math.abs(dangerVo.getGpsts()-safeVo.getGpsts()); double speed = disKM*1000*3600/time; if(speed>200){ deleteList.add(dangerVo.getId()); }else{ safeVo = dangerVo; } } if(!deleteList.isEmpty()){ //TODO 对飘点自行处理 } }