前段时间拿宇树的 Unitree Go2 Edu 版做了一套轻量级园区巡检的原型验证。很多朋友在看官方宣传片时觉得四足巡检非常轻巧,买台机器跑个 Demo 就完事了。但实际把机器狗从「玩具/科研平台」推向「工业/园区巡检场景」时,从供电、配重、通信到底层控制,工程坑一个接一个。
本文记录我们基于 Go2 落地自主巡检方案的全流程,包含外挂负载选型、unitree_sdk2 基础链路打通、状态机逻辑,以及现场调试总结出的踩坑经验。
一、 硬件拓扑与供电改造
在园区场景下,Go2 自带的机身感知(单目鱼眼 + 自研 L1 4D 激光雷达)只能满足基础避障和短距离测距,无法满足电力仪表识别、红外热成像测温或车牌抓拍等细分巡检需求。我们必须加装外挂负载。
1. 负载配置与配重控制
Go2 官方标称的有效负载在 5 kg 左右,极限负载约 8 kg。但在巡检任务中,由于需要持续小跑或爬坡,强烈建议把长期刚性负载控制在 2.5 kg 到 3 kg 以内,否则电机温升极快,续航会直接打五折。
我们外挂的硬件清单如下:
- 边缘计算核心:Jetson Orin Nano / Orin NX(带定制铝合金散热外壳)
- 巡检传感器:双光云台相机(可见光 + 640x512 热成像)
- 定位模块:高精度 RTK-GNSS 模组 + 螺旋天线(室外园区必须依靠 RTK,雷达在空旷草坪很容易退化)
- 支架设计:3D 打印(尼龙碳纤维材质)背板,通过机身预留螺丝孔固定
2. 供电踩坑:底盘电池直取电的风险
Go2 提供了外供电接口,电池输出电压在 24V - 33.6V(充饱电状态)波动。
- 踩坑点:电机大角度发力或越障瞬间,母线电压会产生剧烈的电压跌落与反电动势纹波。早期我们用普通降压模块给 Orin 供电,当机器狗快跑刹车时,Orin 会偶发性硬重启。
- 解法:加装宽压输入(9V-36V)的工业级隔离 DC-DC 降压模块,输出稳定的 12V / 19V,并在输出端并联低 ESR 大电容或微型超级电容缓释模块。
二、 通信架构与 unitree_sdk2 基础链路
Go2 放弃了老一代基于 Boost/UDP 的封装,全面拥抱 CycloneDDS,提供了官方的 unitree_sdk2(支持 C++ 和 Python)。
1. 网络拓扑
巡检架构推荐使用双网卡方案:
- 内部通信:Jetson 算力板通过有线网口连接 Go2 内部交换机(默认机载 IP 段通常为
192.168.123.x),用于高频收发 DDS 运动控制指令和读取底层电机状态。 - 外部通信:外挂 4G/5G 工业路由器,通过内网穿透或 VPN 与园区管理中控平台通信,负责上传视频流和巡检告警数据。
2. 底层控制代码(Python 示例)
巡检业务层一般不需要调用低层级(Low-level)电机力矩控制,调用高级(High-level)的 SportClient 控制速度与步态即可。
以下是通过 unitree_sdk2 发送移动指令的基础封装示例:
import time
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
from unitree_sdk2py.go2.sport.sport_client import SportClient
class Go2PatrolDriver:
def __init__(self, network_interface="eth0"):
# 1. 初始化 DDS 通信通道
ChannelFactoryInitialize(0, network_interface)
# 2. 实例化运动控制客户端
self.sport_client = SportClient()
self.sport_client.SetTimeout(10.0)
self.sport_client.Init()
def prepare_patrol(self):
# 解锁站立
self.sport_client.StandUp()
time.sleep(2)
# 切换到平衡或常规步态
self.sport_client.BalanceStand()
print("Go2 is ready for patrol.")
def move_vector(self, vx: float, vy: float, vyaw: float):
"""
vx: 前后线速度 (m/s)
vy: 左右线速度 (m/s)
vyaw: 转向角速度 (rad/s)
"""
# 注意限速保护:园区巡检建议 vx 控制在 0.5 - 0.8 m/s 以内
vx = max(min(vx, 1.0), -1.0)
vyaw = max(min(vyaw, 1.0), -1.0)
self.sport_client.Move(vx, vy, vyaw)
def stop(self):
self.sport_client.StopMove()
三、 巡检任务逻辑:RTK 航向跟随与业务触发
室外园区的空旷道路与绿化带场景,纯依赖激光 SLAM 建图极易发生横向漂移。我们的方案是:RTK 经纬度做全局路径导航 + 宇树自带避障雷达做局部动态避障。
状态机控制流程
[待机/底座]
│
▼
[读取巡检任务航点列表 (Waypoint List)]
│
├─► [导航阶段]:纯追踪算法计算 (Target Heading - Current Heading)
│ ├─ 控制 vx 与 vyaw 逼近目标点
│ └─ 激光雷达检测前方障碍物 -> 触发局部绕障 / 减速停障
│
├─► [到达航点 (容差 < 0.2m)]:触发 StopMove()
│ ├─ 调整机身姿态(Pitch / Yaw)对准检测目标
│ ├─ 双光相机抓拍 / 热成像测温 / AI 推理(表计读数、烟火识别)
│ └─ 数据打包上传中控服务器
│
▼
[下一个航点 / 返航充电]
在到达指定点后,Go2 允许通过 Euler() 指令微调机身的俯仰角(Pitch)和偏航角(Yaw),这在没有独立云台或云台角度不够时非常实用。你可以直接让狗身俯仰 ±20° 来配合固定相机的拍摄。
四、 实测踩坑记录与解决策略
1. 物理重心(CoG)偏移导致步态震颤
- 现象:外挂传感器如果放在背板靠前的位置,机器狗在停止或快速转向时,前腿会出现高频的机械震颤,严重时甚至触发电机过载保护导致扑街。
- 原因:Go2 内置运动控制器的步态规划模型基于出厂标准重心。负载靠前破坏了前后腿的地面反作用力(GRF)分配。
- 解法:在安装背板时,使用称重法找到系统综合重心,尽量让负载中心落在机身几何中心稍偏后 1-2 cm 处。如果重心被迫偏移,需要在
unitree_sdk2启动配置里做相应的偏置补偿(如果底层固件版本支持参数导入)。
2. DDS 局域网组播风暴与掉线
- 现象:当 Jetson 同时开着 Wi-Fi 连外网,又开着网线连 Go2 底盘时,DDS 通信经常毫无征兆地卡死,日志报
CycloneDDS lease expired。 - 原因:CycloneDDS 默认会监听所有网络接口的多播流量。Wi-Fi 网络如果存在路由漫游或广播风暴,会直接阻塞 DDS 控制链路。
- 解法:显式配置
cyclonedds.xml文件,绑定唯一的通信网卡,禁用多网卡自动发现:
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="any">
<General>
<NetworkInterfaceAddress>eth0</NetworkInterfaceAddress>
</General>
<Discovery>
<ParticipantIndex>auto</ParticipantIndex>
<MaxMessageSize>65500</MaxMessageSize>
</Discovery>
</Domain>
</CycloneDDS>
在启动脚本中加入 export CYCLONEDDS_URI=file:///path/to/cyclonedds.xml。
3. 宇树 L1 雷达的室外感知局限
- 现象:在正午强光照下,或者穿过大片低矮灌木草坪时,自带的 L1 雷达点云噪声明显增多,机器狗频繁误报前方有障碍物而急停。
- 解法:在做避障滤波时,不要直接读取原始 PointCloud 触发刹停。必须在上位机做基于高度的 PassThrough 滤波(忽略地面 5 cm 以下的点),并结合时序一致性滤波(连续 3-5 帧在同一空间体素内存在障碍才判定为有效障碍)。
五、 总结
宇树 Go2 作为目前市面上极具性价比的四足平台,其本体的机械素质、高低温耐受度以及关节动力学响应在同级别里足够优秀。但要把一台裸机改造成能进园区执行日常任务的「巡检工」,工作量往往不在本体控制本身,而在于外挂设备的电气隔离、复杂光照下的多传感器融合容错、以及 DDS 网络的工程健壮性。
先理顺供电与网络拓扑,再做业务层状态机,能省下至少一半的现场排查时间。后续如果需要集成自动回充充电桩,还需要考虑视觉导引底座对接的姿态控制,那又是另一套工程细节了。
许可协议:CC BY-NC 4.0
更新于 12 小时前
觉得文章有帮助?点个赞吧!
0 条评论


