简介:针对TDOA(到达时间差)与TOA(到达时间)两种常见无线定位手段,此MATLAB源码以克拉美罗界(CRLB)为核心,用于评估目标位置估计的理论精度下限。CRLB是统计估计中无偏估计的性能边界,在定位问题中通常由Fisher信息矩阵求逆得到,脚本即围绕测量模型的构建、FIM的组装与CRLB计算展开,可帮助读者理解测量噪声、基站几何分布、观测数量等因素对定位精度的影响。资源面向通信工程学生、定位算法研究者及无线传感器网络开发者,适合理论验证与算法对比。压缩包共1个文件,格式为m脚本,大小仅1KB,代码精简、无冗余依赖,可在MATLAB中直接运行与修改。已有1291人学习下载,对于希望量化TDOA/TOA定位系统性能上限的读者,这份源码提供了一个轻量直观的起点:既能快速核对CRLB计算结果,也能在此基础上扩展不同信道模型,作为后续仿真实验和算法优化的基准模块。
1. 定位精度问题:TOA/TDOA 的克拉美罗界先于算法存在
做无线定位的人迟早会遇到一个尴尬:Chan 算法写对了、Taylor 也能收敛,可最后误差就是比“某个界”大,又说不上来差在哪儿。这个界就是克拉美罗界(CRLB)。它的特殊之处在于,计算时根本不关心你用哪种定位算法,只依赖观测模型、基站几何和噪声分布,因此是评估 TDOA 和 TOA 算法性能的“物理底线”。拿到这类压缩包,如果只去看里面的算法代码而跳过 CRLB 推导,通常会在 R 矩阵相关性、参考站选择和量纲上栽跟头。本文按照“模型 → FIM 构造 → Python 仿真 → 算法对比 → 融合扩展”的顺序,把克拉美罗界的公式、代码和工程坑一次讲透。适合做 UWB、5G 定位、声源定位以及测向交叉定位算法评估的工程师和研究者。
2. 定位模型与克拉美罗界的推导:从 FIM 到定位误差下界
2.1 TOA 与 TDOA 的观测量模型和同步假设
先明确两个观测模型的数学形式。TOA 测量的是信号从目标到基站的单程传播时间,乘上光速后得到距离:
$$ \rho_i = |\theta - p_i| + n_i, \quad n_i \sim \mathcal{N}(0, \sigma_i^2) $$
其中 $\theta=(x,y)$ 是目标位置,$p_i=(x_i,y_i)$ 是第 $i$ 个基站坐标。TOA 要求目标与所有基站的时钟严格同步,否则 $n_i$ 里会混入系统性的钟差偏置。
TDOA 测量的是同一个发射信号到达两个基站的时间差,以 1 号站为参考时:
$$ r_{i1} = |\theta - p_i| - |\theta - p_1| + (n_i - n_1), \quad i=2,\dots,M $$
TDOA 不需要目标和基站之间完全同步,只要求基站之间同步,因此更贴近实际分布式系统的部署方式。但它换来一个代价:观测向量数学形式更复杂,而且两路 TOA 噪声会进入同一个 TDOA 测量,导致 TDOA 观测噪声之间天然相关。这个相关性直接影响后面 R 矩阵的构造,也是许多 CRLB 计算结果对不上的根源。
2.2 Fisher 信息矩阵与雅可比矩阵的构造
克拉美罗界的求解路线固定:先写出对数似然函数,对位置参数求二阶偏导的数学期望,得到 Fisher 信息矩阵(FIM)。对高斯测量噪声,FIM 有统一形式:
$$ J = H^T R^{-1} H $$
其中 $H = \partial h(\theta)/\partial \theta$ 是观测向量对位置的雅可比矩阵,$R = \operatorname{cov}(n)$ 是测量噪声协方差矩阵。位置估计的协方差矩阵下界就是 $C_{CRLB} = J^{-1}$。
对于 TOA,雅可比矩阵每一行是目标到基站方向的单位向量:
$$ \frac{\partial \rho_i}{\partial \theta} = \left[ \frac{x - x_i}{|\theta - p_i|},,\frac{y - y_i}{|\theta - p_i|} \right] $$
对于 TDOA,因为观测是两段距离做差,雅可比矩阵每一行是两个单位方向向量的差:
$$ \frac{\partial r_{i1}}{\partial \theta} = \frac{\theta - p_i}{|\theta - p_i|} - \frac{\theta - p_1}{|\theta - p_1|} $$
这个“做差”把目标到参考站的共同几何关系抵消掉一部分,所以 TDOA 的 FIM 结构与 TOA 明显不同。当目标恰好落在基站连线上时,若干行的雅可比会线性相关,FIM 接近奇异,CRLB 急剧变大——这是定位几何的固有属性,任何算法都绕不开。
2.3 克拉美罗界的两种打开方式:标量与椭圆
CRLB 矩阵 $C$ 包含完整的位置误差下界信息。实际工程里常见两种读法。
第一种是标量指标,即位置均方根误差下界:
$$ \text{GDOP} = \sqrt{\operatorname{tr}(C)} = \sqrt{\sigma_x^2 + \sigma_y^2} $$
这个量适合画等值线图,用来评估某个区域内“最好的情况能到多少米”。第二种是误差椭圆。对 $C$ 做特征值分解,两个特征值的平方根乘上 $\sqrt{5.991}$(对应 95% 置信度的 $\chi^2$ 分位数),就得到误差椭圆两个半轴。误差椭圆能直观展示定位误差的方向性——比如基站分布在东西两侧时,南北方向误差大,椭圆长轴朝南。
下表汇总 CRLB 计算中的关键符号和常见错误:
| 参数 | 含义 | 常见错误 |
|---|---|---|
| $\sigma_i$ | 第 i 路观测噪声标准差 | 把时间噪声直接当代距离噪声用 |
| $\rho_i$ | TOA 等效距离 | 忘记乘光速 $c$ |
| $r_{i1}$ | TDOA 观测 | 噪声误设为相互独立 |
| $R$ | 噪声协方差矩阵 | 对 TDOA 仍用对角阵 |
| $J^{-1}$ | 位置误差下界协方差 | 混淆 GDOP 与误差椭圆 |
提示:计算 CRLB 时如果发现结果对“参考站选择”特别敏感,通常不是参考站的问题,而是把 TDOA 噪声强行当成了独立噪声。
3. 用 Python 计算 TOA/TDOA 的 CRLB:最小可复现代码与等误差线
3.1 直接按定义计算的函数
先写一个可直接复用的 CRLB 计算函数。它接收基站坐标、目标位置和各站测距噪声标准差,返回 FIM 与 CRLB 协方差矩阵。核心就是将上一章的公式逐行翻译成 NumPy 运算。
import numpy as np def jacobian_toa(theta, bs): # theta: [x, y] 目标坐标 # bs: (M, 2) 基站坐标矩阵 diff = theta - bs d = np.linalg.norm(diff, axis=1) return diff / d[:, None] # 每行是方向余弦 def h_tdoa(theta, bs, ref=0): # TDOA 理想测量:距离差 d = np.linalg.norm(bs - theta, axis=1) return d[1:] - d[ref] def compute_crlb(bs, theta, sigma_toa, mode="tdoa", ref=0): bs = np.asarray(bs, dtype=float) theta = np.asarray(theta, dtype=float) M = len(bs) if mode == "toa": H = jacobian_toa(theta, bs) R = np.diag(sigma_toa**2 * np.ones(M)) else: # TDOA 雅可比 = 各站方向向量 - 参考站方向向量 e = jacobian_toa(theta, bs) H = e[1:] - e[ref] # 将 TOA 独立噪声映射到 TDOA 观测空间 idx_out = [i for i in range(M) if i != ref] A = np.zeros((M - 1, M)) for k, i in enumerate(idx_out): A[k, ref] = -1.0 A[k, i] = 1.0 R = A @ np.diag(sigma_toa**2 * np.ones(M)) @ A.T J = H.T @ np.linalg.inv(R) @ H C = np.linalg.inv(J) return C, J这段代码的逻辑分三块:雅可比矩阵构造、R 矩阵构造、FIM 与协方差求逆。重点说明 TDOA 分支里的 R 矩阵——单站测距噪声独立等方差为 $\sigma^2$ 时,TDOA 观测 $r_{i1}=(\rho_i+n_i)-(\rho_1+n_1)$ 的方差是 $2\sigma^2$,而不同 TDOA 观测 $r_{21}$ 与 $r_{31}$ 共享同一个参考站噪声 $n_1$,协方差为 $\sigma^2$。也就是说,R 矩阵对角线是 $2\sigma^2$、非对角线也是 $\sigma^2$,而不是一个对角阵。代码用 A 矩阵做线性变换,正是为了自动生成这个相关结构。
3.2 仿真参数与误差等值线绘制
计算单个点的 CRLB 只说明一个位置的性能,更常用的是画整个区域的高斯误差下界。下面用 4 个基站组成方形布局,在 0 到 200 米的目标网格上逐个计算 GDOP,生成等值线。仿真参数见下表。
| 参数 | 取值 | 说明 |
|---|---|---|
| 基站坐标 | (0,0)、(200,0)、(0,200)、(200,200) | 正方形四角分布 |
| 目标范围 | 0~200 m 方格,步长 2 m | 覆盖整个基站围成区域 |
| $\sigma_{\text{TOA}}$ | 1.0 m | 单站测距噪声标准差 |
| 模式 | tdoa | 参考站取编号 0 |
import matplotlib.pyplot as plt bs = np.array([[0, 0], [200, 0], [0, 200], [200, 200]], dtype=float) gx, gy = np.meshgrid(np.arange(0, 201, 2), np.arange(0, 201, 2)) rmse_map = np.zeros_like(gx) for i in range(gx.shape[0]): for j in range(gx.shape[1]): C, _ = compute_crlb(bs, np.array([gx[i, j], gy[i, j]]), sigma_toa=1.0, mode="tdoa") rmse_map[i, j] = np.sqrt(np.trace(C)) # GDOP fig, ax = plt.subplots(figsize=(7, 6)) cs = ax.contourf(gx, gy, rmse_map, levels=20, cmap="viridis") ax.plot(bs[:, 0], bs[:, 1], "ro", label="base stations") ax.legend() plt.colorbar(cs, label="CRLB position RMSE (m)") plt.xlabel("x (m)") plt.ylabel("y (m)") plt.show()这个网格仿真的意义在于:你可以直观看到“界”不是均匀的。基站围成的中心区域 CRLB 小,靠近边界或延长线时 CRLB 迅速抬升。绘制等值线之后,把 Chan 或 Taylor 的蒙特卡洛结果叠加上去,就能一眼看出算法在哪些区域接近这个界、哪些区域偏离严重。
3.3 三个常见易错点:R 非对角、量纲、参考站编号
计算 CRLB 的代码通常只有几十行,但出错率最高也在这几十行。我一般会按下面三个方向排查。
第一,R 矩阵必须反映真实噪声相关性。很多人在 TDOA 模式下直接写R = np.diag(sigma**2 * np.ones(M - 1)),算出来的下界偏小,和蒙特卡洛对不上时还误以为是算法问题。小组内部讨论“tdoa crlb”相关话题时,最终定位到这一行的频率最高。
第二,量纲必须统一。如果工程上给出的噪声标准差是纳秒,要乘以光速换算成米。忽略这个系数时 CRLB 会小约 9 个数量级,看起来“完美”,实则完全失真。
第三,参考站编号影响 A 矩阵的位置。上面的代码把 ref 作为参数传入,换参考站时A[ref]列保持 -1,其余非参考站列置 1,不要写死成第一列。否则计算出的 CRLB 在一个对称布局里看着没事,换成非对称基站布局就会出错。
4. 算法对不上界?Chan、Taylor 与克拉美罗界对比的蒙特卡洛验证
4.1 Chan 与 Taylor 的定位思路和初始值要求
CRLB 算出来之后,接下来的工作通常是拿实际定位算法去撞这个界。TDOA 场景里最常见的两种基准算法是 Chan 和 Taylor。
Chan 算法把 TDOA 方程伪线性化,先引入目标到参考站的距离作为辅助变量,做一次加权最小二乘,再把辅助变量与 x、y 的约束关系用第二次最小二乘修正。它的优点是不要初值、计算快,缺点是噪声较大时忽略的二次项会带来偏差,尤其在目标远离基站布局时明显。
Taylor 算法是迭代最小二乘:在初值处对距离差方程做一阶泰勒展开,求解增量 $\delta$,反复迭代直到 $|\delta|$ 小于阈值。它精度高,但对初值敏感。常见做法是以基站几何中心作为初值,或者先用 Chan 的输出喂给 Taylor。
4.2 蒙特卡洛仿真:噪声加在测量上,指标算在位置上
要验证算法接近 CRLB 的程度,不能只在理想测量上算一次定位误差,必须做蒙特卡洛。关键细节是噪声的生成方式:先在每个基站独立的 TOA 距离上叠加噪声,再两两做差得到 TDOA 观测,而不是直接在 TDOA 上叠加独立噪声。后者会人为抹掉 R 矩阵里的相关性,导致仿真出的 RMSE 与 CRLB 不匹配。
from scipy.optimize import least_squares def mle_tdoa(r, bs, theta0, ref=0): def residual(x): return h_tdoa(x, bs, ref) - r res = least_squares(residual, theta0, method="lm") return res.x np.random.seed(2024) bs = np.array([[0, 0], [200, 0], [0, 200], [200, 200]], dtype=float) true = np.array([60.0, 80.0]) sigma_toa = 1.0 n_trials = 5000 est = np.zeros((n_trials, 2)) M = len(bs) idx_out = [i for i in range(M) if i != 0] A = np.zeros((M - 1, M)) for k, i in enumerate(idx_out): A[k, 0] = -1.0 A[k, i] = 1.0 d_true = h_tdoa(true, bs) for k in range(n_trials): r_noisy = d_true + A @ (sigma_toa * np.random.randn(M)) est[k] = mle_tdoa(r_noisy, bs, np.mean(bs, axis=0)) rmse = np.sqrt(np.mean(np.sum((est - true)**2, axis=1))) C, _ = compute_crlb(bs, true, sigma_toa, mode="tdoa") crlb = np.sqrt(np.trace(C)) print(f"RMSE={rmse:.3f}m, CRLB={crlb:.3f}m, ratio={rmse/crlb:.2f}")代码里least_squares求解的是 TDOA 最大似然估计,不带初值的情况下也能收敛,等价于一个精度较高的基准。实际工程中如果只是验证 CRLB,用这个基准算法即可;如果验证对象是 Chan,就把mle_tdoa替换成 Chan 的实现,而噪声生成部分保持不变。
参数说明如下:n_trials=5000是为了让 RMSE 统计稳定,低于 1000 次时比值波动大,不利于判断;theta0=np.mean(bs, axis=0)是基站几何中心,作为迭代初值;method="lm"适合小规模无约束最小二乘,TDOA 方程个数等于 M-1,属于小型问题。
4.3 仿真结果怎么读:比值落点与 NLOS 的偏差
跑完上面的代码,正常情况下 RMSE 与 CRLB 的比值会在 1.0 到 1.1 之间。比值略大于 1 是正常的,因为 CRLB 是渐近界,有限样本下最大似然估计只能逼近而不会低于它。如果比值大于 1.2,我一般按顺序查三处:R 矩阵是否写成了对角阵、噪声是否直接在 TDOA 域叠加、迭代算法初值是否落在错误收敛域。
比值小于 1 则几乎可以断定实现有误。原因很简单:CRLB 是所有无偏估计方差的下界,蒙特卡洛 RMSE 是估计量的经验方差,除非定位器做了有偏修正(比如把估计值强行拉向某个几何中心),否则不可能冲破这个界。
还要特别注意 NLOS 场景。CRLB 推导的前提是高斯测量噪声、LOS 传播条件。室内定位一旦出现穿墙或遮挡,测量误差均值不再为零,模型变样,实测 RMSE 高出 CRLB 两三倍是正常的。此时不能说“算法不达界”,而是“模型不匹配”。正确做法是先对观测做 NLOS 识别与剔除,再拿剩余 LOS 测量计算 CRLB。
5. 进阶:测向交叉定位融合与用 CRLB 反向优化基站布局
最后一层应用是把 CRLB 当作设计工具。常见做法是把它和测向交叉定位算法结合:目标既测量到达时间差,也测量到达角,把两类观测量放进同一个 FIM 框架。假设观测量相互独立,融合后的 FIM 就是各自信息矩阵直接相加:
$$ J_{\text{fusion}} = H_{\text{TDOA}}^T R_{\text{TDOA}}^{-1} H_{\text{TDOA}} + H_{\text{AOA}}^T R_{\text{AOA}}^{-1} H_{\text{AOA}} $$
AOA 观测为方位角 $\phi_i = \operatorname{atan2}(y-y_i,,x-x_i)$,其雅可比行为:
$$ \frac{\partial \phi_i}{\partial \theta} = \left[ -\frac{y-y_i}{\rho_i^2},, \frac{x-x_i}{\rho_i^2} \right] $$
实际操作中不需要重写一整套融合 CRLB 代码,只需要写一个compute_crlb_joint函数,内部把两个模式的 H 与 R 分开构造,最后把两个 J 相加再求逆。这样算出的融合 CRLB 通常比单一 TDOA 或单一 AOA 小很多,可以直接回答“加测向值不值得”的问题。
另一个实用技巧是用 CRLB 反向评估基站布局。给定候选基站位置集合,遍历选取子集并计算目标区域平均 GDOP,选择最小平均 GDOP 的组合。评价函数可以用:
area_score = np.mean(rmse_map) # 区域平均 CRLB 下界如果预算只允许部署 3 个基站,就用组合遍历把所有 3 站方案算一遍,选得分最低的。比单纯凭经验“围成正三角形”要可靠得多,因为真实场地往往有墙壁、立柱和禁入区,几何约束下最优布局不一定对称。
收到这类压缩包时,建议的阅读顺序是先复现 CRLB 等值线,再跑蒙特卡洛对比,最后做融合或布局验证。这样既能把推导和代码互相印证,也能快速定位是算法问题、R 矩阵问题还是几何问题。先用 CRLB 把物理底牌摸清,再决定是升级测距精度、增加基站数量还是调整布站位置。
本文还有配套的精品资源,点击获取