
机器狗从遥控器“进化”到自主跟随UWB超宽带技术是绕不开的关键。这两年不少搞机器人的朋友都在问同一件事视觉跟随在户外一抖就丢、GPS在室内直接罢工想让机器狗老老实实跟着人走到底用什么方案最稳我做了多轮对比和实机验证后可以很负责任地说在室内外切换、多障碍物、需要厘米级相对定位的场景里UWB跟随是当前工程落地性价比最高的路子之一尤其是在“go2机器狗STM32UWB模块”这套组合上已经能跑出非常可用的跟随效果。这篇文章不玩虚的直接从选型、原理、算法、联调到排错把整个UWB跟随项目拆开讲透适合正在搞机器狗二次开发、或者准备把UWB接入移动机器人项目的工程师当实操参考。1. 为什么机器狗跟随要选UWB一个被低估的硬核方案很多人听到“跟随”第一反应是摄像头目标检测毕竟大疆、小米的机器人和无人机都有视觉跟随效果看起来也不错。但真把视觉方案放到机器狗身上尤其是户外的四足小跑场景坑一个接一个光照变化、树叶遮挡、目标换装、相机晃动导致的跟踪框漂移还有最致命的——视觉只告诉你“目标在图像里”要转成机器狗能用的相对距离和相对角度得先做标定、深度估计、坐标变换整套pipeline的复杂度和算力开销非常大。我最初在GO2上试过用RGB-D相机跑YOLO深度测距实测在傍晚逆光环境下目标检测成功率和测距稳定性都不太理想处理器也得一直高负载跑着。UWB则是完全不同的思路。超宽带技术通过发送纳秒级窄脉冲在时间轴上达到皮秒级分辨力本质上是“用时间换精度”测距精度能干到厘米级测角精度能做到几度以内而且不受光照影响不依赖图像特征也没有视觉盲区。跟视觉相比UWB更像是一个“带尺子的无线电通道”它不需要“认出”你是主人只需要通过物理层测距测角就知道你在哪个方向、多远。这一点对机器狗跟随来说非常合适因为四足机器人真正需要的不是“看到人”而是“在人身上确定一个可跟踪的物理锚点”然后稳定地保持距离和方向。再对比其他方案。GPS在室内和无遮挡条件下直接不可用蓝牙RSSI的精度正负好几米跟随基本就是撞大运激光雷达可以做人体识别跟随但成本高、点云处理复杂这在几百上千块钱的消费级改造项目里不划算。UWB的优势很明确成本低模块几十到一百多块钱、精度高半径误差普遍在10cm上下、低延迟测距一轮下来十几毫秒、室内外通用对非视距有一定容忍度但需要配合算法缓解。尤其对于GO2这种本身就带运动控制SDK的机器狗UWB传感器只需要输出一个稳定相对坐标剩下的“怎么走”交给机器狗的底层运动控制分工干净利落。表格对比更能说明问题。我在方案预研阶段列过这样一张对比表方案精度抗光照影响室内可用算力需求成本工程复杂度视觉RGB-D/YOLO中受深度估计影响差是高中高高GPS/RTK米级RTK厘米级好否室内失效低中高中蓝牙RSSI差数米好是低低低激光雷达高好是高高高UWB高厘米级好是低低中所以做这个项目时我的核心判断是在“室内外都能用、目标是人、预算有限、要能稳定复现”这四个条件约束下UWB是性价比和可靠性的最优选。视觉可以作为辅助但主骨架必须用UWB撑起来。这个选择在后续多次雨天、傍晚、草地测试中都被证明是对的。2. 系统架构与核心硬件选型2.1 整体拓扑标签、基站与机器狗怎么分工UWB跟随系统的架构乍一看很简单就是两边挂UWB模块一端在目标身上一端在机器狗上然后做测距测角。但实际工程中硬件拓扑和学习资源里常见的“标签-基站”模型要区分清楚。UWB通信存在“锚点”和“标签”两个角色通常锚点是位置已知的固定参考点标签是待定位的移动点。在跟随场景中我们把机器狗身上装的模块作为测距测角的主动方它负责发轮询帧人身上带的模块作为目标端收到帧后回响应帧机器狗端通过双向测距算出距离通过天线阵列的相位差算出到达角。我采用的完整链路如下人身上挂一个轻量UWB标签可以做成胸牌或挂在背包上机器狗本体上安装UWB基站模块和主控板。基站模块负责测距测角并解算相对坐标把数据通过SPI/UART交给主控板主控板STM32F407再做数据滤波、运动解算然后把速度指令打包通过串口或网口发给机器狗的上位机SDK机器狗底层根据速度指令执行运动。这套架构的好处是UWB模块只负责“感知”主控只负责“决策”机器狗只负责“执行”每一层都解耦调试时可以单独验证。2.2 UWB芯片/模块怎么选不要只看价格UWB模块的核心是芯片和天线现在市面上常见的方案有Decawave的DW1000系列和Qorvo收购后推出的DW3000系列还有恩智浦的Trimension系列。DW1000是经典款资料多、社区活跃、二手开发板便宜基本是学习阶段的首选但它的测角功能需要自己搭多天线阵列或用额外算法。DW3110/DW3120这类新型号则在芯片层面集成了PDOA相位差测角能力配合配套天线可以直接算出到达角做跟随项目时能省不少事。NXP的Trimension SR150也有类似能力集成度更高但资料相对封闭踩坑时能搜到的案例少。选型时有个容易踩的坑只看标称测距精度而忽视测角能力。UWB跟随的核心不只是“距离”没有角度信息机器狗就只能知道“主人离我几米”却不知道“在哪个方向”于是转向就只能靠历史轨迹猜出现典型的“追着尾巴转圈”问题。所以做跟随项目时我强烈建议优先选支持PDOA/AOA测角的模块哪怕贵一点也比省下的钱后期填算法坑划得来。模块配套的天线也很关键。UWB是宽带脉冲信号天线相位中心的一致性直接影响PDOA精度。我试过用淘宝上十几块钱的通用天线接DWM1000测距还能用但角度输出抖动非常严重后来换了原厂推荐的天线效果才有质的改善。做工程不要省天线的钱这是无数人用教训换来的经验。2.3 主控选型STM32为什么够用UWB跟随项目的主控不一定要上树莓派或Jetson。虽然机器狗本身有ROS环境但UWB测距解算、坐标滤波和运动控制指令打包这件事用STM32就足够了。我用的是STM32F407主频168MHz有4个UART、SPI接口处理DWM3000的测距数据毫无压力。实测在整个闭环里STM32的CPU占用率不到30%大部分开销还是在轮询数据帧和滤波算法上。用STM32还有几个便利第一UWB模块的原厂驱动库大多基于C语言用STM32的HAL库或标准库都能快速移植第二STM32作为独立节点不占用机器狗主机的算力机器狗的上位机只负责接收速度指令和运动控制职责更清晰第三STM32板子便宜调试时烧录、串口打印、在线调试都很方便。初学者选F103也行但如果要同时跑卡尔曼滤波和角度解算建议还是F407起步多出来的内存和频率都是实打实的余量。2.4 机器狗平台的接入桥接以GO2为例机器狗这边的接入是整个项目里最容易卡壳的环节。以宇树的GO2为例官方提供SDK支持LCM、ROS以及以太网通信。UWB跟随项目的标准做法是STM32把解算后的期望速度通过串口发给一台工控板或直接把STM32通过USB转以太网接入机器狗的网络走SDK的MotionControl接口由SDK把速度指令解析成机器狗可以执行的运动控制命令。需要注意的是机器狗底层的运动控制器通常只接收“期望线速度期望角速度”这种指令所以STM32侧的解算必须输出机器狗能直接消费的格式而不是把距离角度一股脑丢过去让狗自己算。我在联调时遇到过一个很典型的坑直接往机器狗SDK发自定义数据包但没按它规定的协议格式加帧头校验导致狗端完全没反应。后来老老实实看了SDK的example把数据按协议封帧才算打通。这块建议别上来就自己发明协议先跑通官方demo再逐步改造成UWB数据流。3. 跟随算法从“测到距”到“跟得住”3.1 测距三选一TWR与TDoA怎么取舍UWB测距的底层原理是“飞行时间”ToF。无线电波速度是光速如果能测出信号从A到B花了多少时间乘以光速除以2就是单程距离。实际实现时最简单可靠的是“双向测距”TWRA发poll帧B收到后延时回response帧A再发final帧并记录时间戳最后双方在各自的收发时间轴上凑出飞行时间。因为UWB的时间戳分辨率非常高时间测量可以精准到纳秒级所以测距精度就是厘米级。在跟随场景里我用的就是TWR它的好处是不要求两个设备时钟严格同步非常适合标签和基站各自独立供电、独立时钟的场合。TDoA到达时间差则需要多个基站或标签之间做高精度时钟同步更适合固定基站组网的室内定位而不是一对一跟随。这里提醒一点很多UWB评估板出厂默认跑的是简单的单边单向测距SS-TWR精度和稳定性都不如双边双向测距DS-TWR。做跟随项目时务必把驱动配置成DS-TWR数据延迟和测距稳定性会有明显差别。3.2 角度解算单基站实现方向跟随的关键距离只有一维信息要形成完整的跟随控制还必须知道目标在哪个方位。现在消费级UWB方案里最常用的是PDOA相位差到达角原理基站端放两个或多个天线同一个UWB信号到达不同天线的路径有微小差导致两个天线接收到的射频信号相位不同通过相位差反推出信号的到达角。这个原理和人的两只耳朵判断声源方向很像左右耳听到相同声音时方向在正前方一侧相位有差就能判断声音偏左偏右。使用支持PDOA的模块时需要特别注意天线的安装方向。不同模块的参考天线方向和坐标系定义不同如果天线方向和模块标示不一致解算出来的角度可能是负的或者有固定偏置。我建议拿到模块后先做一次静态标定把目标放在正前方不同角度-90°到90°记录模块输出的AOA值拟合出一条校准曲线之后在程序里做查表校正。这套标定流程大约半小时但能大幅提升角度数据的可用性。3.3 运动控制策略极坐标转速度指令有了相对距离d和相对角度θ就可以规划机器狗的运动。最常见的做法是“极坐标运动解算”把机器狗当前的速度期望值拆解为线速度v和角速度ω。控制逻辑不复杂核心是几个阈值判断加上比例控制当d大于“舒适跟随距离”比如1.5m且小于“安全距离”时v正比于(d - D_target)越远走得越快当d小于“安全距离”比如0.8m时v设置为0甚至负值让机器狗往后撤防止撞到人ω则正比于θ目标角度偏差越大转动越快。我实际落地时会加入“死区”和“斜坡限幅”两个处理。死区是指距离误差和角度误差在某个小区间内时不调节速度避免机器狗在平衡点附近抖动斜坡限幅是指对速度指令做一个低通限制防止突然的大速度变化把机器狗甩出去或吓到人。这两点不做的话初始测试基本都会出现狗来回点头、原地画圈的现象。3.4 数据融合别让跟随发飘实测发现UWB原始数据在某些情况下会突然跳变比如人转身时身体遮挡天线、墙角反射导致多径干扰测距值可能在几十毫秒内跳几十厘米。这些毛刺直接进控制环会让机器狗的动作很神经质。所以要加滤波通常的做法是用卡尔曼滤波或滑动平均把UWB的距离和角度数据先平滑再送进运动解算。我用的是一维扩展卡尔曼滤波状态量是距离、距离变化率、角度、角速度观测量是UWB输出的距离和角度。这样不仅输出了平滑的位置还能得到相对速度估计用于前馈控制。卡尔曼滤波的参数调起来会有一些玄学成分Q和R矩阵的比值决定了“信任传感器”还是“信任模型”我调试时的经验是把Q调大一点、R调小一点让滤波器更信任UWB观测值能保留快速响应的同时滤掉毛刺。如果你不想上卡尔曼先用一阶低通滤波也能跑只是动态响应会慢一些。4. 实操落地从原理图到整机联动4.1 前置准备与工具链要复现这个项目硬件准备如下一块支持PDOA的UWB基站模块比如DWM3001CDK或者基于DW3110的评估板一个标签模块可以是同型号确保固件支持TWR应答一块STM32F407开发板一个USB转TTL串口工具以及一台GO2或兼容SDK的四足机器人。软件方面需要STM32CubeIDE或Keil、UWB原厂SDK、宇树SDK如果接GO2以及一套串口调试助手和波形显示工具。波形显示强烈推荐用SerialPlot可以用实时曲线看距离和角度数据联调时会发现肉眼可见的跳变比只看数值高效得多。4.2 核心流程STM32读取UWB测距数据UWB模块和STM32之间一般走SPI接口。原厂SDK都提供了基础的读取API比如DWM3000的dwt_readsystime、dwt_rxenable这类函数。STM32这边的工程结构大致是初始化SPI、配置UWB中断通常是一个外部GPIO用于指示接收事件、在主循环里轮询有没有收到完整测距帧收到后用DS-TWR协议解析出距离和角度。这里我把关键流程拆成伪代码方便理解// 主循环主流程示意 while (1) { if (UWB_RX_IRQ_Flag) { // 收到UWB数据帧中断 UWB_RX_IRQ_Flag 0; dwt_read_rx_frame(...); // 读取原始帧 if (parse_ds_twr(...)) { // 解析DS-TWR协商结果 distance_mm get_range_mm(...); angle_deg get_aoa_deg(...); } } if (new_meas_ready) { filtered kalman_update(distance_mm, angle_deg); v_cmd calc_linear_velocity(filtered.dist); w_cmd calc_angular_velocity(filtered.angle); send_cmd_to_dog(v_cmd, w_cmd); } }注意一个细节UWB数据帧的解析不能在中断服务函数里做耗时操作否则会丢帧。我一般是在中断里置标志位在主循环里解析和处理实测刷新率能稳定在40Hz以上这对运动控制来说已经非常充裕了。4.3 联调把数据送进机器狗大脑STM32计算出的速度指令要按机器狗SDK的协议封装。以GO2为例官方SDK中运动控制通过以太网或共享内存形式接入STM32侧通常会通过UART把指令发送给一个转换桥或者直接把STM32接到狗身上的主板串口引脚。在Linux主机上可以用宇树官方提供的Python或C SDK订阅运动控制话题把串口收到的期望速度转成SDK能识别的数据类型再发布。联调的重点是“先静态后动态”先把机器狗架起来不落地的状态把UWB数据流打印出来确认STM32收到的距离角度和真实摆放位置一致然后让机器狗站立手动给几个固定速度指令确认狗能正常移动最后才跑完整闭环。千万不要一上来就让人拿着标签满屋跑那样问题满天飞根本分不清是UWB不准、滤波没调好还是机器狗响应太慢。4.4 现场标定与安全策略标定分两步。第一步是单点标定把标签放在机器狗正前方1m处看程序输出的距离和角度是否准确误差大的话检查天线安装和模块坐标系。第二步是几个典型角度标定在0°、±45°、±90°方向分别测量角度输出做成查表修正。距离一般线性度很好角度会有一点非线性查表修正后整体精度能控制在5°以内足够机器狗做出正确的转向响应。安全策略绝不能省。我在代码里写了三类保护距离下限保护小于0.5m直接停止前进、断链保护连续200ms没收到UWB数据自动原地停止并进入搜索模式、异常数据保护测距值突变超过阈值时保持上一帧速度而不是响应跳变值。这三类保护看似简单但在室外测试时真的救过我尤其是断链保护否则标签一进包或者人一转身机器狗会因为“看不到目标”而冲出去。5. 常见问题与排查技巧实录5.1 测距值跳变多径干扰和天线遮挡这是UWB项目中最常见的问题。多径干扰指UWB信号经过墙壁、地面多次反射后叠加到直射信号上导致测距测量值出现伪峰。表现就是人正常走着突然测距从1.2m跳到1.8m过一会又跳回来。排查思路有两个方向一是看环境靠近金属墙、大块金属物时跳变会更明显尽量让机器狗远离大面积反射面二是看算法DS-TWR配合“首次路径检测”可以在一定程度上抑制多径但不同模块的策略差异很大需要根据模块手册打开相应优化开关。另外就是滤波兜底把卡尔曼滤波的观测噪声协方差R调大让滤波器对跳变不敏感。5.2 角度输出抖动天线相位中心不一致如果距离正常但角度抖得厉害优先怀疑天线。有些模块虽然叫“支持AOA”但它集成的两个天线相位中心距离很近测角分辨率有限再加上机器狗运动时模块整体晃动角度输出劣化就更明显。解决思路一是选用原厂推荐的天线组合二是在软件层面增加角度滤波我用了低通中值滤波结合三是把模块固定到机器狗结构件的刚性位置减少振动。如果角度还是不稳就要考虑是不是PDOA解算的参考天线方向被接反了可以打印原始I/Q数据检查。5.3 跟随滞后刷新率不够和滤波过度机器狗在快速转身时总是慢半拍首先查数据链路每一级的刷新率UWB测距帧率、STM32主循环处理频率、串口波特率、SDK下发指令频率。我之前发现STM32用115200波特率下发速度指令时偶尔会在高频率下发时丢字节导致狗端指令缺失表现就是运动突然停顿。后来把波特率提高到921600并加了环形缓冲问题才解决。另一个原因是滤波做得太重比如滑动窗口长度取50必然带来明显相位滞后这时候要减少窗口或者改用卡尔曼滤波在平滑性和响应速度之间找到平衡点。5.4 标签丢失后机器狗乱跑断链保护如果没有做UWB标签一旦没电或者走出有效范围机器狗收到的就是陈旧的测距数据由于程序还在用旧数据算指令狗会顺着上一个速度方向继续走。这是很危险的情况。所以再次强调必须有断链检测和停止机制。我在实现中是每收到一帧就更新时间戳主循环里检查时间戳是否在200ms内更新过超过则把速度指令强行置零并让机器狗原地转动寻找目标可以转一圈等UWB重新建链。5.5 快速排查速查表现象可能原因排查/解法测距跳变多径、金属反射、标签遮挡调整天线方向、开启首径检测、卡尔曼滤波角度抖动天线相位中心差、模块振动、参考方向错误换天线方案、加滤波、重做静态标定机器狗抖动点头死区太小、比例增益过高增大死区、降低比例系数、加斜坡限幅跟随滞后滤波过重、刷新率低、波特率不够降滤波强度、提高帧率和波特率建链慢/频繁掉线固件协议配置不对、供电不足检查DS-TWR配置、用独立稳压电源标签丢失乱跑缺少断链保护加时间戳检查、强制停车、搜索模式5.6 体验优化从“能跟”到“跟得舒服”把UWB跟随跑通只是第一步要让机器狗跟着人走得像样还要调很多细节。比如在运动解算里增加“转向与前进联动”的控制机器狗在转弯时先减速再转避免高速转圈导致身体侧翻又比如根据目标距离动态调整期望速度的坡度离得越远加速越平缓避免机器狗猛地冲刺。还有一个很实用的小技巧在停走逻辑里增加“驻留时间”只有当目标持续偏离或接近超过一定时间后再触发动作这样人站在原地几秒钟时狗不会因为距离轻微变化就前后摆动。结语一点个人体会把UWB跟随从一张原理图变成能真正跟在人身后跑的机器狗中间踩过的坑比想象中多尤其是UWB原始数据进控制环那一步数据毛刺对运动稳定性的影响远比理论上看到的严重。但整个项目走下来我的体会是这套方案的工程价值确实突出成本可控、链路清晰、算法不玄学而且UWB本身还在快速迭代新一代模块的测角能力和抗多径能力都在提升。最后说一个实用小技巧联调时把测距测角数据同时用波形工具画出来再把机器狗的实际速度叠加在同一时间轴上你会发现很多问题一眼就能定位到到底是感知层、滤波层还是执行层出了问题。这套调试习惯比任何单点配置都值钱。