2. 系统架构设计:融合定位系统的骨架

做融合定位系统,最怕什么?我个人的经验是,最怕一开始就把架构想简单了。很多人觉得,不就是把LTE的定位数据和UWB的定位数据加在一起算个平均值吗?嗯,如果你真这么干,那项目大概率会踩坑。

这一章,我们就来聊聊融合定位系统的总体架构。我会把LTE定位子系统和UWB定位子系统的接口设计讲清楚,最后再深入数据融合引擎的架构。说白了,这就是整个系统的骨架,骨架搭好了,后面的血肉才能长上去。

核心观点:融合定位不是简单的数据叠加,而是通过架构设计,让两种技术互补短板。LTE负责广域覆盖和连续定位,UWB负责高精度局部修正。两者通过标准化的接口和数据融合引擎,形成一个有机整体。

2.1 总体架构:三层两接口

先看一张图,这是我个人习惯用的架构分层方式。我把整个系统分成三层:感知层、融合层和应用层。层与层之间,通过两个标准接口连接。

融合定位系统总体架构(三层两接口) 应用层 资产管理 | 人员定位 | 导航服务 | 安全预警 北向接口(RESTful API) 数据融合引擎(融合层) 卡尔曼滤波 | 粒子滤波 | 加权最小二乘 时间同步 | 空间对齐 | 异常检测 缓存管理 | 数据清洗 | 置信度评估 南向接口(MQTT / gRPC) LTE定位子系统 OTDOA / ECID / 指纹 UWB定位子系统 TDOA / TOF / PDOA 说明:感知层负责原始数据采集,融合层负责算法处理,应用层负责业务呈现。 南向接口屏蔽了底层硬件差异,北向接口屏蔽了融合算法复杂度。

这张图我建议你多看两眼。为什么这么分?我解释一下:

  • 感知层:包含LTE定位子系统和UWB定位子系统。它们各自独立工作,输出原始的定位数据。LTE这边,我常用的是OTDOA(观测到达时间差)和ECID(增强小区ID);UWB那边,TDOA和TOF是主流。
  • 融合层:这是核心。数据融合引擎在这里运行,它接收来自感知层的多源数据,做时间同步、空间对齐、异常检测,然后用卡尔曼滤波或粒子滤波算出最终位置。
  • 应用层:面向业务。资产管理、人员定位、导航服务、安全预警……这些是客户真正关心的东西。

我的经验:南向接口一定要设计成可插拔的。我在一个项目中,客户临时要求换成另一家UWB厂商的设备。因为南向接口是标准化的MQTT协议,我只改了设备驱动层的配置,融合引擎一行代码没动。如果你把接口写死了,换设备就得重写融合逻辑,那代价就大了。

2.2 LTE定位子系统接口设计

LTE定位子系统,说白了就是利用现有的LTE基站网络来做定位。它的接口设计,核心是LPP(LTE Positioning Protocol)协议。

我记得刚开始做这个的时候,被LPP的协议栈搞得头大。后来我总结了一个规律:你只需要关注三个关键接口。

接口名称 协议 传输内容 典型延迟
LTE基站 → 定位服务器 LPPa 小区ID、RSRP、RSRQ、TA < 100ms
终端 → 定位服务器 LPP OTDOA测量值、RSTD < 200ms
定位服务器 → 融合引擎 gRPC 经纬度、置信度、时间戳 < 50ms

这里有个坑,我必须要提醒你。LTE定位的原始数据,比如RSRP(参考信号接收功率)和TA(时间提前量),它们的更新频率是不一样的。RSRP可能每100ms来一次,TA可能500ms才更新一次。如果你不做时间对齐,融合出来的位置会抖动得很厉害。

避坑指南:我曾经在一个项目中,直接拿LTE的原始RSRP数据去算位置,结果发现定位结果忽远忽近。后来排查发现,是因为RSRP的测量周期和TA的测量周期没有对齐。解决方案是:在LTE定位子系统内部做一个缓存队列,把不同周期的数据统一插值到同一个时间轴上,再输出给融合引擎。

2.3 UWB定位子系统接口设计

UWB这边,情况比LTE要简单一些,但精度要求更高。UWB定位子系统的接口设计,核心是数据帧格式的统一。

我见过很多UWB厂商,每家都有自己的数据格式。有的用二进制,有的用JSON,有的甚至用自定义的文本协议。所以,南向接口的第一个任务,就是做协议转换。

下面是我在一个项目中用过的UWB数据帧格式,你可以参考:

