转载、引用请标明出处
http://www.jianshu.com/p/3c3d9e92739d
本文出自zhh_happig的博客,谢谢

Android百度地图(一):百度地图定位sdk 类方法参数、定位原理详细介绍
Android百度地图(二):百度地图sdk显示位置点、图层绘制
Android百度地图(三):百度地图画运动轨迹及图层点击事件处理
Android百度地图(五):百度地图鹰眼sdk监控进出地理围栏(区域)
Android百度地图(六):百度地图POI检索,行政区边界、公交、线路规划查询,地理编码介绍

上一篇文章介绍了地图画轨迹的基本原理和实现。不难发现,当位置处于建筑物密集区、桥梁、高架桥下,gps信号较差时,画出来的轨迹效果会比较差。即使是在空旷地带,也难免会出现gps漂移的情况而造成轨迹的偏差。这时就需要我们对位置点进行纠偏、去噪、抽稀、绑路操作。百度鹰眼sdk则提供了相应的api,本篇文章将介绍如何使用百度鹰眼sdk画出效果相对较好的轨迹。

先来看看效果图
1.百度地图(三)文章中demo取得原始位置点画出来的轨迹图:


Android百度地图(四):百度地图运动轨迹纠偏、去噪、绑路之百度鹰眼_第1张图片 原始位置轨迹图a

可以发现轨迹大致能反应用户所经过的路劲,效果还是不错的,说明gps信号较好,精度较高。但是除了西边的轨迹较为平滑之外,其他方位的轨迹都出现了锯齿形状,原因是gps位置有一定精度差,所以不一定会准确的定位到所行走的路劲上。如果运动范围较大(需缩小地图显示整个轨迹,轨迹将在视觉上变得平滑),而且轨迹精度要求不高,能确定用户在户外,个人觉得图a就能满足要求了

2.使用百度鹰眼sdk处理后的轨迹图:


Android百度地图(四):百度地图运动轨迹纠偏、去噪、绑路之百度鹰眼_第2张图片 经处理后的轨迹图

可以发现经处理的轨迹已经没有锯齿形状了,位置都落到了路劲上,这就是我们想要的效果。如果无法确定用户gps信号的优良,可能会进行网络定位,并且轨迹的精度要求很高,那么位置必须通过百度鹰眼sdk处理后再画出运动轨迹,这样才能达到图b的效果。

下面将介绍如何使用百度鹰眼sdk画出效果相对较好的轨迹,包括驾车、骑行、步行。

一 配置工程

1.申请key
2.创建鹰眼轨迹服务空间并获取 service_id
3.在Application标签中声明SERVICE组件,每个APP拥有自己独立的鹰眼追踪service

二 百度鹰眼sdk关键api介绍

1.轨迹数据处理流程图


Android百度地图(四):百度地图运动轨迹纠偏、去噪、绑路之百度鹰眼_第3张图片 流程图

2.初始化

//以下都是伪代码/***  轨迹服务:通过serviceId对应服务端创建的鹰眼sdk服务,用于存储、访问和管理自己的终端和轨迹。注:个人最多创建10个鹰眼sdk服务。   serviceId:轨迹服务id,这就是配置工程申请的service_id   entityName:服务监控的对象的标识,最好是手机设备唯一标识。一个轨迹服务可监控最多100万个对象。   isNeedObjectStorage:是否需要对象存储服务,比如在某个点存一个图层图片,显示这里有超速摄像头,                        获取轨迹的时候,也可以获取这个图层图片显示在轨迹的相应位置上.                        这里默认为:一般为false,关闭对象存储服务。                        注:鹰眼 Android SDK v3.0以上版本支持随轨迹上传图像等对象数据,                        若需使用此功能,该参数需设为 true,且需导入bos-android-sdk-1.0.2.jar。*/Trace mTrace = new Trace(serviceId, entityName,isNeedObjectStorage);/***  轨迹客户端LBSTraceClient,主要功能:   (1)内部具有定位功能,能采集定位位置点,百度定位sdk不清楚的可以阅读篇头百度文章(一)   (2)将采集数据打包发给服务端   (3)请求服务端,查询经过轨迹、位置、围栏、图像等信息*/LBSTraceClient mClient = new LBSTraceClient(mContext);

3.定位当前位置显示在地图上

