记一次迭代过程中实时位置显示详细测试过程

项目背景:现项目主要是做关于机器人的调度系统,涉及到web端、移动端、小程序及服务端和实体机器人端;

迭代背景:采用的敏捷开发,迭代周期为两周,本次迭代的US为机器人在地图上位置显示及路径显示,主要涉及到地图、设备状态、设备位置、电梯等状态信息展示;

记录方向:只记录测试执行过程中比较特殊的实现点的详细测试过程;

记录时间:20200104,测试阻塞,反补测试功能点及测试用例后;

 

备注:反补测试功能点及测试用例的时机:a、功能点评审后修改测试功能点;b、在测试执行过程中发现遗漏点及细节性问题,防止测试遗留,需要反补测试功能点及用例;

记录点:

1、设备状态信息判断,该状态是需要实时变化的,最开始编写功能点的时候没有考虑到该功能点,可以有在线变为离线,离线变为在线状态,在测试过程中才发现该细节,然后就是反补测试功能点和测试用例;

1.1、该状态判断的逻辑整理如下:a、进入页面或者刷新请求http接口,根据接口文档的返回显示状态;b、然后一直停留在该界面上,通过websocket连接订阅mqtt消息:主要有三个topic,设备状态、设备位置及电梯;根据订阅到的设备状态topic进行判断,如果10s内没有订阅到该topic,就判断为离线;

1.2、服务端与机器人的通讯机制也是通过mqtt进行通讯的,机器人发布topic的机制为:1s推送一次、有变化才推送,无变化则不推送相关信息;

2、机器人路径描点

1.1、获取机器人位置信息的通讯协议是mqtt;机器人发布topic A,服务端订阅topic A;服务端订阅到消息后通过topic B发布消息,前段通过topic B订阅消息;这是机器人位置信息从机器人到web端显示这个过程的链路;

1.2、订阅到的位置信息格式:位置信息分为:position位置信息和orientation 四元数信息;四元数信息主要表示的空间坐标信息,可以查看四元数的百科:四元数

{"data":{"mapId":"333a22c1-a6b6-4e0a-86a6-18e97fa6cd30","orientationW":-0.4185264650360043,"orientationX":0.0,"orientationY":0.0,"orientationZ":0.9082046014332145,"packTimestamp":0,"positionX":124.27075596298803,"positionY":158.59433354135734,"positionZ":0.0},"deviceId":"00000000000000000013","sequence":2021010430896588,"timestamp":1609756929202}

1.3、要将接收到的位置信息显示在web端,web端描出的点位数据有问题,显示的位置信息有问题,查询的结果是没有对接收到的位置信息做坐标转换;

因为项目组没有对应研究数学的人,在进行坐标转换遇到很大的问题,最后采用了最笨的临时方案,根据实际的位置数据与接收的位置数据进行换算,得出换算关系,然后将转换关系“写死”:

/**
     * @param x0 旋转中心点X坐标
     * @param y0 旋转中心点y坐标
     * @param x1 起始点x坐标
     * @param y1 起始点y坐标
     * @param degree 旋转角度,因为视图坐标系是以左上角为原点,传输时传入顺时针的负值
     */
    fun rotate(x0: Float, y0: Float, x1: Float, y1: Float, degree: Double):FloatArray {

        val k = Math.toRadians(degree)
        val x2 = ((x1 - x0) * Math.cos(k) + (y1 - y0) * Math.sin(k) + x0).toFloat()
        val y2 = (-(x1 - x0) * Math.sin(k) + (y1 - y0) * Math.cos(k) + y0).toFloat()
        return floatArrayOf(x2,y2)

    }

备注:在确定坐标转换方案的时候,讨论过84坐标系,但该转换关系太过于复杂,缺乏相应的人员有能力来做这项工作,且该工作量巨大,最终舍弃到该方案;

3、历史路径持久化

