11、Wi-Fi RTT(定位):RTT 测距原理、WifiRttManager、应用场景
各位同学,今天我们来聊一个挺有意思的话题——Wi-Fi RTT。
说白了,就是让手机通过 Wi-Fi 信号,测量出它跟某个热点之间的距离。你可能会问:这跟 GPS 有什么区别?嗯,区别大了。GPS 在室内基本是废的,而 Wi-Fi RTT 恰恰擅长室内定位。我在做智能家居项目时,就靠它实现了米级精度的室内导航,效果比蓝牙 Beacon 稳定得多。
11.1 RTT 测距原理
RTT 的全称是 Round Trip Time,往返时间。原理其实很简单:
- 手机发一个 Wi-Fi 帧给 AP(接入点)
- AP 收到后立刻回复一个确认帧
- 手机记录从发出到收到回复的时间差 ΔT
- 距离 = (ΔT × 光速) / 2
为什么除以 2?因为信号走了一个来回。这个时间差非常短,通常在纳秒级别。我记得第一次看日志时,看到几十纳秒的数值,还以为是 bug,后来才反应过来——光速太快了,30 纳秒对应大约 4.5 米,完全合理。
关键点:RTT 测距依赖的是精确的时间戳,而不是信号强度(RSSI)。RSSI 受环境干扰太大,你转个身信号就能掉 10 dBm,但 RTT 的时间测量相对稳定得多。
Android 从 9.0(API 28)开始支持 RTT,底层用的是 IEEE 802.11mc 标准,也叫 Wi-Fi 精细时间测量(FTM)。如果你的 AP 不支持 802.11mc,那 RTT 就用不了。我在项目中踩过这个坑——买了一批廉价路由器,结果全都不支持,最后只能换硬件。
11.2 WifiRttManager 使用详解
Android 提供了 WifiRttManager 这个系统服务来管理 RTT 测距。使用流程大致分三步:
- 获取服务实例
- 构建测距请求
- 发起测距并处理回调
先看获取服务的代码:
WifiRttManager wifiRttManager =
(WifiRttManager) context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
if (wifiRttManager == null) {
// 设备不支持 RTT
return;
}
嗯,这里要注意:不是所有 Android 设备都支持 RTT。你需要先检查 PackageManager.FEATURE_WIFI_RTT 特性:
if (!context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WIFI_RTT)) {
// 不支持 RTT,提示用户
return;
}
接下来构建测距请求。你需要指定目标 AP 的 ScanResult:
List<RangingRequest> requests = new ArrayList<>();
RangingRequest request = new RangingRequest.Builder()
.addAccessPoint(scanResult)
.build();
requests.add(request);
然后发起测距:
wifiRttManager.startRanging(requests,
Executors.newSingleThreadExecutor(),
new RangingResultCallback() {
@Override
public void onRangingResults(List<RangingResult> results) {
for (RangingResult result : results) {
int status = result.getStatus();
if (status == RangingResult.STATUS_SUCCESS) {
int distanceMm = result.getDistanceMm();
int stdDevMm = result.getDistanceStdDevMm();
// distanceMm 单位是毫米
}
}
}
@Override
public void onRangingFailure(int code) {
// 测距失败,code 表示失败原因
}
});
个人经验:回调中的 getDistanceStdDevMm() 非常有用。如果标准差大于 500 毫米,说明这次测距结果不可靠,建议丢弃或重测。我在商场导航项目中,就是靠这个过滤掉了 30% 的噪声数据。
11.3 应用场景
RTT 能做什么?我总结了几类典型场景:
| 场景 | 说明 | 精度要求 |
|---|---|---|
| 室内导航 | 商场、机场、医院内找店铺或登机口 | 1~3 米 |
| 资产追踪 | 仓库内定位货架或设备 | 0.5~1 米 |
| 紧急救援 | 消防员在浓烟中定位队友 | 1 米以内 |
| 智能家居 | 根据用户位置自动开关灯或空调 | 2~5 米 |
你想想看,室内导航这个场景,以前只能用蓝牙 Beacon 做粗略定位,误差经常超过 5 米。换成 RTT 后,配合三个以上的 AP 做三角定位,精度能稳定在 1~2 米。我曾经在一个 5000 平米的展厅做过测试,用户拿着手机走,定位点基本跟实际位置重合,体验非常好。
避坑指南:RTT 测距受多径效应影响较大。如果 AP 放在墙角或金属柜子旁边,信号反射会导致测距偏大。我曾经在机房测试,结果测出来的距离比实际远了 3 米,排查了半天才发现是 AP 旁边有个铁皮机柜。解决办法是:部署 AP 时尽量避开金属障碍物,或者用多个 AP 做数据融合。
11.4 核心知识体系
下面这张图总结了 RTT 定位的核心逻辑,从底层原理到上层应用一目了然:
从图中你可以看到,RTT 定位的根基是 802.11mc 物理层标准,Android 通过 WifiRttManager 封装了底层细节,开发者只需要关注业务逻辑。我个人觉得,这套架构设计得相当优雅——底层复杂,上层简单。
11.5 实战建议
最后给几个实战中的小建议:
- 多 AP 部署:单 AP 只能测距,不能定位。至少需要 3 个 AP 才能做三角定位。我在项目中用了 4 个,冗余一个防止故障。
- 数据滤波:RTT 原始数据有抖动,建议用卡尔曼滤波或滑动平均。我习惯用滑动窗口取中位数,效果不错。
- 权限声明:别忘了在 Manifest 中添加
ACCESS_FINE_LOCATION和ACCESS_WIFI_STATE权限,否则测距会直接失败。 - 后台限制:Android 10 以后,后台应用不能频繁发起 RTT 测距。如果你需要持续定位,建议用前台服务。
总结一句话:Wi-Fi RTT 是室内定位的利器,精度高、延迟低、部署成本低。但前提是你的硬件支持 802.11mc,并且部署位置要合理。记住我前面说的铁皮机柜的教训,别在金属旁边放 AP。
公众号:蓝海资料掘金营,微信deep3321