如何在农机上本地解决 GPS 轨迹冲突?
解读
国内农机作业环境常出现“无网、弱网、断网”三态并存,GPS 模块可能因遮挡、多路径漂移或 RTK 基站切换导致同一地块出现时间戳重叠、坐标跳变、重复上传三类冲突。面试官想考察的是:能否在本地边缘节点(通常是树莓派或安卓平板)用 CouchDB 的离线优先机制完成冲突检测与合并,而不是把矛盾简单抛给云端。核心诉求是“本地闭环、零人工、可回滚”。
知识点
- CouchDB 本地-中心双集群架构:农机平板运行 Nano 版 CouchDB(简称 edge-Couch),地头 relay 节点运行 Micro-Couch,县级数据中心运行 Cluster-Couch,三层之间用** filtered replication** 与自定义冲突函数同步。
- 文档模型设计:一条 GPS 轨迹拆成“航迹头”与“航迹点数组”双文档,头文档存农机 VIN、作业幅宽、RTK 基站 ID,点文档按 1 Hz 切片,
_id用“vin$timestamp$uuid”保证时间有序且唯一。 - 冲突类型与本地检测:
- 时间重叠冲突:同一
_id出现两条 doc,用doc._conflicts数组立即感知; - 空间跳变冲突:edge-Couch 内置 GeoCouch 插件,在
validate_doc_update里计算相邻点速度,若大于 15 m/s 则拒绝写入并生成_local/conflict#speed日志; - 重复上传冲突:利用 Merkle 树哈希(
_attachments/geo.bin的md5字段)比对,md5 相同即视为重复,直接丢弃。
- 时间重叠冲突:同一
- 本地冲突解决函数:在
local.js里注册function(conflictDocs, winner){},策略为“四段优先级”:
① RTK 固定解 > ② RTK 浮点解 > ③ 单点 GPS > ④ 基站外推;
若优先级相同,选时间戳更小的 doc 为 winner, loser 移入_deleted_conflicts并写_local/audit供后续追责。 - 离线回滚机制:edge-Couch 每完成 50 m 作业长度就做一次
POST /_compact并生成只读快照_local/snap${unixtime},若驾驶员发现地块漏喷,可在平板 UI 一键PUT /_rev回退到最近快照,无需网络。 - 与国内规范对齐:农业农村部《农机北斗作业监测技术规范》要求原始轨迹保存 5 年,因此冲突合并后的 loser 文档不物理删除,而是打标签
{"_deleted":true, "archive":"true"},等农机夜间回车库 Wi-Fi 时再增量同步到县级 Cluster-Couch,既满足合规,又节省 4G 流量。
答案
“我会在农机平板本地部署 Nano-CouchDB,首先把 GPS 航迹拆成头、点双文档,_id 带时间戳与 uuid 保证唯一。利用 GeoCouch 在 validate_doc_update 里做速度门限过滤,当场拒绝跳变点;对真正的时间重叠冲突,通过 doc._conflicts 触发本地 JavaScript 函数,按‘RTK 固定解>浮点解>单点GPS>外推’四段优先级自动选主,其余版本打软删除标签并写 _local/audit 日志。每 50 m 作业长度自动生成只读快照,支持驾驶员无网回滚。夜间回车库后,用 filtered-replication 把冲突记录与快照同步到县数据中心,既满足农业部五年留存要求,又把 4G 流量压到最低。整个流程完全本地闭环,无需人工干预。”
拓展思考
- 如果县里要求实时展示农机作业面积,而 edge-Couch 又因 4G 信号塔切换出现双向断网,如何在不丢数的前提下把“冲突已解决”的状态码先推送到驾驶员手机蓝牙,等网络恢复后再补传?
- 当同一地块多台协同农机(插秧机+植保机)同时作业,跨车冲突的
_id命名空间如何设计,才能避免 VIN 不同却坐标重叠导致的误判? - 考虑国产鸿蒙 OS 即将取消安卓后台服务,CouchDB 的 PouchDB-worker 在鸿蒙的 TaskPool 里运行时,如何保障冲突函数依旧能调用到硬件层 RTK 原始观测值?