因为该US需要需要显示当天的历史数据,服务端需要将订阅到的位置信息持久化到数据库。在开发实现写过具体的历史数据持久化的方案。大致口述一下,不进行详细展开,下一篇博文在详细描述出来,主要是自己看了很多次还是

没有看懂;

3.1、持久化框架:redis及mongodb,在项目中使用redis做的缓存,mongodb来做具体的持久化;

3.2、持久化方案:

a、每台机器人数据先按照上报数据中的时间戳取分钟级在redis中进行缓存,redis存储Key格式:device:${device_id}:status:${时间戳,精度到分} ,redis缓存使用HashMap进行存储,hashMap的key为当前接受到的数据的序列号;

b、数据补全,由于机器人可能仅上报变化的数据,为了保持每条报文的完整性,后端在接收到机器人上报的报文后先根据redis中之前数据的缓存对新收到的数据进行补全;

3.3、持久策略

a、定时持久化

使用xxl-job提供分布式定时任务,每分钟将该分钟前的记录持计划到数据库中。持久化时使用redis的scan按照通配符获取所有机器需要持计划的数据,之后批量插入mongodb。

b、被动持久化

除了定时持久化外,在设备离线1分钟后触发主动持久化操作。延时1分钟可以避免设备因为异常情况出现频繁重启上下线带来的数据持久化风险。延时触发操作可以使用RabbitMQ的延时队列实现。

每次后端接收到数据之后触发持久化检查,如果需要持久化就主动进行持久化操作;

c、缓存清理

因为数据暂存于redis缓存中,为了避免缓存异常,需要提供如下相关实现:

每个缓存key创建时默认设定30分钟的超时时间(时间可配置),在每次向缓存中插入数据时主动重置缓存的有效期;

在每次数据进行持久化后立刻删除缓存key,删除操作使用redis的scan配合通配符方式进行删除;

4、设备信息弹窗显示,因为设备一直在移动中,点击设备图标信息要显示设备信息详细弹窗,详细弹窗也要跟着机器人进行移动;

因为该US大部分工作都属于前端,该问题也困扰了很久,没法做到设备详情弹窗根据机器人图标一起移动,最后做的逻辑是点击设备图标显示设备信息弹窗,2秒后设备信息弹窗消失;

5、当天历史路径数据查询策略

当设备一直在作业的时候,历史路径数据量非常庞大,怎么查询才能控制资源占用;

项目组做了两点改进方案:

a、数据压缩:如果按天纬度查询时时间越长数据数据较大,相近时间的坐标点可能差异不大,此时可以对数据进行相似剔除压缩以减少数据量。数据压缩算法可以评估参考使用JTS java库中提供的道格拉斯-普克算法算法;

b、后端对历史路径进行分包,最开始的做法为一个包,数据量庞大,前段渲染有压力,后面有进行数据分包;

6、地图放大系统资源占用庞大,浏览器经常出现假死现象,需要过很久才能响应过来

因为地图上要显示机器人当天的路径信息数据量比较大,而且还在不停地通过mqtt订阅信息新的位置信息,地图进行缩放的时候对所有的位置数据进行重新描点。

在优化过程中做了一下动作:a、前段把数据分为两部分:历史数据和实时数据,是做了保存的,分为两个变量,只有实时数据在变化,历史数据固定不变;b、前段对数据的有效性筛选,只保留了实际会用到的数据;

c、服务端对数据进行了压缩,就是上一个特殊点中提到的数据压缩;

7、该界面是需要展示的,是需要长时间停留在该界面上,因为页面有订阅mqtt消息,时间过久导致系统资源占用非常庞大,出现假死现象;

a、前段对数据做了筛选,具体的策略是什么,当时问了也没有弄懂怎么个优化机制,但还是的记录一下,至少得留个脚印,等以后再来查看的时候发现“哦,原来遇到过这个问题!”

posted @ 2021-01-04 19:38  小菜鸡1枚  阅读(127)  评论(0编辑  收藏  举报