//定位请求参数类LocRequest locRequest = new LocRequest(serviceId);//时时定位设备当前位置,定位信息不会存储在轨迹服务端,即不会形成轨迹信息,只用于在MapView显示当前位置mClient.queryRealTimeLoc(locRequest, entityListener);//这里只会一次定位,多次定位使Handler.postDelayed(Runnable, interval)实现;//Entity监听器(用于接收实时定位回调)private OnEntityListener entityListener = new OnEntityListener() {     @Override     public void onReceiveLocation(TraceLocation location) {          //将回调的当前位置location显示在地图MapView上,地图显示位置不清楚的可以篇头阅读百度文章(二)          //这里位置点的返回间隔时间为Handler.postDelayed的延时时间     }   };/*** 当轨迹服务开启,且采集数据开启之后,显示在地图上的位置点可以用服务端纠偏后的最新点,  因为通过mClient.queryRealTimeLoc获取的点可能不精确,出现漂移等情况。*///查询服务端纠偏后的最新轨迹点请求参数类LatestPointRequest request = new LatestPointRequest(getTag(), serviceId, entityName);ProcessOption processOption = new ProcessOption();//纠偏选项processOption.setRadiusThreshold(50);//设置精度过滤,0为不需要;精度大于50米的位置点过滤掉processOption.setTransportMode(TransportMode.walking);processOption.setNeedDenoise(true);//去噪处理processOption.setNeedMapMatch(true);//绑路处理request.setProcessOption(processOption);//设置参数mClient.queryLatestPoint(request, trackListener);//请求纠偏后的最新点//轨迹监听器(用于接收纠偏后实时位置回调)private OnTrackListener trackListener = new OnTrackListener() {     @Override     public void onLatestPointCallback(LatestPointResponse response) {          //将纠偏后实时位置显示在地图MapView上          //这里位置点的返回间隔时间为数据打包上传的频率;数据发送到服务端,才会更新最新的纠偏位置     }};

4.开启服务,开始采集数据

//设置定位模式mClient.setLocationMode(LocationMode.High_Accuracy);/*** 设置采集频率:这里的采集频率指的是轨迹数据的采集频率,和上面显示当前位置的定位频率要区分开  最小为2秒,最大为5分钟,否则设置不成功,默认值为5s* 打包上传频率:mClient每隔packInterval时间会自动打包上传* 打包时间间隔必须为采集时间间隔的整数倍,且最大不能超过5分钟,否则设置不成功,默认为30s*/mClient.setInterval(gatherInterval, packInterval);/*** 开启轨迹服务*/mClient.startTrace(mTrace, traceListener);//开启位置点采集mClient.startGather(traceListener);startTime = System.currentTimeMillis()/1000;//记录开始采集时间//轨迹服务监听器private OnTraceListener traceListener = new OnTraceListener() {    /**    * 绑定com.baidu.trace.LBSTraceService服务回调接口    * @param errorNo  状态码,0:成功,1:失败    * @param message 消息    */    @Override    public void onBindServiceCallback(int errorNo, String message) {    }    /**    * 开启服务回调接口    * @param errorNo 状态码    * 0:成功,10000:请求发送失败,10001:服务开启失败,10002:参数错误,10003:网络连接失败      10004:网络未开启,10005:服务正在开启,10006:服务已开启    * @param message 消息    */    @Override    public void onStartTraceCallback(int errorNo, String message) {    }     /**     * 停止服务回调接口     * @param errorNo 状态码     * 0:成功,11000:请求发送失败,11001:服务停止失败,11002:服务未开启,11003:服务正在停止     * @param message 消息     */     @Override     public void onStopTraceCallback(int errorNo, String message) {     }     /**     * 开启采集回调接口     * @param errorNo 状态码     * 0:成功,12000:请求发送失败,12001:采集开启失败,12002:服务未开启     * @param message 消息                  */     @Override     public void onStartGatherCallback(int errorNo, String message) {     }     /**     * 停止采集回调接口     * @param errorNo 状态码     * 0:成功,13000:请求发送失败,13001:采集停止失败,13002:服务未开启     * @param message 消息                   */     @Override     public void onStopGatherCallback(int errorNo, String message) {     }     /**     * 推送消息回调接口     * @param messageType 状态码     * 0x01:配置下发,0x02:语音消息,0x03:服务端围栏报警消息,0x04:本地围栏报警消息         */     @Override     public void onPushCallback(byte messageType, PushMessage pushMessage) {        //这个回调其实是比较重要的,本篇主要讲的是画轨迹,所以就不详细讲了        /**        * 那么这里能实现什么功能呢,我想到的两个例子        * 1.到达目的地提示用户,在目的地画个圈,进入提醒           实现:CreateFenceRequest创建围栏:圆形围栏、多边形围栏、线型围栏、行政区围栏,一旦进出则推送报警,           pushMessage.getFenceAlarmPushInfo().getMonitoredAction()可以知道进或出,           MonitoredAction.enter:进围栏,MonitoredAction.exit:出围栏        * 2.用户出一定区域发出提醒,在当前位置地画个圈,出去了则提醒        *  比如孩子在小区玩,拿着手机和小伙伴在树底下玩王者农药,我们为了孩子的安全,           只允许他在小区范围内活动,一旦离开了小区的范围就给大人发个短信什么的,哈哈        */     }};  

