Android百度地图(四):百度地图运动轨迹纠偏、去噪、绑路之百度鹰眼 您所在的位置:网站首页 百度地图划线导航怎么弄 Android百度地图(四):百度地图运动轨迹纠偏、去噪、绑路之百度鹰眼

Android百度地图(四):百度地图运动轨迹纠偏、去噪、绑路之百度鹰眼

2024-06-30 00:49| 来源: 网络整理| 查看: 265

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

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

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

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

原始位置轨迹图a

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

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

经处理后的轨迹图

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

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

一 配置工程

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

二 百度鹰眼sdk关键api介绍

1.轨迹数据处理流程图

流程图

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);//设置抽稀,仅在查询历史轨迹时有效,默认需要false processOption.setNeedMapMatch(true);//绑路处理,将点移到路径上,默认不需要false historyTrackRequest.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中的id historyTrackRequest.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);//显示当前位置,并时时动态的画出运动轨迹 } };

动态轨迹效果图

效果图 四 查询被监控者轨迹

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

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

监控者查询数据

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

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

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

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



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有