宇树G1机器人ROS 2通信开发和使用
宇树G1机器人ROS 2通信开发的核心逻辑,是基于“环境配置-源码编译-连接搭建-驱动启动-功能开发”的全流程标准化范式,通过ROS 2的话题、服务通信机制,实现上位机与机器人的双向数据交互。核心要点可归纳为三点:一是环境适配,必须严格匹配Ubuntu 20.04/22.04与ROS 2 Humble版本,避免兼容性问题;二是通信链路验证,驱动启动后需优先通过topic/list、service/
一、核心概述
宇树G1机器人ROS 2通信开发的核心,是基于ROS 2 Humble框架构建上位机与机器人之间的高可靠通信链路,实现机器人状态感知、运动指令下发、模式切换等核心功能。官方提供的ROS 2通信例程深度适配Ubuntu 20.04/22.04系统,涵盖环境配置、驱动部署、话题通信、服务调用等全流程开发环节,为机器人的二次开发与场景落地提供了标准化的技术支撑。
二、详细使用步骤
步骤1:环境准备
1.1 系统与ROS 2版本要求
-
操作系统:Ubuntu 20.04(Focal)或Ubuntu 22.04(Jammy)
-
ROS 2版本:Humble Hawksbill(官方推荐,兼容性最优)
-
依赖工具:git、cmake、colcon、python3-pip
1.2 基础环境安装
# 1. 安装基础依赖工具
sudo apt update && sudo apt install -y git cmake build-essential python3-colcon-common-extensions python3-pip
# 2. 安装ROS 2 Humble(若未安装,参考官方标准流程)
# 导入ROS 2密钥与软件源
sudo apt install -y curl gnupg lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
# 安装桌面版(含可视化工具)
sudo apt update && sudo apt install -y ros-humble-desktop
# 3. 配置ROS 2环境变量(永久生效)
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc
# 4. 安装宇树G1专属驱动依赖
pip3 install transforms3d pyserial
sudo apt install -y ros-humble-rosbridge-suite ros-humble-tf2-tools ros-humble-robot-state-publisher
步骤2:获取G1 ROS 2源码与工作空间构建
2.1 创建并初始化ROS 2工作空间
# 创建工作空间目录结构
mkdir -p ~/unitree_g1_ws/src
cd ~/unitree_g1_ws/src
# 克隆宇树G1 ROS 2官方源码仓库
git clone https://github.com/unitreerobotics/unitree_ros2.git
# 切换至G1专属开发分支(以官方最新分支为准,此处为示例)
cd unitree_ros2
git checkout g1-devel
2.2 编译工作空间与环境配置
# 回到工作空间根目录
cd ~/unitree_g1_ws
# 编译工作空间(--symlink-install避免重复编译,提升效率)
colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release
# 配置工作空间环境变量(永久生效)
echo "source ~/unitree_g1_ws/install/setup.bash" >> ~/.bashrc
source ~/.bashrc
# 验证环境配置(查看G1相关功能包)
ros2 pkg list | grep unitree_g1
若输出“unitree_g1_bringup”“unitree_g1_msgs”等包名,说明环境配置成功。
步骤3:机器人与上位机通信连接搭建
3.1 两种连接方式配置
宇树G1支持有线、无线两种连接模式,可根据开发场景灵活选择:
-
有线直连(推荐开发调试,稳定性高):用网线连接上位机网口与G1机器人网口;进入上位机“网络设置”,手动配置IP为192.168.123.xxx(xxx范围11-254),子网掩码255.255.255.0,网关192.168.123.1;G1机器人默认有线IP为192.168.123.10。
-
无线连接(适合移动场景测试):开启G1机器人后,上位机搜索并连接机器人WiFi热点(默认名称:Unitree-G1-xxxx,密码:unitree123);连接成功后,上位机将自动获取192.168.1.xxx网段IP,G1默认无线IP为192.168.1.10。
3.2 连接有效性验证
# 有线连接验证(ping机器人默认IP)
ping 192.168.123.10 -c 4
# 无线连接验证(ping机器人默认IP)
# ping 192.168.1.10 -c 4
若出现“4 packets transmitted, 4 received”,说明网络连接正常;若丢包或超时,需检查IP配置、网线连接或机器人WiFi热点状态。
步骤4:G1 ROS 2核心驱动启动与通信链路验证
4.1 启动核心驱动节点
# 启动G1基础驱动(包含状态发布、指令接收、模式管理核心功能)
ros2 launch unitree_g1_bringup g1_bringup.launch.py
启动成功标志:终端无红色错误信息,持续输出“Robot state published successfully”等日志。
4.2 核心话题与服务验证
# 1. 查看G1相关所有话题
ros2 topic list | grep unitree_g1
# 核心话题说明:
# /unitree_g1/state:机器人状态话题(含电池、位姿、关节状态、里程计等)
# /unitree_g1/cmd_vel:速度控制指令话题(线速度、角速度)
# /unitree_g1/joint_cmd:关节控制指令话题(单关节/多关节角度控制)
# /unitree_g1/sensor_data:传感器数据话题(IMU、超声波等)
# 2. 查看状态话题数据(实时打印)
ros2 topic echo /unitree_g1/state -n 5 # -n 5表示只打印5条数据
# 3. 查看G1相关所有服务
ros2 service list | grep unitree_g1
# 核心服务说明:
# /unitree_g1/set_mode:机器人模式设置服务(待机/站立/行走/趴卧)
# /unitree_g1/reset_robot:机器人复位服务(关节归零、状态重置)
# /unitree_g1/set_gain:控制增益设置服务(调节运动平滑度)
步骤5:核心功能开发实战示例
5.1 示例1:速度控制(发布/cmd_vel话题)
功能说明:通过发布Twist类型消息到/cmd_vel话题,实现机器人前进、后退、旋转等基础运动控制。
代码文件路径:~/unitree_g1_ws/src/unitree_ros2/unitree_g1_examples/scripts/velocity_control.py
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
class G1VelocityController(Node):
def __init__(self):
super().__init__('g1_velocity_controller')
# 创建话题发布者,队列大小10(确保消息不丢失)
self.vel_publisher = self.create_publisher(Twist, '/unitree_g1/cmd_vel', 10)
# 定时器回调(10Hz发布频率,与机器人控制频率匹配)
self.timer = self.create_timer(0.1, self.timer_callback)
self.get_logger().info("G1速度控制节点已启动,开始下发运动指令...")
def timer_callback(self):
# 构造速度指令消息
vel_msg = Twist()
# 线速度x:0.2m/s(前进,范围:-0.5~0.5m/s,避免超阈值报错)
vel_msg.linear.x = 0.2
vel_msg.linear.y = 0.0 # G1不支持横向平移,固定为0
vel_msg.linear.z = 0.0
# 角速度z:0.1rad/s(右转,范围:-0.8~0.8rad/s)
vel_msg.angular.x = 0.0
vel_msg.angular.y = 0.0
vel_msg.angular.z = 0.1
# 发布指令
self.vel_publisher.publish(vel_msg)
self.get_logger().info(f"下发速度指令:线速度x={vel_msg.linear.x}m/s,角速度z={vel_msg.angular.z}rad/s")
def main(args=None):
rclpy.init(args=args)
controller_node = G1VelocityController()
try:
# 保持节点运行
rclpy.spin(controller_node)
except KeyboardInterrupt:
# 按下Ctrl+C时,发布停止指令
stop_msg = Twist()
controller_node.vel_publisher.publish(stop_msg)
controller_node.get_logger().info("接收到中断信号,发布停止指令,节点退出...")
finally:
# 资源清理
controller_node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
运行流程:
# 1. 赋予脚本执行权限
chmod +x ~/unitree_g1_ws/src/unitree_ros2/unitree_g1_examples/scripts/velocity_control.py
# 2. 编译新增节点(仅编译示例功能包,提升效率)
cd ~/unitree_g1_ws && colcon build --packages-select unitree_g1_examples
# 3. 启动速度控制节点(需先启动核心驱动)
ros2 run unitree_g1_examples velocity_control.py
5.2 示例2:机器人状态监控(订阅/state话题)
功能说明:订阅/unitree_g1/state话题,解析并打印机器人核心状态信息(电池电压、运动模式、实际速度等),用于开发监控模块。
代码文件路径:~/unitree_g1_ws/src/unitree_ros2/unitree_g1_examples/scripts/state_monitor.py
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
# 导入G1自定义状态消息类型(需确保unitree_g1_msgs已编译)
from unitree_g1_msgs.msg import G1State
class G1StateMonitor(Node):
def __init__(self):
super().__init__('g1_state_monitor')
# 创建话题订阅者,回调函数处理状态数据
self.state_subscriber = self.create_subscription(
G1State,
'/unitree_g1/state',
self.state_callback,
10 # 队列大小
)
self.state_subscriber # 防止变量被垃圾回收
self.get_logger().info("G1状态监控节点已启动,持续接收状态数据...")
def state_callback(self, msg):
# 解析核心状态字段
battery_volt = msg.battery_voltage # 电池电压(V,低于11.5V需充电)
robot_mode = self.parse_robot_mode(msg.robot_mode) # 解析模式含义
actual_vel_x = msg.odom.twist.twist.linear.x # 实际前进速度(m/s)
actual_ang_z = msg.odom.twist.twist.angular.z # 实际旋转角速度(rad/s)
joint_states = msg.joint_states # 关节状态(角度、速度、力矩)
# 打印核心状态信息
self.get_logger().info(
f"===== G1机器人状态 ====="
f"\n电池电压:{battery_volt:.2f}V"
f"\n当前模式:{robot_mode}"
f"\n实际线速度x:{actual_vel_x:.2f}m/s"
f"\n实际角速度z:{actual_ang_z:.2f}rad/s"
f"\n关节数量:{len(joint_states.name)}"
)
def parse_robot_mode(self, mode_val):
# 模式值解析(对应官方定义)
mode_map = {
0: "待机模式(Idle)",
1: "站立模式(Stand)",
2: "行走模式(Walk)",
3: "趴卧模式(LieDown)",
4: "复位模式(Reset)"
}
return mode_map.get(mode_val, f"未知模式({mode_val})")
def main(args=None):
rclpy.init(args=args)
monitor_node = G1StateMonitor()
try:
rclpy.spin(monitor_node)
except KeyboardInterrupt:
monitor_node.get_logger().info("状态监控节点退出...")
finally:
monitor_node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
运行流程:
# 1. 赋予执行权限
chmod +x ~/unitree_g1_ws/src/unitree_ros2/unitree_g1_examples/scripts/state_monitor.py
# 2. 编译功能包
cd ~/unitree_g1_ws && colcon build --packages-select unitree_g1_examples
# 3. 启动监控节点
ros2 run unitree_g1_examples state_monitor.py
5.3 示例3:服务调用(设置机器人站立模式)
功能说明:通过调用/unitree_g1/set_mode服务,将机器人从待机模式切换为站立模式,是运动控制的前置步骤。
代码文件路径:~/unitree_g1_ws/src/unitree_ros2/unitree_g1_examples/scripts/set_stand_mode.py
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
# 导入G1模式设置服务类型
from unitree_g1_msgs.srv import SetMode
class G1StandModeSetter(Node):
def __init__(self):
super().__init__('g1_stand_mode_setter')
# 创建服务客户端,指定服务名与服务类型
self.set_mode_client = self.create_client(SetMode, '/unitree_g1/set_mode')
# 等待服务端就绪(超时5秒,避免无限等待)
while not self.set_mode_client.wait_for_service(timeout_sec=5.0):
self.get_logger().warn("/unitree_g1/set_mode服务未就绪,等待中...")
self.get_logger().info("/unitree_g1/set_mode服务已就绪,准备发送站立模式请求...")
def send_stand_request(self):
# 构造服务请求(mode=1对应站立模式)
request = SetMode.Request()
request.mode = 1 # 模式定义:0=待机,1=站立,2=行走,3=趴卧
# 发送异步请求并等待结果
future = self.set_mode_client.call_async(request)
rclpy.spin_until_future_complete(self, future)
# 处理服务响应
if future.done():
try:
response = future.result()
if response.success:
self.get_logger().info("机器人站立模式设置成功!")
else:
self.get_logger().error("机器人站立模式设置失败,响应状态:失败")
except Exception as e:
self.get_logger().error(f"调用服务失败:{str(e)}")
def main(args=None):
rclpy.init(args=args)
mode_setter = G1StandModeSetter()
# 发送站立模式请求
mode_setter.send_stand_request()
# 资源清理
mode_setter.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
运行流程:
# 1. 赋予执行权限
chmod +x ~/unitree_g1_ws/src/unitree_ros2/unitree_g1_examples/scripts/set_stand_mode.py
# 2. 编译功能包
cd ~/unitree_g1_ws && colcon build --packages-select unitree_g1_examples
# 3. 启动服务调用节点(需先启动核心驱动)
ros2 run unitree_g1_examples set_stand_mode.py
三、常见问题与解决方案
问题1:驱动启动失败,提示“找不到unitree_g1_bringup功能包”
核心原因:工作空间未编译成功、环境变量未配置或配置错误。
解决方案:
-
检查工作空间编译日志:进入~/unitree_g1_ws,查看colcon build编译输出,若有红色错误(如依赖缺失、语法错误),根据错误信息补全依赖(如sudo apt install 缺失的包),重新编译;
-
验证环境变量:执行echo $ROS_PACKAGE_PATH,查看输出是否包含“~/unitree_g1_ws/install/share”,若未包含,重新执行source /unitree_g1_ws/install/setup.bash,或检查/.bashrc文件中是否添加了该环境变量(可通过cat ~/.bashrc查看);
-
若环境变量配置正确仍报错,删除build、install、log三个编译目录,重新编译:rm -rf build install log && colcon build --symlink-install。
问题2:话题无数据(ros2 topic echo无输出)或话题不存在
核心原因:驱动节点未正常启动、机器人未开机/未连接、话题名拼写错误。
解决方案:
-
检查驱动节点状态:执行ros2 node list,查看是否存在“/unitree_g1_node”节点,若不存在,重新启动驱动(ros2 launch unitree_g1_bringup g1_bringup.launch.py),并查看终端错误日志;
-
验证机器人连接:重新执行ping命令(如ping 192.168.123.10),确认网络连通;若机器人未开机,先开机并等待1-2分钟(机器人系统启动需要时间);
-
检查话题名:确保话题名拼写与驱动一致(区分大小写),正确话题名前缀为“/unitree_g1/”,可通过ros2 topic list | grep unitree_g1确认实际存在的话题;
-
无线连接场景特殊检查:确认上位机连接的是G1专属WiFi热点,而非其他同名网络,可重新断开WiFi并重新连接。
问题3:指令下发无响应(如发布cmd_vel后机器人不动)
核心原因:机器人未进入运动模式、指令值超安全阈值、话题发布频率不匹配。
解决方案:
-
检查机器人模式:必须先通过/set_mode服务将机器人设置为“行走模式(mode=2)”或“站立模式(mode=1)”,待机模式(mode=0)下无法响应运动指令;可通过订阅/state话题查看当前模式;
-
验证指令值范围:G1安全速度阈值为:线速度x∈[-0.5, 0.5]m/s,角速度z∈[-0.8, 0.8]rad/s,若指令值超出范围,机器人会忽略指令,需调整指令值至安全范围;
-
检查发布频率:机器人控制频率为10Hz,若发布频率过低(如1Hz),可能导致指令响应延迟或无响应,需将发布频率设置为10Hz左右(通过定时器0.1秒回调实现);
-
检查关节状态:若机器人处于趴卧模式(mode=3)或关节卡滞,运动指令也无法响应,可调用/reset_robot服务复位机器人后再测试。
问题4:编译时提示“缺少unitree_g1_msgs消息类型”
核心原因:消息功能包(unitree_g1_msgs)未编译,或编译顺序错误(先编译依赖消息的包,再编译消息包)。
解决方案:
-
单独编译消息功能包:cd ~/unitree_g1_ws && colcon build --packages-select unitree_g1_msgs,确保消息包编译成功;
-
重新编译整个工作空间:colcon build --symlink-install,让依赖消息的功能包(如unitree_g1_bringup、unitree_g1_examples)能正确找到消息类型;
-
若仍报错,删除消息包的编译产物:rm -rf install/unitree_g1_msgs log/unitree_g1_msgs,再重新编译消息包和整个工作空间。
问题5:机器人电池电压正常,但频繁掉线或通信卡顿
核心原因:网络连接不稳定、上位机防火墙拦截、机器人WiFi信号弱。
解决方案:
-
优先切换为有线连接:有线连接稳定性远高于无线,开发调试阶段建议使用有线直连;
-
关闭上位机防火墙:sudo ufw disable(Ubuntu默认防火墙关闭,若手动开启需关闭),避免防火墙拦截ROS 2通信端口;
-
优化无线连接:若必须使用无线,确保上位机与机器人距离不超过5米,无遮挡物;可重启机器人WiFi热点(重启机器人)后重新连接;
-
检查网络带宽:若同一网络下有其他设备占用大量带宽,可能导致通信卡顿,可断开其他设备后测试。
问题6:调用/set_mode服务提示“服务调用失败,连接超时”
核心原因:服务端未启动、网络连接中断、服务名错误。
解决方案:
-
确认驱动节点已启动:ros2 node list查看是否存在/unitree_g1_node,若不存在,重新启动驱动;
-
验证服务是否存在:ros2 service list | grep /unitree_g1/set_mode,确认服务存在后再调用;
-
检查网络连接:重新ping机器人IP,若丢包率高,解决网络问题(如更换网线、靠近机器人);
-
增加服务等待时间:在服务客户端代码中,将wait_for_service的超时时间从5秒改为10秒,避免服务端启动慢导致的连接超时。
问题7:ROS 2节点启动时提示“未找到Python模块transforms3d”
核心原因:未安装宇树G1驱动所需的Python依赖。
解决方案:
-
使用pip3安装缺失模块:pip3 install transforms3d pyserial(这两个是G1驱动核心Python依赖);
-
若安装后仍报错,检查Python环境:确认使用的是Python3(ROS 2 Humble默认使用Python3),执行which python3,确保pip3安装的模块路径在Python3的site-packages目录下(可通过pip3 show transforms3d查看安装路径);
-
若使用虚拟环境,需在虚拟环境中重新安装依赖,并确保启动ROS 2节点时激活了虚拟环境。
四、总结
宇树G1机器人ROS 2通信开发的核心逻辑,是基于“环境配置-源码编译-连接搭建-驱动启动-功能开发”的全流程标准化范式,通过ROS 2的话题、服务通信机制,实现上位机与机器人的双向数据交互。核心要点可归纳为三点:一是环境适配,必须严格匹配Ubuntu 20.04/22.04与ROS 2 Humble版本,避免兼容性问题;二是通信链路验证,驱动启动后需优先通过topic/list、service/list等命令确认通信基础正常;三是指令合规性,运动指令需严格遵循安全阈值,模式切换需按“待机-站立-行走”的逻辑顺序执行。
本文扩充的常见问题解决方案,覆盖了环境配置、编译构建、通信连接、功能执行等全环节高频问题,可有效降低开发调试成本。后续进阶开发(如SLAM建图、自主导航、视觉融合控制)可基于本文的基础通信框架,扩展对应的功能包(如ROS 2的slam_toolbox、nav2等),实现更复杂的机器人应用场景落地。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)