5.停止服务,停止采集数据

mClient.stopGather(traceListener);endTime = System.currentTimeMillis()/1000;//记录停止采集时间mClient.stopTrace(mTrace, traceListener);

6.请求服务端处理后的位置数据

/** * 历史轨迹请求类 */HistoryTrackRequest historyTrackRequest = new HistoryTrackRequest();ProcessOption processOption = new ProcessOption();//纠偏选项processOption.setRadiusThreshold(50);//精度过滤processOption.setTransportMode(TransportMode.walking);//交通方式,默认为驾车processOption.setNeedDenoise(true);//去噪处理,默认为false,不处理processOption.setNeedVacuate(true);//设置抽稀,仅在查询历史轨迹时有效,默认需要falseprocessOption.setNeedMapMatch(true);//绑路处理,将点移到路径上,默认不需要falsehistoryTrackRequest.setProcessOption(processOption);/*** 设置里程补偿方式,当轨迹中断5分钟以上,会被认为是一段中断轨迹,默认不补充* 比如某些原因造成两点之间的距离过大,相距100米,那么在这两点之间的轨迹如何补偿  SupplementMode.driving:补偿轨迹为两点之间最短驾车路线  SupplementMode.riding:补偿轨迹为两点之间最短骑车路线  SupplementMode.walking:补偿轨迹为两点之间最短步行路线  SupplementMode.straight:补偿轨迹为两点之间直线*/historyTrackRequest.setSupplementMode(SupplementMode.no_supplement);historyTrackRequest.setSortType(SortType.asc);//设置返回结果的排序规则,默认升序排序;升序:集合中index=0代表起始点;降序:结合中index=0代表终点。historyTrackRequest.setCoordTypeOutput(CoordType.bd09ll);//设置返回结果的坐标类型,默认为百度经纬度/***设置是否返回纠偏后轨迹,默认不纠偏 true:打开轨迹纠偏,返回纠偏后轨迹; false:关闭轨迹纠偏,返回原始轨迹。 打开纠偏时,请求时间段内轨迹点数量不能超过2万,否则将返回错误。*/historyTrackRequest.setProcessed(true);//请求历史轨迹((BaseRequest)historyTrackRequest).setTag(tag);//设置请求标识,用于唯一标记本次请求,在响应结果中会返回该标识historyTrackRequest.setServiceId(serviceId);//设置轨迹服务id,Trace中的idhistoryTrackRequest.setEntityName(entityName);//Trace中的entityName/*** 设置startTime和endTime,会请求这段时间内的轨迹数据;* 这里查询采集开始到采集结束之间的轨迹数据*/historyTrackRequest.setStartTime(startTime);historyTrackRequest.setEndTime(endTime);mClient.queryHistoryTrack(historyTrackRequest, mTrackListener);//发起请求,设置回调监听

7.历史轨迹数据回调
注:当我们记录采集的起始时间,然后在查询这段时间内的点,画在地图上,可以实现用户运动结束后,一次性画出整个运动轨迹的功能

//伪代码 private List trackPoints = new ArrayList<>();//轨迹点集合/*** 轨迹监听器(用于接收历史轨迹回调)*/private OnTrackListener mTrackListener = new OnTrackListener() {                 @Override     public void onHistoryTrackCallback(HistoryTrackResponse response) {        //如果觉得轨迹点可能过多,可以多次分页查询,详细代码参见源码        List points = response.getTrackPoints();//获取轨迹点        for (TrackPoint trackPoint : points) {               //将轨迹点转化为地图画图层的LatLng类               trackPoints.add(MapUtil.convertTrace2Map(trackPoint.getLocation()));        }        //MapUtil封装了百度地图MapView和BaidumMap中的一些api        mapUtil.drawHistoryTrack(trackPoints, sortType);//将轨迹点画在地图上,对百度地图画图层不清楚的可以阅读偏头百度地图(三)文章     }};

