1. 项目概述
在机器人仿真开发中,将Unitree G1这样的复杂机器人模型与ROS1 Noetic环境集成是一个常见但具有挑战性的任务。本文记录了我如何通过Gazebo和RViz实现G1机器人的关节联动控制,重点解决了URDF物理参数配置、ros_control控制器集成以及RViz-Gazebo双向通信等关键技术问题。
这个方案的核心价值在于:
- 为G1机器人提供完整的仿真调试环境
- 实现RViz关节控制面板与Gazebo仿真的实时联动
- 支持两种工作模式:自由落体物理仿真和固定基座调试模式
- 提供可直接复用的配置脚本和启动文件
2. 环境准备与依赖安装
2.1 系统要求
本方案基于以下环境验证:
- Ubuntu 20.04 LTS
- ROS1 Noetic 完整桌面版
- Gazebo 11 (随ROS Noetic默认安装)
- Python 3.8
2.2 必要ROS包安装
执行以下命令安装核心依赖包:
bash复制sudo apt-get install ros-noetic-ros-control \
ros-noetic-ros-controllers \
ros-noetic-gazebo-ros-control \
ros-noetic-joint-state-publisher-gui
这些包提供了:
ros_control框架:机器人控制接口标准化gazebo_ros_control插件:Gazebo与ros_control的桥梁joint_state_publisher_gui:RViz中的可视化关节控制面板
3. URDF配置与物理参数优化
3.1 基础URDF结构调整
原始G1的URDF需要针对Gazebo仿真进行以下关键修改:
python复制# 移除世界坐标系固定锚点
for link in root.findall('link'):
if link.get('name') == 'world': root.remove(link)
for joint in root.findall('joint'):
if joint.get('name') == 'world_anchor': root.remove(joint)
# 确保存在base_link作为浮动基座
if not has_base_link:
base_link = ET.Element('link', name='base_link')
# 添加必要的惯性参数
inertial = ET.SubElement(base_link, 'inertial')
ET.SubElement(inertial, 'mass', value="0.01")
ET.SubElement(inertial, 'inertia',
ixx="0.001", ixy="0", ixz="0",
iyy="0.001", iyz="0", izz="0.001")
3.2 关键物理参数配置
不同部位的关节需要差异化的物理参数:
python复制# 腿部关节需要更强的支撑力
if "ankle" in name or "knee" in name or "hip" in name:
ET.SubElement(gz, 'mu1').text = "1.5" # 静摩擦系数
ET.SubElement(gz, 'mu2').text = "1.5" # 动摩擦系数
ET.SubElement(gz, 'kp').text = "1000000.0" # 接触刚度
ET.SubElement(gz, 'kd').text = "100.0" # 接触阻尼
注意事项:脚底接触参数直接影响站立稳定性。实际调试中发现,当
kp<500000时,机器人容易陷入地面;当kd<50时,会出现明显的弹跳现象。
4. ros_control控制器配置
4.1 控制器YAML文件生成
python复制with open(YAML_FILE, 'w') as f:
f.write(f"{PKG_NAME}:\n")
f.write(" joint_state_controller:\n")
f.write(" type: joint_state_controller/JointStateController\n")
f.write(" publish_rate: 100\n\n")
for jn in joint_names:
f.write(f" {jn}_controller:\n")
f.write(" type: position_controllers/JointPositionController\n")
f.write(f" joint: {jn}\n")
f.write(" pid: {p: 800.0, i: 0.0, d: 20.0}\n")
4.2 双级PID控制策略
本方案采用两级PID控制:
-
上层控制器:ros_control中的JointPositionController
- P=800,D=20(抑制振荡)
- 积分项I设为0避免积分饱和
-
底层物理引擎:Gazebo内置PID
yaml复制gazebo_ros_control: pid_gains: left_hip_pitch_joint: {p: 1000.0, i: 0.1, d: 50.0} right_knee_joint: {p: 1000.0, i: 0.1, d: 50.0}
调试心得:通过
rostopic echo /gazebo/link_states可以实时监控各连杆状态,当出现持续振荡时,应优先增大D值而非减小P值。
5. RViz-Gazebo桥接实现
5.1 通信桥梁设计
python复制class Bridge:
def __init__(self):
rospy.init_node('rviz_bridge')
self.pubs = {}
self.ns = "/g1_description"
rospy.Subscriber("/gui_commands", JointState, self.cb)
def cb(self, msg):
for i, n in enumerate(msg.name):
if n not in self.pubs:
self.pubs[n] = rospy.Publisher(
f"{self.ns}/{n}_controller/command",
Float64, queue_size=10)
self.pubs[n].publish(msg.position[i])
5.2 话题路由方案
xml复制<!-- RViz启动配置 -->
<node name="jsp_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui">
<remap from="/joint_states" to="/gui_commands"/>
</node>
<!-- Gazebo启动配置 -->
<node name="bridge" pkg="g1_description" type="bridge_node.py" output="screen" />
6. 两种工作模式实现
6.1 自由落体物理仿真模式
关键启动参数:
xml复制<node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model"
args="-file $(find g1_description)/urdf/g1_complete.urdf
-urdf -z 0.85 -model g1_robot
-J left_hip_pitch_joint -0.45
-J left_knee_joint 0.9
-J left_ankle_pitch_joint -0.45" />
操作提示:Gazebo启动后处于暂停状态,点击Play按钮机器人会自由下落。合理的初始关节角度配置可使机器人保持稳定蹲姿。
6.2 固定基座调试模式
通过修改URDF实现:
python复制# 添加世界坐标系固定锚点
world_link = ET.Element('link', name='world')
anchor = ET.Element('joint', name='world_anchor', type='fixed')
ET.SubElement(anchor, 'parent', link='world')
ET.SubElement(anchor, 'child', link='base_link')
ET.SubElement(anchor, 'origin', xyz="0 0 0.79", rpy="0 0 0")
# 关闭重力
ET.SubElement(gz, 'turnGravityOff').text = 'true'
7. 常见问题与解决方案
7.1 机器人倒地问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 加载后立即倒地 | 初始关节角度不合理 | 调整spawn_model中的-J参数 |
| 缓慢倾斜倒地 | 脚底摩擦力不足 | 增大mu1/mu2值(1.2-1.8) |
| 高频抖动 | PID参数不当 | 增大D值或减小P值 |
7.2 通信延迟优化
当出现明显控制延迟时:
- 检查
rosparam get /use_sim_time应为false - 增加bridge_node的发布队列大小:
python复制self.pubs[n] = rospy.Publisher(..., queue_size=50) - 在launch文件中添加:
xml复制<param name="gazebo/physics/max_step_size" value="0.001"/>
8. 进阶调试技巧
8.1 实时参数调整
安装动态调参工具:
bash复制sudo apt-get install ros-noetic-rqt-reconfigure
使用示例:
bash复制rosrun rqt_reconfigure rqt_reconfigure
可实时调整PID参数观察效果
8.2 接触力可视化
在Gazebo中开启接触力显示:
- 菜单栏选择View > Contacts
- 设置Display Interval为1(每帧更新)
- 红色线条表示接触力方向和大小
8.3 性能优化建议
对于29自由度的G1机器人:
- 在Gazebo中启用多线程物理引擎:
xml复制<physics type="ode"> <max_update_rate>1000</max_update_rate> <threads>4</threads> </physics> - 关闭不需要的传感器插件
- 使用
gzclient --verbose查看性能瓶颈
