4、RSSI测距实战:RSSI数据采集、滤波处理与距离估算

RSSI测距,说白了就是利用信号强度来猜距离。听起来简单,但实际做起来坑不少。我记得刚入行那会儿,拿着蓝牙模块在实验室里测,数据跳得跟心电图似的,根本没法用。后来才明白,原始RSSI不经过处理,直接拿去算距离,结果基本是废的。

这一章,我们就来把RSSI测距的完整流程走一遍。从数据采集开始,到三种常用滤波方法,再到距离估算和误差分析。每一步我都会把项目里踩过的坑讲清楚。

核心流程: 原始RSSI采集 → 滤波预处理 → 路径损耗模型估算 → 误差分析与校准

RSSI测距实战知识体系 ① 数据采集 多网关同步采样 ② 滤波处理 均值/中值/高斯 ③ 距离估算 路径损耗模型 均值滤波 平滑但易受干扰 中值滤波 抗脉冲干扰强 高斯滤波 保留有效信号 ④ 误差分析与校准 环境衰减因子校准 | 多径效应补偿 | 异常值剔除 实战要点:先采集100个以上样本 → 对比三种滤波效果 → 选择最优方案 室内环境建议使用高斯滤波 + 中值滤波组合

4.1 RSSI数据采集:别急着上手

数据采集看起来最简单,但恰恰是出错最多的地方。我曾经有个项目,部署了6个网关,结果采集回来的数据完全对不上,排查了两天才发现是采样时间窗口没对齐。

采集时要注意几个关键点:

  • 采样频率:建议10-20Hz,太低捕捉不到信号波动,太高数据冗余太大
  • 采样时长:每个位置至少采集3-5秒,保证有足够样本做滤波
  • 多网关同步:所有网关必须在同一时间窗口内采样,否则距离估算会乱套
  • 环境记录:记下当时的温度、湿度、遮挡物情况,这些后面分析误差时用得上

我的习惯:每次采集前先发一个同步广播包,所有网关收到后开始采样。这样能保证时间窗口偏差在10ms以内。

下面是一个简单的数据采集代码示例,我用的是ESP32 + 蓝牙Beacon的方案:

// RSSI数据采集示例(Arduino框架)
#define SAMPLE_COUNT 100
int rssi_samples[SAMPLE_COUNT];

void collect_rssi_samples() {
  for (int i = 0; i < SAMPLE_COUNT; i++) {
    // 扫描并获取最近的Beacon RSSI
    rssi_samples[i] = get_beacon_rssi("BEACON_MAC");
    delay(50);  // 20Hz采样
  }
}

int get_beacon_rssi(String mac) {
  // 实际项目中这里调用蓝牙扫描API
  // 返回RSSI值,单位dBm
  return -65;  // 示例返回值
}

4.2 三种滤波方法:各有各的脾气

原始RSSI数据拿到手,第一件事就是滤波。你想想看,信号在室内反射、绕射、吸收,RSSI值能稳定才怪。我试过不滤波直接算距离,误差能到10米以上,完全没法用。

4.2.1 均值滤波:简单但有效

均值滤波是最基础的方法。把N个样本加起来除以N,就得到一个平均值。优点是计算量小,缺点是对突发干扰很敏感。

// 均值滤波
float mean_filter(int* samples, int len) {
  long sum = 0;
  for (int i = 0; i < len; i++) {
    sum += samples[i];
  }
  return (float)sum / len;
}

适用场景:信号相对稳定的环境,比如空旷的仓库、走廊。

4.2.2 中值滤波:抗干扰能力强

中值滤波的原理很简单:把样本排序,取中间那个值。这样做的好处是,哪怕有几个样本因为干扰跳到了-30dBm或-90dBm,对结果影响也不大。

// 中值滤波
int median_filter(int* samples, int len) {
  // 先排序(这里用简单的冒泡,实际项目用快速排序)
  int temp[len];
  memcpy(temp, samples, len * sizeof(int));
  
  for (int i = 0; i < len - 1; i++) {
    for (int j = 0; j < len - i - 1; j++) {
      if (temp[j] > temp[j + 1]) {
        int t = temp[j];
        temp[j] = temp[j + 1];
        temp[j + 1] = t;
      }
    }
  }
  
  // 取中值
  return temp[len / 2];
}

我曾经踩过的坑:有一次在工厂车间做测试,均值滤波出来的结果完全不对,后来发现是因为叉车经过时产生了强烈的电磁干扰。换成中值滤波后,问题立刻解决了。