{
  "device_id": "UWB_ANCHOR_03",
  "timestamp": 1712345678.123,
  "measurements": [
    {
      "tag_id": "TAG_A001",
      "range_m": 12.34,
      "rssi_dbm": -65.2,
      "method": "TDOA"
    },
    {
      "tag_id": "TAG_A001",
      "range_m": 8.76,
      "rssi_dbm": -70.1,
      "method": "TOF"
    }
  ],
  "confidence": 0.95
}

为什么我要强调confidence这个字段?因为UWB在非视距(NLOS)环境下,测距误差会急剧增大。如果没有置信度字段,融合引擎会把错误数据当成有效数据,结果就是定位漂移。

关键设计原则:UWB定位子系统输出的每一帧数据,都必须包含时间戳、测距值、置信度三个核心字段。缺少任何一个,融合引擎都无法正常工作。

2.4 数据融合引擎架构

好了,前面两个子系统把数据送过来了。现在轮到数据融合引擎登场。这是整个系统的大脑,也是最复杂的一块。

数据融合引擎的架构,我把它分成四个模块:

  1. 数据预处理模块:负责时间同步、空间坐标对齐、异常值剔除。
  2. 状态估计模块:核心算法模块,运行卡尔曼滤波或粒子滤波。
  3. 置信度评估模块:根据当前环境、信号质量、历史轨迹,动态评估定位结果的可靠性。
  4. 输出管理模块:将融合后的位置数据格式化成标准接口,推送给应用层。

你想想看,如果LTE说你在A点,UWB说你在B点,你信谁?这就是置信度评估模块要解决的问题。我个人的做法是,给每个数据源一个动态权重。比如,在室内开阔环境,UWB的权重设为0.8,LTE的权重设为0.2;到了室外或者UWB信号遮挡严重的地方,就把权重反过来。

下面是一个简化的卡尔曼滤波融合流程,我用伪代码表示:

// 数据融合引擎核心流程(简化版)
// 输入:LTE位置 (x_lte, y_lte, conf_lte)
//        UWB位置 (x_uwb, y_uwb, conf_uwb)
// 输出:融合位置 (x_fused, y_fused)

// 1. 时间对齐
if (abs(t_lte - t_uwb) > MAX_TIME_DIFF) {
    // 丢弃过时数据,使用预测值
    (x_lte, y_lte) = predict_last_position(dt);
}

// 2. 空间对齐(坐标转换)
(x_lte_m, y_lte_m) = lla_to_enu(x_lte, y_lte, origin);

// 3. 异常检测
if (abs(x_lte_m - x_uwb) > MAX_DISTANCE) {
    // 可能有一个数据源出错了
    // 根据置信度决定信任哪个
    if (conf_uwb > conf_lte) {
        // 信任UWB
        (x_fused, y_fused) = (x_uwb, y_uwb);
    } else {
        // 信任LTE
        (x_fused, y_fused) = (x_lte_m, y_lte_m);
    }
    return;
}

// 4. 卡尔曼滤波融合
// 计算融合权重
weight_lte = conf_lte / (conf_lte + conf_uwb);
weight_uwb = conf_uwb / (conf_lte + conf_uwb);

// 加权融合
x_fused = weight_lte * x_lte_m + weight_uwb * x_uwb;
y_fused = weight_lte * y_lte_m + weight_uwb * y_uwb;

// 5. 更新卡尔曼滤波器状态
kf.predict();
kf.update([x_fused, y_fused]);

我的经验:卡尔曼滤波的初始参数设置很关键。我刚开始做的时候,直接把过程噪声和测量噪声设成固定值,结果在动态场景下定位延迟很大。后来我改成自适应噪声模型——根据当前运动速度和信号质量动态调整噪声协方差矩阵,效果好了很多。

2.5 接口设计的几个关键决策

最后,我想聊聊接口设计时几个容易纠结的点。这些是我在实际项目中踩过的坑,分享给你:

决策点 选项A 选项B 我的建议
南向接口协议 MQTT gRPC 如果设备端资源受限(比如低功耗标签),选MQTT;如果对实时性要求极高(<10ms),选gRPC
数据格式 JSON Protobuf 原型验证阶段用JSON,方便调试;生产环境用Protobuf,减少带宽和解析开销
时间同步方式 NTP PTP(IEEE 1588) LTE基站一般支持NTP,精度够用;UWB基站建议用PTP,亚微秒级同步
融合引擎部署位置 边缘节点 云端 对延迟敏感的场景(如AGV导航),放边缘;对历史数据分析需求强的,放云端