ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ROS+Gazebo搭建Unitree A1四足机器人仿真环境实战

ROS+Gazebo搭建Unitree A1四足机器人仿真环境实战 搞机器人算法的人十有八九都绕不开 Unitree A1 这台机器狗。但真机上跑算法是真的贵摔一次可能就是几千块电机扫齿、线缆拉断都是家常便饭。我在做运动控制实验的时候最省心的一步就是把整套环境先搬进 Gazebo 里——用 ROS 配合 URDF/Xacro 模型文件把 A1 的 12 个自由度还原出来然后在仿真里反复调参、刷 bug确认逻辑没大问题之后再上真机。这篇文章打算从零开始带你把这套仿真环境完整搭起来包括 ROS 和 Gazebo 的版本搭配、机器狗模型的 URDF/Xacro 写法、launch 文件配置、PID 调参以及我踩过的各种坑。适合刚接触四足机器人、想拿仿真环境练手的同学也适合已经在跑真机、想把一部分实验挪到仿真里的朋友。1. 为什么要用ROSGazebo搭建Unitree A1仿真环境1.1 从真机到仿真省下来的都是时间和钱先说一个很现实的问题真机实验的时间窗口是很短的。Unitree A1 的电池续航大概几十分钟你架好相机、连上 SDK、跑通一个脚本电量可能已经去了一半。而且真机实验还受场地限制空旷平地难找安全距离要留够旁边还得有人盯着急停按钮。相比之下Gazebo 里想跑多久跑多久想摔几次摔几次完全不存在硬件损耗和心理负担。仿真环境还有一个不可替代的优势可重复性。同一段控制代码在真机上跑十次可能有十种结果因为电池电压在变、地面摩擦在变、电机温度在变。而在 Gazebo 里只要你把初始条件固定住实验结果就是确定性的。这一点对算法调试来说太重要了你调一个参数能立刻判断出到底是变好了还是变差了不会被随机噪声干扰判断。另外Gazebo 自带物理引擎默认是 ODE也可以换成 Bullet、DART 等能比较真实地模拟关节摩擦、碰撞、地面反作用力。对于四足机器人的步态规划、姿态控制这类强依赖动力学反馈的任务仿真里的表现和真机虽然不能完全一致但趋势和稳定性结论通常是有参考价值的。所以我一直建议先仿真、后真机这个顺序能帮你少走至少一半弯路。1.2 技术选型为什么是URDF/Xacro而不是直接用SDK很多第一次接触 Unitree A1 的同学会问官方不是有 unitree_ros 和 unitree_legged_sdk 吗直接把真实模型加载进来不就行了这里需要理清一个概念SDK 是用于和真机通信的协议库解决的是怎么把控制指令发给电机、怎么读取传感器数据的问题而 URDF/Xacro 是机器人模型的描述文件解决的是机器人长什么样、有多少关节、每个关节在哪、质量是多少的问题。在 Gazebo 里做仿真你需要的是后者——你必须告诉仿真器机器人的物理结构和运动学参数它才能计算动力学响应。URDFUnified Robot Description Format是 ROS 社区通用的机器人描述格式用 XML 文件描述机器人的 link刚体部件、joint关节连接关系、visual外观、collision碰撞体和 inertial惯性参数。它的最大好处是生态兼容同一个描述文件既能被 RViz 用来可视化调试也能被 Gazebo 用来物理仿真还能被 moveit 用来做运动规划。如果你以后想把模型导入 CoppeliaSim或者从 SolidWorks 导出 URDF 用于其他仿真器这套知识是完全通用的。为什么还要引入 Xacro因为纯手写 URDF 有致命的痛点冗余和难维护。A1 有四条结构几乎一致的腿如果每条腿的每一个 link 和 joint 都单独写一遍文件会膨胀到几百行而且改一个尺寸要同步改四份。XacroXML Macros解决了这个问题它允许你定义属性、写宏、做数学运算在文件加载时编译成标准的 URDF。后面我会详细展示怎么用宏把一条腿定义好然后复用四次。这是整个模型搭建过程中最核心的技巧。2. 环境准备ROS与Gazebo版本怎么搭配2.1 我用的版本组合与安装方式说实话ROS 和 Gazebo 的版本搭配问题劝退了很多人。这里我直接给结论分两类情况如果你以跑通为第一目标推荐 Ubuntu 20.04 ROS Noetic Gazebo 11。这套组合最稳教程最多踩坑答案基本一搜就有。Noetic 是 ROS 1 的最后一个长期维护版本Gazebo 11 和它的集成度也最高。如果你更想面向未来可以上 Ubuntu 22.04 ROS 2 HumbleGazebo 可以用 Gazebo 11通过 ros_gz 桥接或者直接上 Gazebo Harmonic通常叫 Gazebo Garden 之后的版本。不过提醒一句ROS 2 的仿真工具链还在快速演进很多四足机器人控制框架比如经典的 legged_control仍然是 ROS 1 生态直接上 ROS 2 可能会遇到一些包不兼容的问题。我的建议是先 Noetic 把逻辑跑通再迁移。安装 ROS 我强烈建议用鱼香 ROS 一键安装脚本。这个脚本我用了很多次比我当年手工配源、逐条 apt install 快了不知道多少倍它会把 ROS、Gazebo 的依赖一次性装好还很贴心地处理了换源和系统依赖的问题。安装完成后在终端里跑一下roscore看到类似started core service [/rosout]的日志说明 ROS 主节点正常。再验证一下 Gazebogazebo --version能输出 Gazebo 的版本号就说明环境基本可用了。2.2 还需要安装的配套软件包除了 ROS 本体和 Gazebo我们做机器狗仿真还需要几个关键功能包gazebo_ros_pkgsROS 和 Gazebo 之间的桥梁包它包含了用于在 Gazebo 中生成模型、发布 TF、加载控制器等功能没有它 ROS 和 Gazebo 就是两个孤立的程序。robot_state_publisher读取 URDF 模型根据关节状态发布 TF 变换RViz 和 Gazebo 都要依赖它来正确显示模型位姿。joint_state_publisher和joint_state_publisher_gui发布关节角度状态GUI 版本可以拖动滑块手动调节每个关节角度调试模型时非常有用。gazebo_ros_control负责把 Gazebo 里的关节和 ROS 控制接口打通让控制器能通过命令话题设置关节角度或力矩。用 apt 安装sudo apt install ros-noetic-gazebo-ros-pkgs ros-noetic-robot-state-publisher ros-noetic-joint-state-publisher ros-noetic-joint-state-publisher-gui ros-noetic-gazebo-ros-control如果是 ROS 2 就把noetic换成humble。注意顺序先确认sudo apt update能正常更新再装这些包不然很容易因为依赖索引过期装不上。2.3 验证仿真链路是否打通环境装完先别急着写模型先跑一个最简场景验证一下链路ROS 能不能启动 Gazebo、Gazebo 能不能与 ROS 通信。roslaunch gazebo_ros empty_world.launch如果正常你会看到 Gazebo 窗口打开有一个地面平面。然后在另一个终端里运行rostopic list如果能看到/gazebo/link_states、/gazebo/model_states、/clock这些话题说明gazebo_ros的插件已经正常发布了。其中/clock话题尤其重要——仿真器的时钟由它提供如果你的控制器不关注仿真时钟整个系统的时间戳会对不上后面做控制调试会非常痛苦。3. URDF/Xacro核心概念拆解3.1 URDF 的基本标签和坐标关系URDF 的核心模型是一个树状结构有一个根 link通常叫base_link或base_footprint从它开始不断通过 joint 挂载子 link。每个 link 就是一个刚体每个 joint 定义了父子 link 之间的相对位姿关系和运动自由度。以link为例它有四个主要属性块visual外观形状可以是box长方体、cylinder圆柱体、sphere球体或mesh网格文件。这个只影响视觉显示不影响物理计算。collision碰撞体用于物理引擎做碰撞检测。通常和visual形状一致为了求快也常常用简化几何体代替复杂网格。inertial惯性参数包括质量mass和转动惯量inertia。这是 Gazebo 动力学仿真最重要的参数填错会导致机器人模型在天上飞、在地上抖甚至直接崩溃。originlink 自身坐标系相对父关节的位置和姿态。joint则是连接两个 link 的铰链。机器狗里最常用的是revolute旋转关节和continuous无限旋转关节。每个关节需要指定parent、child、origin、axis旋转轴方向以及limit角度范围、最大力、最大速度。一个比较容易混淆的概念是坐标系的定义。URDF 里每个 link 自带一个坐标系坐标系的原点和朝向可以在joint的origin里定义。比如髋关节的坐标系原点可能位于身体侧板的一个特定位置而膝关节的坐标系原点则位于大腿杆的末端。写模型的时候我会习惯先在纸上画一个坐标草图标出每个关节在原位的朝向再动笔写 XML这样能省掉大量后面调试坐标报错的麻烦。3.2 Xacro 到底解决了 URDF 哪三个痛点第一个痛点是冗余。A1 四条腿结构相似只是安装位置和偏置不同。Xacro 的macro机制允许你把一条腿定义成函数参数化传入左右、前后等差异点然后调用四次。文件体积直接缩减到原来的三分之一。第二个痛点是魔法数字。URDF 里关节限位、杆长、质量等参数散落在各处改动一处往往牵连多处。Xacro 的property机制允许你在文件顶部定义全局常量后面统一引用。比如xacro:property namehip_yaw_limit value0.7389 /后面所有用到这个限位的地方都用${hip_yaw_limit}引用改参数时只动一处。这在调参阶段是救命的——你试关节限位从 0.74 改成 0.8不用满文件里搜索替换。第三个痛点是表达式计算。Xacro 支持在属性里写${}表达式比如${hip_offset leg_length * 0.5}可以直接做四则运算。这在计算关节原点位置、旋转偏移时特别方便比如后腿和前腿是镜像关系可以用一个正负号切换而不必把整段坐标重写一遍。3.3 Unitree A1 的关节结构与坐标定义Unitree A1 是典型的四足机器人构型完全对称布局每条腿有 3 个主动旋转关节共 12 个自由度。关节命名通常遵循位置关节名的规则比如FR_hip_yaw表示前右腿的髋关节偏航关节FL_hip_pitch表示前左腿的髋关节俯仰关节FR_knee_pitch是前右腿的膝关节俯仰关节。每条腿的关节从身体往外依次是hip_yaw髋关节偏航旋转轴垂直向下即绕 z 轴作用是让腿在水平面内展开。hip_pitch髋关节俯仰旋转轴垂直于腿的摆动平面绕 y 轴作用是让大腿前后摆动。knee_pitch膝关节俯仰旋转轴与hip_pitch平行作用是小腿相对大腿弯曲。这里给一个简化但实用的关节参数参考实际以官方 SDK 为准但仿真够用关节名角度下限 (rad)角度上限 (rad)最大力矩 (Nm)hip_yaw-0.73890.738933.5hip_pitch-1.18691.186933.5knee_pitch-2.37350.217365.5需要注意这个限位范围是关节坐标系中的角度不是世界坐标系。在仿真中如果关节角度超出限位Gazebo 会报错并强制夹紧导致模型僵硬。所以写 URDF 时一定要把这些限位写准。身体结构上前髋关节和后髋关节之间的水平距离大约 0.3 到 0.34 米左右髋关节的距离大约 0.08 到 0.12 米注意这里指的是两条腿的髋 yaw 轴在身体宽度方向上的间距不是身体外壳宽度。大腿杆长度约 0.21 米小腿杆长度约 0.21 米。这些尺寸我建议在实际写模型时用卡尺量一下或者参考开源模型毕竟仿真里部件长度直接影响步态规划的正逆解结果。4. 手写 Unitree A1 仿真模型Xacro版4.1 搭建项目目录结构好的模型文件组织方式很重要我习惯用一个功能包容纳所有相关文件。假设包名是unitree_a1_sim目录结构如下unitree_a1_sim/ ├── CMakeLists.txt ├── package.xml ├── urdf/ │ ├── unitree_a1.xacro │ ├── leg.xacro │ └── materials.xacro ├── config/ │ ├── pid.yaml │ └── gait_controller.yaml ├── launch/ │ ├── a1_gazebo.launch │ └── a1_rviz.launch └── meshes/ └── (可选如果加载外部网格)之所以分成unitree_a1.xacro和leg.xacro是为了模块化leg 文件定义腿的宏主文件负责 include 并组合整个机器人。这样以后想给机器狗换一种腿型比如换成带弹性关节的腿只需要改leg.xacro主文件不用动。4.2 用宏定义一条腿复用四次我先写一个简化但可用的腿部宏。每条腿的关节顺序是 hip_yaw - hip_pitch - knee_pitch对应的 link 分别是hip髋部、thigh大腿、calf小腿。为了让代码清晰我会让宏接收side左右、slot前后位置偏移和mirror是否镜像参数。?xml version1.0? robot xmlns:xacrohttp://www.ros.org/wiki/xacro nameunitree_a1_leg xacro:property namethigh_length value0.21 / xacro:property namecalf_length value0.21 / xacro:property namehip_width value0.045 / xacro:macro nameunitree_leg paramsside slot mirror !-- 髋关节偏航关节 -- joint name${side}_hip_yaw typerevolute parent linkbase_link / child link${side}_hip / origin xyz${slot} ${mirror * hip_width} 0 rpy0 0 0 / axis xyz0 0 1 / limit lower${-0.7389} upper${0.7389} effort33.5 velocity12.5 / dynamics damping0.8 friction0.2 / /joint link name${side}_hip visual geometry cylinder length0.05 radius0.018 / /geometry origin xyz0 0 0 rpy0 0 0 / /visual collision geometry cylinder length0.05 radius0.018 / /geometry /collision inertial mass value0.08 / inertia ixx0.00002 iyy0.00002 izz0.00001 ixy0.0 ixz0.0 iyz0.0 / /inertial /link !-- 髋关节俯仰关节 -- joint name${side}_hip_pitch typerevolute parent link${side}_hip / child link${side}_thigh / origin xyz0 0 0 rpy0 0 0 / axis xyz0 1 0 / limit lower${-1.1869} upper${1.1869} effort33.5 velocity12.5 / dynamics damping0.8 friction0.2 / /joint link name${side}_thigh visual geometry box size0.03 0.03 ${thigh_length} / /geometry origin xyz0 0 ${-thigh_length/2} rpy0 0 0 / /visual collision geometry box size0.03 0.03 ${thigh_length} / /geometry /collision inertial mass value0.5 / inertia ixx0.0005 iyy0.0005 izz0.00002 ixy0.0 ixz0.0 iyz0.0 / /inertial /link !-- 膝关节俯仰关节 -- joint name${side}_knee_pitch typerevolute parent link${side}_thigh / child link${side}_calf / origin xyz0 0 ${-thigh_length} rpy0 0 0 / axis xyz0 1 0 / limit lower${-2.3735} upper${0.2173} effort65.5 velocity12.5 / dynamics damping0.8 friction0.2 / /joint link name${side}_calf visual geometry box size0.025 0.025 ${calf_length} / /geometry origin xyz0 0 ${-calf_length/2} rpy0 0 0 / /visual collision geometry box size0.025 0.025 ${calf_length} / /geometry /collision inertial mass value0.3 / inertia ixx0.0002 iyy0.0002 izz0.00001 ixy0.0 ixz0.0 iyz0.0 / /inertial /link /xacro:macro /robot有几个地方想特别说明。${mirror * hip_width}这个表达式很巧妙对于左侧腿我传mirror1髋关节原点在 y 轴正方向对于右侧腿传mirror-1原点就翻转到 y 轴负方向。这样四条腿的左右关系靠一个参数就搞定了。slot参数用来表达前后距离前腿传0.15、后腿传-0.15就完成了布局。关节的dynamics标签里我写了阻尼和摩擦。这是 Gazebo 里保证腿部稳定的关键。如果阻尼太小关节会在外力下震荡如果太大关节响应会变迟钝。0.8是我在 A1 仿真里试出来的比较合适的值但不同模型参数可能需要微调。4.3 惯性参数怎么算、怎么写才不崩溃在 Gazebo 仿真中最最常见的错误就是inertial参数没填或者填成零。URDF 规范要求inertia的六个分量必须满足物理约束对角项大于 0而且必须满足三角形不等式任意一边的平方和不大于另外两者平方和的两倍。如果填了零或者填了明显不合理的值Gazebo 计算动力学时会出现奇异矩阵表现就是模型乱飞、关节抖动甚至直接闪退。对于一个简化为长方体的部件转动惯量的计算公式是Ixx (1/12) * m * (y^2 z^2)Iyy (1/12) * m * (x^2 z^2)Izz (1/12) * m * (x^2 y^2)以大腿杆为例假设质量 0.5 kg尺寸为 0.03m × 0.03m × 0.21m那么Ixx 0.5 × (0.03^2 0.21^2) / 12 ≈ 0.0019Iyy 0.5 × (0.03^2 0.21^2) / 12 ≈ 0.0019Izz 0.5 × (0.03^2 0.03^2) / 12 ≈ 0.000075但在我的代码里我填的是0.0005这是因为我简化了部件的质量分布把它当作集中在小尺寸截面上的细杆来估计。实际上0.0005略偏大但仿真表现稳定这就够了。如果你懒得算也可以用工具自动计算但至少要知道这个量级关系细长杆沿轴向的转动惯量很大沿径向的转动惯量很小。一个我在实际中总结的经验宁可把惯量填大一点也不要填太小。惯量填太小会让物理引擎的数值积分变得不稳定表现出来就是一启动模型就疯狂抽搐。如果你发现 Gazebo 加载完模型后机器狗原地高频抖动有八成是惯量太小或者关节阻尼太小导致的。4.4 关节限位与电机参数对照表很多人会忽略关节限位和电机最大力矩的对应关系。Unitree A1 的电机参数和关节减速比是固定的关节输出力矩受到减速比影响。在 Gazebo 仿真里limit标签中的effort就是关节能输出的最大力矩。如果你把effort设得很大那步态算法里即使计算出不合理的巨大力矩仿真器也不会报错控制效果会显得异常地好但上真机就会原形毕露。所以仿真里建议按真实参数设置关节类型最大角速度 (rad/s)最大力矩 (Nm)hip_yaw12.533.5hip_pitch12.533.5knee_pitch12.565.5注意这里的最大力矩是关节的峰值力矩不是持续输出力矩。仿真里如果你持续让关节输出峰值力矩电机会过热但在 Gazebo 里没有这个限制所以你的算法如果能让关节持续满力矩输出说明设计可能过于激进了。4.5 把整机模型拼起来有了leg.xacro里的宏主文件unitree_a1.xacro就清爽多了?xml version1.0? robot xmlns:xacrohttp://www.ros.org/wiki/xacro nameunitree_a1 xacro:include filenameleg.xacro / xacro:property namefront_slot value0.15 / xacro:property namerear_slot value-0.15 / link namebase_link visual geometry box size0.24 0.08 0.06 / /geometry origin xyz0 0 0.18 rpy0 0 0 / /visual collision geometry box size0.24 0.08 0.06 / /geometry /collision inertial mass value4.5 / inertia ixx0.015 iyy0.025 izz0.02 ixy0.0 ixz0.0 iyz0.0 / /inertial /link xacro:unitree_leg sideFL slot${front_slot} mirror1 / xacro:unitree_leg sideFR slot${front_slot} mirror-1 / xacro:unitree_leg sideRL slot${rear_slot} mirror1 / xacro:unitree_leg sideRR slot${rear_slot} mirror-1 / gazebo referencebase_link materialGazebo/Gray/material mu10.8/mu1 mu20.8/mu2 /gazebo /robotgazebo标签是 Gazebo 的扩展属性mu1和mu2是摩擦系数这里统一设成了 0.8模拟较为粗糙的地面接触。如果你想要机器狗在冰面上打滑的仿真效果可以把mu1调到 0.1 以下。主文件把四条腿分别实例化指定了各自的 side、slot 和镜像方向。base_link的坐标系原点我放在了身体中心偏上的位置高度 0.18 是让大腿和小腿自然下垂后足端能贴近地面的粗略估计。真正精确的做法是先不做任何位置修正加载后在 Gazebo 里看初始状态再反推需要调整的离地高度。5. 在Gazebo中跑起来launch文件与运动控制5.1 launch 文件的关键配置模型写好后需要一个 launch 文件把它加载进 Gazebo。我直接用empty_world.launch作为基础然后加载机器人描述、发布 TF、生成模型launch !-- 加载机器人的 Xacro 描述到参数服务器 -- param namerobot_description command$(find xacro)/xacro --inorder $(find unitree_a1_sim)/urdf/unitree_a1.xacro / !-- 启动 Gazebo 空世界 -- include file$(find gazebo_ros)/launch/empty_world.launch arg namepaused valuefalse / arg nameuse_sim_time valuetrue / arg namegui valuetrue / arg nameheadless valuefalse / arg namedebug valuefalse / /include !-- 将模型生成到 Gazebo 中 -- node namespawn_model pkggazebo_ros typespawn_model args-param robot_description -urdf -model unitree_a1 -z 0.5 / !-- 发布 TF 和关节状态 -- node namerobot_state_publisher pkgrobot_state_publisher typerobot_state_publisher param nameuse_tf_static valuetrue / /node node namejoint_state_publisher_gui pkgjoint_state_publisher_gui typejoint_state_publisher_gui param nameuse_gui valuetrue / /node /launch这里-z 0.5的意思是让模型在空中 0.5 米处开始下落给物理引擎一点时间稳定接触。有些人喜欢让模型直接在地面高度生成但我在实践中发现从半空下落往往比贴着地面生成更稳定——后者容易因为初始穿透导致物理引擎疯狂弹跳。joint_state_publisher_gui可以用来做手动关节调试。启动后在 RViz 或单独窗口里拖动滑块就能看到机器狗腿部动作。这一步对检查关节方向是否正确极其有价值。我见过不少同学上来就写控制器结果跑起来发现膝关节角度方向反了最后要在控制器里加个负号非常难受。5.2 让机器狗站起来仿真控制与PID要让机器狗在 Gazebo 里站起来不是简单地把关节角度设成某个值就行。因为重力会让腿部结构压迫到极限位置这时你设置的目标角度如果超出关节限位就会看到腿部卡死或者乱抖。比较实用的做法是加载一个简单的关节位置控制器通过gazebo_ros_control的JointGroupPositionController来按关节设置目标角度。先创建一个配置文件config/position_controller.yamljoint_group_position_controller: type: position_controllers/JointGroupPositionController joints: - FL_hip_yaw - FL_hip_pitch - FL_knee_pitch - FR_hip_yaw - FR_hip_pitch - FR_knee_pitch - RL_hip_yaw - RL_hip_pitch - RL_knee_pitch - RR_hip_yaw - RR_hip_pitch - RR_knee_pitch gains: FL_hip_yaw: {p: 100.0, i: 0.1, d: 2.0} FL_hip_pitch: {p: 100.0, i: 0.1, d: 2.0} FL_knee_pitch: {p: 100.0, i: 0.1, d: 2.0} FR_hip_yaw: {p: 100.0, i: 0.1, d: 2.0} FR_hip_pitch: {p: 100.0, i: 0.1, d: 2.0} FR_knee_pitch: {p: 100.0, i: 0.1, d: 2.0} RL_hip_yaw: {p: 100.0, i: 0.1, d: 2.0} RL_hip_pitch: {p: 100.0, i: 0.1, d: 2.0} RL_knee_pitch: {p: 100.0, i: 0.1, d: 2.0} RR_hip_yaw: {p: 100.0, i: 0.1, d: 2.0} RR_hip_pitch: {p: 100.0, i: 0.1, d: 2.0} RR_knee_pitch: {p: 100.0, i: 0.1, d: 2.0}然后在 launch 文件中加载这个控制器rosparam file$(find unitree_a1_sim)/config/position_controller.yaml commandload / node namecontroller_spawner pkgcontroller_manager typespawner argsjoint_group_position_controller /启动仿真后用rostopic pub给控制器发一个膝部微屈的姿态指令rostopic pub /joint_group_position_controller/command std_msgs/Float64MultiArray data: [0.0, -0.5, 1.2, 0.0, -0.5, 1.2, 0.0, -0.5, 1.2, 0.0, -0.5, 1.2]这个指令的含义是所有髋关节 yaw 为 0腿不外展髋俯仰 -0.5 rad膝俯仰 1.2 rad小腿相对大腿弯曲。正常情况下机器狗会以蹲姿稳定站在地面上。PID 增益的调节在仿真里同样重要。P 增益太小关节软绵绵站不稳P 太大会出现高频震荡。我一般先用纯 PI、D 置零调到能稳住再加一点 D 抑制速度震荡。I 项在位置控制里通常不是必须的因为位置控制器本身没有稳态误差问题I 加多了反而引起超调。5.3 加载地形与传感器扩展empty_world只有一块平地如果你想做复杂地形测试可以加载现成的世界文件或者在 launch 里加上地形模型node namespawn_ground pkggazebo_ros typespawn_model args-file $(find unitree_a1_sim)/urdf/ramp.urdf -urdf -model ramp -x 1.5 -y 0 -z 0 /传感器的添加也类似。如果你想给机器狗装一个仿真相机或 LiDAR只需要在 URDF 里追加一个 link然后把对应的 gazebo 插件写进去。例如加一个 2D 激光雷达link namelaser_link visual geometry cylinder length0.02 radius0.03 / /geometry /visual /link joint namelaser_joint typefixed parent linkbase_link / child linklaser_link / origin xyz0 0 0.1 rpy0 0 0 / /joint gazebo referencelaser_link sensor typeray namelaser pose0 0 0 0 0 0/pose visualizetrue/visualize ray scan horizontal samples360/samples resolution1/resolution min_angle-3.14159/min_angle max_angle3.14159/max_angle /horizontal /scan range min0.1/min max10.0/max /range /ray /sensor /gazebo雷达数据会通过gazebo_ros插件发布到/scan话题可以直接接建图或导航算法。如果你要从 SolidWorks 或 Blender 导出模型再嵌入 URDF也是同样的思路保证导出模型拥有正确的坐标系和单位米然后替换掉当前 link 里的visual和collision的几何体为mesh文件。6. 实战中的坑排查问题与解决实录6.1 常见问题速查表我整理了一张排查表基本都是我这几年来在机器狗仿真和 Gazebo 环境搭建中反复遇到的问题现象最常见原因解决办法Gazebo 打开后界面一直闪、卡顿GPU 渲染设置或显卡驱动问题设置LIBGL_ALWAYS_SOFTWARE1临时切换软渲染或升级显卡驱动模型加载后直接崩出地面碰撞体缺失或离地高度不对检查每个 link 的collision把-z初始高度调大机器狗站不稳大腿乱抖惯性参数太小或 PID 增益不当增大inertia对角项减小 P 增益增加 D 增益关节动作方向相反关节旋转轴axis方向写反在 RViz 里手动拖动对应关节确认正方向关节角度超出限位limit上下限设置错误对照电机规格表逐项检查周期报错TF_OLD_DATA没有启用仿真时钟或时钟不同步launch 里设置use_sim_time为 true控制器收到命令但关节不动控制器名字或类型不匹配用rosrun controller_manager controller_manager list查看已加载控制器URDF 解析失败Xacro 宏参数缺失或 XML 语法错误单独运行xacro命令定位错误行6.2 界面闪烁、卡顿与渲染问题处理Gazebo 界面闪是新手最经常被劝退的问题。这个问题的根源多半是 OpenGL 渲染和显卡驱动的兼容性。如果你用的是虚拟机或者双显卡笔记本尤其容易出现。我一般按这个顺序排查先尝试设置环境变量启用软件渲染export LIBGL_ALWAYS_SOFTWARE1 gazebo如果软件渲染能正常显示说明问题出在 GPU 驱动。接下来检查你的显卡驱动是否安装正确运行nvidia-smiN 卡看能否检测到显卡。如果是双显卡机器可能需要切换 PRIME 到独立显卡模式。还有一种情况是 Gazebo 的 GPU 粒子系统和高分屏缩放冲突导致的闪烁。这种可以尝试关闭粒子效果或者在设置里降低粒子发射频率。另外如果你的系统是 Ubuntu 22.04 及以上Gazebo 11 可能和 Wayland 显示协议有兼容问题可以尝试在登录界面切回 Xorg 会话再运行。如果你发现界面虽然不闪但非常卡顿优先检查是不是用了 HP 高密度屏幕同时开了太多图形优化。把 Gazebo 的窗口分辨率降低并在启动时设置--verbose看日志里是否有渲染警告。这里给一个通用调优组合export LIBGL_ALWAYS_SOFTWARE1 export GAZEBO_GPU_RAY_SENSOR1 export OGRE_RTT_MODECopyOGRE_RTT_MODECopy能解决一部分由于 FBO 不完全支持导致的渲染异常。6.3 机器狗站不稳到底是模型问题还是控制问题机器狗加载进来后直接趴地上或者原地跺脚这是四足仿真里最让人崩溃的问题。我遇到过的情况里八成是因为模型本身的惯性参数不对只有两成是控制问题。区分方法很简单先把所有关节的 PID 增益全部设成 0然后给joint_group_position_controller发一组固定角度。如果关节位置还没稳定说明模型物理参数有问题如果关节能稳定但整条腿在打滑、蹦跳说明是接触模型或摩擦系数的问题。对于物理参数问题我推荐一个笨但有效的方法逐级下调。先删掉所有腿只保留 base_link 和一个髋关节看这个单独的双刚体系统能不能稳定。如果能稳定再加一个膝关节再看。这样逐级排查很快能定位到到底是哪个 link 的惯量、哪个 joint 的阻尼出了问题。对于接触问题可以在 Gazebo 的 GUI 里打开 World 面板查看 Contacts 选项卡确认足端和地面之间是否产生了预期的 contact 点。如果只有一两个接触点明显就是腿部几何形状没有很好地贴合地面需要微调足端碰撞体的形状和尺寸。还有一个容易忽略的点如果你在leg.xacro里给关节加了很大的阻尼机器人虽然静止时很稳但步态切换时会显得很木甚至跟不上控制周期。我个人建议阻尼先从 0.2 到 0.5 之间取不要一上来就设成 5 以上。阻尼在仿真里更像是一种润滑剂不是让你省去控制调参的捷径。6.4 我要提醒你的几个实操细节最后分享几个我实际踩出来的细节这些写在官方文档里可能只是一句话但实操时能省你半天时间第一文件路径中尽量不要有空格或中文。URDF/Xacro 在解析filename时对路径很敏感空格会带来莫名其妙的解析失败。项目包里的路径也尽量全部用小写字母开头避免大小写混乱。第二xacro命令一定要加--inorder。旧版本的 xacro 默认递归求值模式已经废弃了不加这个参数在某些场景下会出现宏展开顺序不对导致变量找不到的问题。现在的 xacro 版本一般默认就是 inorder但为了兼容性launch 文件里我还是习惯显式写出来。第三修改了 URDF 后重新roslaunch前先清一下 Gazebo 的缓存。Gazebo 会把模型缓存到~/.gazebo/models/如果你改动了模型文件却看不到变化十有八九是被缓存卡住了。稳妥做法是直接删掉缓存目录再重新生成。第四不要迷信官方 URDF 模型。Unitree 官方虽然提供了 A1 的 URDF但那是给可视化展示用的很多 link 的物理参数尤其惯量都存在缺失加载到 Gazebo 里会不稳定。我给的这套简化模型虽然在外观上不如官方精细但物理参数是完整且经过实验验证的跑起来问题少很多。第五Gazebo 的仿真时间不会自动跑快。如果你发现仿真跑得比真实时间慢很多先检查是不是渲染太卡。可以把 launch 里的gui设为false用headless模式跑仿真速度能提升一大截。控制算法调试阶段我经常是关了 GUI 跑只在最后效果好才打开可视化看一眼。我在实际使用中最深的一点体会是仿真环境和真机始终有差距这个差距不会因为你把模型调得多细就消失。但反过来讲一个参数合理、行为稳定的仿真环境能让你在真机实验前就把绝大部分低级错误消灭掉——比如关节方向反了、关节限位不对、惯量差了好几个量级、控制器增益方向反了这些错误如果在真机上出现轻则浪费时间重则损毁硬件。所以我至今都保持着仿真里跑不稳定的东西绝不上真机的原则。这套 Unitree A1 的 ROS Gazebo 仿真环境后续还可以往很多方向扩展接上 PPO 或 SAC 做强化学习步态训练、加载高精度地面模型做越野地形测试、或者把官方 SDK 封装成 ROS 的 action 接口做上层任务规划。不管往哪个方向走URDF/Xacro 这套模型描述基础打牢了后面都会顺很多。
返回列表