4.2.3 高斯滤波:保留有效信号

高斯滤波是我个人比较喜欢的方法。它假设RSSI值服从正态分布,只保留概率较高的样本,剔除那些偏离太远的异常值。

// 高斯滤波
float gaussian_filter(int* samples, int len) {
  // 第一步:计算均值和标准差
  float mean = mean_filter(samples, len);
  float variance = 0;
  
  for (int i = 0; i < len; i++) {
    variance += pow(samples[i] - mean, 2);
  }
  variance /= len;
  float std_dev = sqrt(variance);
  
  // 第二步:只保留均值±1.5σ范围内的样本
  int valid_count = 0;
  float sum_valid = 0;
  
  for (int i = 0; i < len; i++) {
    if (abs(samples[i] - mean) <= 1.5 * std_dev) {
      sum_valid += samples[i];
      valid_count++;
    }
  }
  
  return (valid_count > 0) ? (sum_valid / valid_count) : mean;
}

为什么用1.5σ? 我做过大量实测,1.5倍标准差能保留约87%的有效样本,同时剔除掉那些明显异常的跳变点。这个参数可以根据实际环境微调。

4.3 三种滤波效果对比

为了让你更直观地看到区别,我拿一组实际采集的数据做了对比。这是在办公室环境下,距离网关5米处采集的100个样本。

滤波方法 输出值(dBm) 标准差(dBm) 计算耗时(ms) 抗干扰能力
原始数据 -68.3 4.7 - 无
均值滤波 -68.3 2.1 0.02 弱
中值滤波 -67.0 1.8 0.15 强
高斯滤波 -68.8 1.2 0.35 较强

从表中能看出来:高斯滤波的标准差最小,说明稳定性最好。但计算耗时也最长。实际项目中怎么选?我的建议是:

  • 资源受限的嵌入式设备:用中值滤波,效果好且计算量适中
  • 服务器端处理:用高斯滤波,精度优先
  • 快速原型验证:用均值滤波,简单直接

4.4 距离估算:从RSSI到米

滤波完的RSSI值,怎么换算成距离?这里要用到路径损耗模型。最常用的是对数距离路径损耗模型:

// 距离估算函数
float rssi_to_distance(float rssi, float tx_power, float n) {
  // tx_power: 1米处的参考RSSI值(通常-59dBm)
  // n: 环境衰减因子(自由空间2.0,室内2.5-4.0)
  // 公式: distance = 10^((tx_power - rssi) / (10 * n))
  return pow(10, (tx_power - rssi) / (10.0 * n));
}

// 使用示例
float filtered_rssi = gaussian_filter(samples, 100);
float distance = rssi_to_distance(filtered_rssi, -59, 3.0);
printf("估算距离: %.2f 米\n", distance);

这里有两个关键参数需要校准:

  • tx_power:1米处的参考RSSI。这个值每个设备都不一样,必须实测。我习惯在1米处采集200个样本取均值作为tx_power。
  • n(环境衰减因子):这个值决定了信号随距离衰减的速度。自由空间是2.0,普通办公室大概2.5-3.0,有隔断的仓库可能到3.5-4.0。

避坑指南:千万不要直接用芯片手册上写的tx_power。我遇到过好几次,手册写-59dBm,实际测出来是-63dBm,差4个dBm,算出来的距离能差30%。

4.5 误差分析:为什么测不准?

RSSI测距的误差来源很多,我总结了几类:

误差类型 典型误差范围 主要原因 缓解方法
多径效应 2-8米 信号反射叠加 多网关协同、天线分集
阴影衰落 1-5米 障碍物遮挡 动态环境建模
设备差异 1-3米 天线增益不同 逐个设备校准
温度漂移 0.5-2米 射频器件温漂 温度补偿

我记得有一次在停车场做测试,估算距离一直在3-8米之间跳,怎么都稳定不下来。后来发现是旁边有根金属柱子,信号反射特别严重。换了位置之后,误差立刻降到了1米以内。

所以,做RSSI测距一定要有心理准备:绝对精度很难做到1米以下。但在多网关协同定位中,我们通过多个网关的数据融合,可以大幅提升定位精度。这个后面几章会详细讲。

4.6 本章小结

这一章我们把RSSI测距的完整流程走了一遍。从数据采集的注意事项,到三种滤波方法的原理和代码实现,再到距离估算和误差分析。核心就一句话:原始RSSI不可信,滤波是必须的,参数校准是关键。