
ROS2 Humble Gazebo 加载 TurtleBot3 小车失败—— package:// 与 model:// 的坑摘要在 ROS2 Humble Gazebo classic 11 环境下用spawn_entity把 URDF 小车导入 Gazebo 时出现“小车无法正常加载/看不见车身”的问题。本文完整记录排查过程定位到package://与model://两套 URI 协议不对齐 缺少gazebo_model_path导出这一根本原因并给出两种解决方案。一、问题描述使用 ROS2 运行ros2 launch turtlebot3_sim gazebo_spawn.launch.py。现象Gazebo 能启动日志里甚至显示Successfully spawned entity [turtlebot3]但小车在 Gazebo 里无法正常加载——车身、轮子、激光雷达的视觉模型mesh都看不到只剩碰撞盒或一片空白。与此同时/odom、/scan、/imu、/joint_states、/cmd_vel等话题又都正常说明物理、关节、传感器其实都在工作。二、环境信息项版本操作系统Ubuntu 22.04内核 6.8.0ROSROS2 HumbleGazeboGazebo classic11.10.2不是新版 gz sim / Ignition相关包turtlebot3_description、turtlebot3_sim、gazebo_ros三、排查过程xacro 展开正常xacro turtlebot_burger_gazebo.urdf.xacro能正常生成 URDF无报错。robot_state_publisher 正常能发布/robot_descriptionTRANSIENT_LOCAL锁存 QoS并成功解析所有 link。spawn 服务正常日志显示SpawnEntity: Successfully spawned entity [turtlebot3]差速驱动插件、关节状态插件都正常加载。但 mesh 加载异常用gz model --info -m turtlebot3查看 Gazebo 里最终生成的 SDF发现 mesh 的路径全被改成了filename: model://turtlebot3_description/meshes/bases/burger_base.stl注意URDF 里写的明明是package://turtlebot3_description/meshes/...进 Gazebo 后却变成了model://。路径解析失败检查 Gazebo 实际使用的GAZEBO_MODEL_PATH发现里面只有官方turtlebot3_gazebo/models没有turtlebot3_description。四、根本原因问题本质是两套生态、两套 URI 协议没有对齐1.package://是 ROS 的协议model://是 Gazebo 的协议package://xxx/...由 ROS 工具robot_state_publisher、RViz通过 ament 资源索引解析。Gazebo classic不认package://它只认model://走GAZEBO_MODEL_PATH、file://、绝对路径。2. URDF 是 ROS 原生格式mesh 天然写package://URDF 本来就是给 ROS 工具链设计的mesh 路径用package://对 RViz 完全正确但对 Gazebo 就不行。3. gazebo_ros 在 URDF→SDF 转换时把package://重写成model://spawn_entity把 URDF 发给 Gazebo 后服务端libgazebo_ros_factory.so做 URDF→SDF 转换package://xxx/yyy被自动改写成model://xxx/yyy。这一步是自动且躲不掉的。4.model://靠GAZEBO_MODEL_PATH解析而它由各包 package.xml 的导出收集gazebo_ros 启动时会扫所有包的package.xml收集gazebo_ros gazebo_model_path...拼成GAZEBO_MODEL_PATH。而turtlebot3_description的package.xml没有这个导出所以它的目录不在路径里 →model://turtlebot3_description/...解析不到 → mesh 加载失败。一句话总结URDF 里写的是 ROS 的package://Gazebo 只认model://而model://又没注册路径两头落空。五、解决方案方案 A推荐一劳永逸给 description 包导出gazebo_model_path编辑turtlebot3_description/package.xml在export里加一行exportbuild_typeament_cmake/build_typegazebo_rosgazebo_model_path${prefix}/..//export说明${prefix}会被替换成install/turtlebot3_description/share/turtlebot3_description/..后正好是install/turtlebot3_description/share/这样model://turtlebot3_description/meshes/...就能解析到 mesh 文件。然后重新编译并 sourcecd~/turtlebot3 colcon buildsourceinstall/setup.bash ros2 launch turtlebot3_sim gazebo_spawn.launch.py方案 B快速验证不用重编译手动加环境变量exportGAZEBO_MODEL_PATH$GAZEBO_MODEL_PATH:~/turtlebot3/install/turtlebot3_description/share/ ros2 launch turtlebot3_sim gazebo_spawn.launch.py缺点每次开新终端都要重新设置。建议先用 B 快速验证再落地到 A。六、验证用 Gazebo 底层SystemPaths::FindFileURI验证# 不加路径修复前→ 解析不到会一直尝试联网查询卡死/找不到 # 加上 install/turtlebot3_description/share/ 之后 FindFileURI(model://turtlebot3_description/meshes/bases/burger_base.stl) /home/lzx/turtlebot3/install/turtlebot3_description/share/turtlebot3_description/meshes/bases/burger_base.stl ← FOUND修复后重新启动Gazebo 里小车车身、轮子、激光雷达的视觉模型即可正常显示。七、延伸其他人导入 Gazebo 是怎么处理的ROS2 生态里主要有这几种做法URDF 与 SDF 分离最标准官方 TurtleBot3 做法turtlebot3_description只放 URDFpackage://mesh给 RViz /robot_state_publisher用turtlebot3_gazebo另放一套 SDF 模型model://mesh给 Gazebo 用并在package.xml导出gazebo_ros gazebo_model_path${prefix}/models/。原因URDF 服务 ROS 工具链SDF 服务 Gazebo 的传感器/插件/材质等更丰富的特性两者能力不对称。给 description 包直接导出gazebo_model_path即本文方案 A适合“想复用同一套 URDF 直接进 Gazebo”。gazebo_media_path导出对应GAZEBO_RESOURCE_PATH用于贴图/材质/shadert 等 media 资源和model://网格不是一回事别混淆。手动设GAZEBO_MODEL_PATH本文方案 Bquick-fix。新版 Gazebogz sim / Ignition原生支持package://在 ROS2 下通过 ament 直接解析不再需要这套转换和路径导出但本文环境是 Gazebo classic 11用不上。八、总结现象是“小车加载不进去”但物理/传感器其实都正常缺的是视觉 mesh。根因是package://ROS→model://Gazebo的自动转换叠加gazebo_model_path未导出导致 mesh 路径解析不到。修复只需在turtlebot3_description/package.xml加一行gazebo_model_path导出即可。