简介这份资源面向从事室内定位研究的高校学生、科研人员与工程开发者聚焦超宽带UWB定位算法在MATLAB环境下的完整实现。内容围绕脉冲生成、室内信道建模、接收机解扩与均衡、TDOA/TOA/AOA等定位算法求解以及多基站仿真评估与结果可视化展开帮助读者搭建可运行的UWB定位系统原型。压缩包共39个文件以27个pdf文档、5个m脚本、5张png图示、1个mlx实时脚本和1个md说明为主pdf用于理论推导与算法讲解m与mlx承载可执行代码png呈现仿真结果整体约51.69MB。目前已有106人学习。读者可据此获得从信号产生到定位误差评估的完整代码链路并借助MATLAB优化与统计工具箱快速迭代算法、对比不同定位方案性能。1. 室内定位超宽带算法 MATLAB.zip从测距到定位一套能跑通的工程链路室内定位超宽带算法 MATLAB.zip 这个标题核心信息量其实有三层室内定位是场景超宽带UWB是物理层手段MATLAB 是验证工具。很多刚接触 UWB 定位的工程师第一反应是「买个模块读个距离就完事了」但真到多基站、多标签、非视距环境里你会发现测距值抖得离谱解算出来的坐标能飘出房间。这个方向适合两类人一类是做机器人、AGV、仓储物流定位的嵌入式工程师需要把 UWB 原始测距转成稳定坐标另一类是做算法验证的研究生或算法工程师想在 MATLAB 里先把定位链路跑通再移植到嵌入式端。它解决的不是「能不能测距」而是「怎么把一堆带噪声、带异常值的距离观测变成可信的二维或三维坐标」。下面我按自己踩过坑的顺序把这条链路拆开讲。2. UWB 测距原理与 MATLAB 仿真环境搭建先让双边测距跑起来2.1 为什么选双边测距而不是单边测距UWB 测距最常用的两种方式单边双向测距SS-TWR和双边双向测距DS-TWR。SS-TWR 只做一次往返设备时钟偏移会直接乘进飞行时间误差里。假设两个模块晶振偏差 20 ppm往返 100 微秒误差就能到 2 纳秒量级换算成距离约 60 厘米。DS-TWR 做两次往返把时钟偏移项在公式里对消掉代价是测距时间翻倍。室内定位场景里标签移动速度通常不高翻倍的测距时间换来厘米级稳定度这笔账划算。DS-TWR 的飞行时间公式T_prop (T_round1 * T_round2 - T_reply1 * T_reply2) / (T_round1 T_round2 T_reply1 T_reply2)其中 T_round1 是设备 A 发起、B 响应的第一次往返时间T_reply1 是 B 从收到到回复的处理时间T_round2 和 T_reply2 是反向的对应量。这个公式的好处是四个时间戳的时钟偏差在分子分母里同阶出现比值把偏差约掉了。2.2 在 MATLAB 里搭一个可复现的测距仿真不要一上来就接硬件先在 MATLAB 里把测距误差模型建出来后面调定位算法才有基准。下面这段代码模拟 DS-TWR 在 10 米距离、时钟偏差 20 ppm、高斯噪声 0.1 纳秒条件下的测距输出。% DS-TWR 测距仿真模拟时钟偏差与噪声对测距的影响 c 3e8; % 光速 m/s d_true 10; % 真实距离 m t_prop_true d_true / c; % 真实飞行时间 s ppm 20e-6; % 晶振偏差 20 ppm sigma_t 0.1e-9; % 时间戳噪声标准差 s N 1000; % 仿真次数 t_round1 2 * t_prop_true 1e-6; % 往返时间含 1us 处理时间 t_reply1 1e-6; t_round2 2 * t_prop_true 1e-6; t_reply2 1e-6; err zeros(N,1); for k 1:N % 给每个时间戳叠加时钟偏差和噪声 tr1 t_round1 * (1 ppm) sigma_t * randn; tp1 t_reply1 * (1 ppm) sigma_t * randn; tr2 t_round2 * (1 - ppm) sigma_t * randn; tp2 t_reply2 * (1 - ppm) sigma_t * randn; t_prop (tr1*tr2 - tp1*tp2) / (tr1 tr2 tp1 tp2); err(k) (t_prop - t_prop_true) * c; end fprintf(测距误差均值 %.4f m标准差 %.4f m\n, mean(err), std(err));逻辑说明循环里对四个时间戳分别施加正负 ppm 偏差模拟 A、B 两个设备时钟方向相反的情况再叠加高斯噪声。最后用 DS-TWR 公式反解飞行时间换算成距离误差。参数说明ppm 控制晶振质量普通晶振 20 ppmTCXO 可以到 2 ppmsigma_t 控制时间戳分辨率DW1000 这类芯片时间戳精度约 15 皮秒但实际受多径影响会到 0.1 纳秒量级。跑完你会看到误差标准差在厘米级如果换成 SS-TWR 公式均值会直接偏出几十厘米这就是选型理由。2.3 仿真环境里必须加的三类误差源只加高斯噪声的仿真太干净移植到硬件必翻车。我一般会补三类第一类是多径导致的测距正偏UWB 在室内金属和玻璃环境下首径可能被削弱芯片锁到次径测距偏大第二类是非视距衰减人体遮挡能让信号强度掉 10 dB 以上测距直接跳变第三类是天线延迟每个模块的射频前端延迟不同不校准的话所有距离都带一个固定偏移。在 MATLAB 里可以用一个偏置项加随机跳变来近似后面定位解算时再用校准参数扣掉。3. 从距离到坐标最小二乘与卡尔曼滤波的 MATLAB 实现3.1 多基站定位的几何基础与最小二乘解有了三个以上基站的测距值就能解二维坐标。设基站 i 坐标为 (xi, yi)标签坐标为 (x, y)测距值为 di则(x - xi)^2 (y - yi)^2 di^2这是非线性方程直接解麻烦。常用做法是选一个参考基站把其他基站方程减去参考基站方程线性化成一元一次方程组再用最小二乘解。下面代码实现这个过程并加入一个 5 厘米的测距偏置来模拟天线延迟。% 多基站最小二乘定位线性化 最小二乘 anchors [0 0; 10 0; 10 10; 0 10]; % 四个基站坐标 m p_true [3.5, 6.2]; % 真实标签位置 bias 0.05; % 天线延迟导致的测距偏置 m sigma_d 0.08; % 测距噪声标准差 m d zeros(4,1); for i 1:4 d(i) norm(p_true - anchors(i,:)) bias sigma_d * randn; end % 以第一个基站为参考构造线性方程组 A*p b A 2 * (anchors(2:end,:) - anchors(1,:)); b zeros(3,1); for i 2:4 b(i-1) d(1)^2 - d(i)^2 anchors(i,1)^2 anchors(i,2)^2 ... - anchors(1,1)^2 - anchors(1,2)^2; end p_est A \ b; fprintf(真实位置 (%.2f, %.2f)解算位置 (%.2f, %.2f)\n, ... p_true(1), p_true(2), p_est(1), p_est(2));逻辑说明A 矩阵由基站坐标差构成b 向量由测距平方差和坐标平方项构成反斜杠直接解最小二乘。参数说明bias 是系统误差最小二乘本身消不掉必须在测距阶段校准sigma_d 是随机误差多基站冗余可以平均掉一部分。跑一次你会看到解算位置和真实位置差几厘米到十几厘米如果 bias 设成 0.3 米误差会直接放大到分米级这就是为什么天线延迟校准不能省。3.2 卡尔曼滤波平滑轨迹把跳变坐标拉回来最小二乘是逐帧解算帧间没有约束标签静止时坐标也会小范围跳。卡尔曼滤波把位置和速度作为状态量用运动模型预测再用测距观测更新能把跳变压下去。下面是一个匀速运动模型的卡尔曼滤波实现。% 卡尔曼滤波平滑二维轨迹状态 [x, y, vx, vy] dt 0.1; % 采样间隔 s F [1 0 dt 0; 0 1 0 dt; 0 0 1 0; 0 0 0 1]; % 状态转移矩阵 H [1 0 0 0; 0 1 0 0]; % 观测矩阵只观测位置 Q diag([1e-4, 1e-4, 1e-3, 1e-3]); % 过程噪声 R diag([0.01, 0.01]); % 观测噪声对应最小二乘解算方差 x [0; 0; 0; 0]; % 初始状态 P eye(4); % 初始协方差 % 模拟一段带噪声的最小二乘解算轨迹 t 0:dt:5; pos_meas [2 0.5*t 0.1*randn(size(t)); ... 1 0.3*t 0.1*randn(size(t))]; pos_filt zeros(2, length(t)); for k 1:length(t) % 预测 x F * x; P F * P * F Q; % 更新 z pos_meas(:,k); y z - H * x; S H * P * H R; K P * H / S; x x K * y; P (eye(4) - K * H) * P; pos_filt(:,k) x(1:2); end fprintf(滤波前位置标准差 %.3f m滤波后 %.3f m\n, ... std(pos_meas(1,:) - (2 0.5*t)), ... std(pos_filt(1,:) - (2 0.5*t)));逻辑说明预测步用匀速模型推状态更新步用观测残差修正。参数说明Q 越大越信任观测轨迹跟得快但抖R 越大越信任预测轨迹平滑但滞后。我一般先用最小二乘解算的方差估计 RQ 按标签最大加速度反推。跑完对比标准差滤波后通常能压到滤波前的一半以下。注意卡尔曼滤波对非视距跳变只能缓解不能根治遇到连续跳变还是要靠测距层的异常值剔除。3.3 基站布局对定位精度的影响四个基站摆成正方形和摆成一条直线精度差很多。几何精度因子GDOP决定误差放大倍数基站围成的区域越大、越接近正多边形GDOP 越小。我一般建议基站不要共线高度尽量一致标签活动区域落在基站围成的凸包内部。如果只能在房间一侧布基站另一侧的定位误差会明显偏大这时候要么加基站要么在算法里对边缘区域做加权约束。4. 避坑与排查UWB 定位从仿真到硬件最容易翻车的五件事4.1 测距值整体偏大或偏小现象所有距离都比卷尺量出来的多或少一个固定值。原因天线延迟未校准每个模块射频前端延迟不同标签和基站互换后偏置方向还会变。解决在已知距离下做双向测距解出每个模块的延迟参数写进配置里扣掉。常见做法是取 1 米和 5 米两个点做线性拟合把斜率和截距都校一遍。4.2 静止时坐标持续跳动现象标签放着不动解算坐标在十几厘米范围内随机跳。原因测距噪声被最小二乘放大尤其是基站布局接近共线时。解决先看测距标准差如果超过 10 厘米先查电源和天线如果测距正常但坐标跳加卡尔曼滤波或对最小二乘加正则项。我一般会先画测距残差图残差大的基站直接降权。4.3 非视距环境下坐标突然飞走现象人走过标签和基站之间坐标瞬间偏出几米人走开后恢复。原因人体遮挡导致首径被削弱芯片锁到反射径测距偏大。解决在测距层加信号强度门限首径强度低于阈值时标记为可疑定位解算时剔除或降权。MATLAB 里可以用一个滑动窗口检测测距跳变连续三帧跳变超过阈值就触发剔除。4.4 多标签互相干扰导致测距丢失现象单个标签测距正常多个标签同时工作时部分距离读不到或跳变。原因UWB 信道冲突标签发送时隙没排开。解决在协议层做时分多址给每个标签分配独立时隙MATLAB 仿真里可以加一个冲突模型模拟时隙碰撞导致的丢包验证定位算法在丢包下的鲁棒性。4.5 从 MATLAB 移植到嵌入式后结果对不上现象MATLAB 里跑得好好的算法移植到 C 语言后坐标偏差大。原因浮点精度差异、矩阵求逆数值稳定性、坐标系定义不一致。解决移植前把 MATLAB 算法用定点或单精度浮点重跑一遍确认精度损失可接受矩阵求逆尽量用 QR 分解替代正规方程避免条件数放大。我一般会在 MATLAB 里生成测试向量嵌入式端逐帧对比中间结果定位到具体哪一步开始偏。5. 进阶技巧用残差加权与鲁棒估计把定位精度再压一档最小二乘和卡尔曼滤波是基线真到复杂环境里还得加鲁棒估计。我常用的做法是两步先算最小二乘残差再用残差反推每个测距值的权重做一次加权最小二乘。残差大的基站权重低残差小的权重高这样非视距跳变不会把整体解算带偏。% 残差加权最小二乘迭代两次抑制异常测距 p_est A \ b; % 第一次普通最小二乘 for iter 1:2 r zeros(4,1); for i 1:4 r(i) d(i) - norm(p_est - anchors(i,:)); % 测距残差 end w 1 ./ (abs(r) 0.05); % 残差越大权重越小 W diag(w(2:end)); % 参考基站不参与加权 p_est (A * W * A) \ (A * W * b); % 加权最小二乘 end fprintf(加权后位置 (%.2f, %.2f)\n, p_est(1), p_est(2));逻辑说明第一次解算得到粗略位置算每个基站的测距残差残差大的给低权重再做加权最小二乘。参数说明0.05 是防止除零的小量实际取值看测距噪声水平噪声大就取大一点。迭代两次通常够用次数多了可能过拟合。这个技巧在非视距占比 20% 以内的场景里能把定位误差压掉三到五成。另一个技巧是给卡尔曼滤波加自适应 R 矩阵。当测距残差连续偏大时临时调大 R让滤波器更信任预测而不是观测等残差恢复再调回来。这样轨迹在遮挡期间不会飞遮挡结束后也能快速跟上。实现上用一个滑动窗口统计残差方差映射到 R 的缩放系数即可。最后说个血泪经验MATLAB 里验证算法时一定要把仿真数据存成文件移植后用同一份数据回放对比。我见过太多人仿真和硬件各调各的最后对不上只能从头查。把测试向量固定下来每一步中间结果都打印比事后猜哪里出问题省太多时间。希望帮到你。本文还有配套的精品资源点击获取