如何在农机上本地解决 GPS 轨迹冲突?

解读

国内农机作业环境常出现“无网、弱网、断网”三态并存,GPS 模块可能因遮挡、多路径漂移或 RTK 基站切换导致同一地块出现时间戳重叠、坐标跳变、重复上传三类冲突。面试官想考察的是:能否在本地边缘节点(通常是树莓派或安卓平板)用 CouchDB 的离线优先机制完成冲突检测与合并,而不是把矛盾简单抛给云端。核心诉求是“本地闭环、零人工、可回滚”。

知识点

  1. CouchDB 本地-中心双集群架构:农机平板运行 Nano 版 CouchDB(简称 edge-Couch),地头 relay 节点运行 Micro-Couch,县级数据中心运行 Cluster-Couch,三层之间用** filtered replication** 与自定义冲突函数同步。
  2. 文档模型设计:一条 GPS 轨迹拆成“航迹头”与“航迹点数组”双文档,头文档存农机 VIN、作业幅宽、RTK 基站 ID,点文档按 1 Hz 切片,_id 用“vin$timestamp$uuid”保证时间有序且唯一
  3. 冲突类型与本地检测
    • 时间重叠冲突:同一 _id 出现两条 doc,用doc._conflicts 数组立即感知;
    • 空间跳变冲突:edge-Couch 内置 GeoCouch 插件,在 validate_doc_update 里计算相邻点速度,若大于 15 m/s 则拒绝写入并生成 _local/conflict#speed 日志;
    • 重复上传冲突:利用 Merkle 树哈希_attachments/geo.binmd5 字段)比对,md5 相同即视为重复,直接丢弃。
  4. 本地冲突解决函数:在 local.js 里注册 function(conflictDocs, winner){},策略为“四段优先级”:
    ① RTK 固定解 > ② RTK 浮点解 > ③ 单点 GPS > ④ 基站外推;
    若优先级相同,选时间戳更小的 doc 为 winner, loser 移入 _deleted_conflicts 并写 _local/audit 供后续追责。
  5. 离线回滚机制:edge-Couch 每完成 50 m 作业长度就做一次 POST /_compact 并生成只读快照 _local/snap${unixtime},若驾驶员发现地块漏喷,可在平板 UI 一键 PUT /_rev 回退到最近快照,无需网络。
  6. 与国内规范对齐:农业农村部《农机北斗作业监测技术规范》要求原始轨迹保存 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 流量压到最低。整个流程完全本地闭环,无需人工干预。”

拓展思考

  1. 如果县里要求实时展示农机作业面积,而 edge-Couch 又因 4G 信号塔切换出现双向断网,如何在不丢数的前提下把“冲突已解决”的状态码先推送到驾驶员手机蓝牙,等网络恢复后再补传?
  2. 当同一地块多台协同农机(插秧机+植保机)同时作业,跨车冲突_id 命名空间如何设计,才能避免 VIN 不同却坐标重叠导致的误判?
  3. 考虑国产鸿蒙 OS 即将取消安卓后台服务,CouchDB 的 PouchDB-worker 在鸿蒙的 TaskPool 里运行时,如何保障冲突函数依旧能调用到硬件层 RTK 原始观测值?