8.里程计算

DistanceRequest distanceRequest = new DistanceRequest(tag, serviceId, entityName);distanceRequest.setStartTime(startTime);// 设置开始时间distanceRequest.setEndTime(endTime);// 设置结束时间distanceRequest.setProcessed(true);// 纠偏ProcessOption processOption = new ProcessOption();// 创建纠偏选项实例processOption.setNeedDenoise(true);// 去噪processOption.setNeedMapMatch(true);// 绑路processOption.setTransportMode(TransportMode.walking);// 交通方式为步行distanceRequest.setProcessOption(processOption);// 设置纠偏选项distanceRequest.setSupplementMode(SupplementMode.no_supplement);// 里程填充方式为无mTraceClient.queryDistance(distanceRequest, mTrackListener);// 查询里程// 初始化轨迹监听器OnTrackListener mTrackListener = new OnTrackListener() {    // 里程回调    @Override    public void onDistanceCallback(DistanceResponse response) {         double distance = response.getDistance()//里程,单位:米         double speed = distance/(endTime-startTime);//速度:m/s    }};

三 动态时时画运动轨迹

//伪代码/*** 使用LatestPointRequest实现:查询服务端纠偏后的最新的点,在3中已经介绍了* onLatestPointCallback此回调方法不仅可以画出当前的位置点,还可以将每一个最新纠偏后的点加入到位置点集合中,  每返回一个点,就刷新一次轨迹图,这样就能动态画出轨迹了。*///接收纠偏后最新位置回调private OnTrackListener trackListener = new OnTrackListener() {     @Override     public void onLatestPointCallback(LatestPointResponse response) {                   if(first){//返回的第一个点是上一次采集的最后一个点,可能和当前位置距离很大,应该弃用             first = false;             return;         }         //位置点的返回间隔时间为数据打包上传的频率          LatestPoint point = response.getLatestPoint();         LatLng currentLatLng = mapUtil.convertTrace2Map(point.getLocation());         trackPoints.add(currentLatLng);         mapUtil.drawHistoryTrack(trackPoints,false,mCurrentDirection);//显示当前位置,并时时动态的画出运动轨迹     }};

动态轨迹效果图


Android百度地图(四):百度地图运动轨迹纠偏、去噪、绑路之百度鹰眼_第4张图片 效果图

四 查询被监控者轨迹

现实也很简单,被监控者手机开始采集数据

//开启轨迹服务,注意被监控者与监控者中的serviceId必须一致,mTrace的entityname为被监控手机的deviceIdmClient.startTrace(mTrace, traceListener);//开启位置点采集mClient.startGather(traceListener);

监控者查询数据

//查询数据,historyTrackRequest的entityname为被监控手机的deviceIdmClient.queryHistoryTrack(historyTrackRequest, mTrackListener);

好啦,到此,运动轨迹的纠偏、绑路等处理就讲完了,详细实现请参照源码。

如果各位看官觉得文章不错,别忘了点个喜欢。
源码下载地址

以上文章内容,是本人工作中的总结,供大家参考,有误的地方还请指正。

更多相关文章

  1. Android百度地图(一):百度地图定位sdk 类方法参数、定位原理详细
  2. Android Geocoder(位置解析)
  3. Android百度地图导航的那些坑
  4. Android百度地图(六):百度地图POI检索,行政区边界、公交、线路规
  5. Android百度地图SDK—地图标记
  6. Android使用百度地图移动到我的位置
  7. edittext的光标的位置
  8. 2011Android技术面试整理附有详细答案(包括百度、新浪、中科软等
  9. AndroidStudio 2.3.3 百度云盘地址

随机推荐

  1. Android消息处理机制3——MessageQueue
  2. Android(安卓)ant自动打包脚本:自动替换友
  3. android客户端使用网络数据压缩
  4. 进击的Android之异步加载
  5. Android SAX解析xml文件
  6. Flutter工程中的Android风味使用
  7. (转)Android_GPS
  8. Android(安卓)-- Service的开启关闭与生
  9. 【Android】Android实现截取当前屏幕图片
  10. android中sqlite操作