Wiki
將Ign Gazebo遷移至Gz Sim
本文由簡體中文內容確定性轉換,並受版本化術語表保護。
1.將Ign Gazebo遷移至Gz Sim
(即 ROS2 Humble 遷移至 ROS2 Jazzy 及之後版本。只用 Humble 的工程也建議看一下,因為很多寫法會影響以後升級。)
ROS2 Humble 時代,新版 Gazebo 仍經常使用 Ignition / Ign Gazebo 的命名,例如命令是 ign gazebo,ROS 包名常見 ros_ign_*,外掛檔名常見 ignition-gazebo-xxx-system。
到了 ROS2 Jazzy,官方搭配的是 Gazebo Harmonic。此時命名體系基本切換為 Gazebo / Gz Sim,例如命令變成 gz sim,ROS 包名改成 ros_gz_*,外掛檔名改成 gz-sim-xxx-system。
所以從 Humble 遷移到 Jazzy 時,相容性問題最大的地方通常就是 Gazebo。介面和功能看起來差不多,但程式碼裡大量名字不互通,需要把 Ignition 時代的命名遷移到 Gz Sim / Gazebo Harmonic 寫法。
可以簡單理解為:大部分遷移不是功能重寫,而是命名體系、外掛名、launch 包名、SDF 標籤和環境變數的遷移。
官方參考:
- Gazebo Harmonic 遷移說明:https://gazebosim.org/docs/harmonic/migration_from_ignition/
- Gazebo Fuel 模型引用示例:https://gazebosim.org/docs/harmonic/fuel_insert/
- Gazebo Sensors 示例:https://gazebosim.org/docs/harmonic/sensors/
- ROS2 Gazebo Classic 遷移到新 Gazebo 的說明:https://gazebosim.org/docs/harmonic/migrating_gazebo_classic_ros2_packages/
- SDFormat Sensor 規範:https://sdformat.org/spec
1.1.遷移前先搜尋舊寫法
在工程根目錄執行:
rg -n -i "ignition|ignition-gazebo|libignition|ros_ign|ign_args|ign_version|fuel.ignitionrobotics|ignition_frame_id|<ignition-gui>|ign gazebo|ign topic|alwaysOn" src
重點檢查這些檔案:
*.sdf:world、model、GUI、外掛、Fuel URL 通常在這裡。*.urdf.xacro/*.urdf:機器人外掛、感測器標籤通常在這裡。*.launch.py:Gazebo 啟動包、啟動引數、橋接 topic 通常在這裡。package.xml:執行依賴通常在這裡。CMakeLists.txt:安裝目錄和編譯依賴通常在這裡。
建議修改時加成對中文註釋,方便以後知道從哪裡開始、到哪裡結束:
<!-- Jazzy 迁移开始:说明这里为什么要改。 -->
<plugin filename="gz-sim-physics-system" name="gz::sim::systems::Physics"/>
<!-- Jazzy 迁移结束:说明这里已经改成什么写法。 -->
1.2.SDF檔案

根據官方遷移說明,普通命名通常把 ignition / ign 換成 gz。

外掛要按新命名修改,例如:
ignition::gazebo名稱空間改為gz::simignition::改為gz::ignition-gazebo-XXX-system改為gz-sim-XXX-systemlibignition-gazebo-XXX-system.so改為gz-sim-XXX-system
常見替換表:
| Humble / Ignition 寫法 | Jazzy / Gazebo Harmonic 寫法 | 示例場景 |
|---|---|---|
ignition-gazebo-* |
gz-sim-* |
外掛檔名 |
libignition-gazebo-*.so |
gz-sim-* |
外掛檔名 |
ignition::gazebo::* |
gz::sim::* |
外掛名稱空間 |
ros_ign_* |
ros_gz_* |
ROS-Gazebo 包名 |
ign_args |
gz_args |
launch 引數 |
ign_version |
gz_version |
launch 引數 |
IGN_GAZEBO_RESOURCE_PATH |
GZ_SIM_RESOURCE_PATH |
模型/資源路徑 |
fuel.ignitionrobotics.org |
fuel.gazebosim.org |
Gazebo Fuel URL |
1.2.1.系統外掛
舊寫法:
<plugin filename="libignition-gazebo-physics-system.so"
name="ignition::gazebo::systems::Physics"/>
Jazzy / Gazebo Harmonic 寫法:
<plugin filename="gz-sim-physics-system"
name="gz::sim::systems::Physics"/>
常見系統外掛:
| 舊外掛 | 新外掛 |
|---|---|
ignition-gazebo-physics-system |
gz-sim-physics-system |
ignition-gazebo-sensors-system |
gz-sim-sensors-system |
ignition-gazebo-scene-broadcaster-system |
gz-sim-scene-broadcaster-system |
ignition-gazebo-user-commands-system |
gz-sim-user-commands-system |
ignition-gazebo-contact-system |
gz-sim-contact-system |
ignition-gazebo-diff-drive-system |
gz-sim-diff-drive-system |
ignition-gazebo-joint-state-publisher-system |
gz-sim-joint-state-publisher-system |
1.2.2.GUI 標籤
舊版 Gazebo GUI 配置可能寫:
<ignition-gui>
<property type="string" key="state">docked</property>
</ignition-gui>
Jazzy / Gazebo Harmonic 改成:
<gz-gui>
<property type="string" key="state">docked</property>
</gz-gui>
可以用下面命令檢查:
rg -n "<ignition-gui>|</ignition-gui>" src
1.3.URDF / Xacro 裡的 Gazebo 感測器
感測器部分是 Jazzy 遷移時最容易留下 warning 的地方。
1.3.1.alwaysOn 改為 always_on
舊寫法:
<alwaysOn>true</alwaysOn>
Jazzy / SDF 標準寫法:
<always_on>true</always_on>
如果不改,Gazebo 可能會提示:
XML Element[alwaysOn], child of element[sensor], not defined in SDF.
1.3.2.ignition_frame_id / gz_frame_id 與 pose relative_to
舊寫法可能是:
<ignition_frame_id>laser</ignition_frame_id>
有些 Gazebo ROS 遷移文件裡會看到:
<gz_frame_id>laser</gz_frame_id>
但是在當前 ROS2 Jazzy / Gazebo Harmonic 工具鏈裡,URDF 轉 SDF 通常會輸出 SDF 1.11,而 SDF 1.11 沒有標準 <gz_frame_id> 元素。因此啟動時可能會出現:
XML Element[gz_frame_id], child of element[sensor], not defined in SDF. Copying[gz_frame_id] as children of [sensor].
但是這個警告說實話,是警告,但實際上這個標籤是生效的,必須要使用這個標籤,請忽略那些警告。
然後你也可以再加上一個下面這個pose relative_to標籤,這是官方示例裡給的。
<pose relative_to="laser">0 0 0 0 0 0</pose>
相機示例:
<sensor name="cam_link" type="camera">
<update_rate>10.0</update_rate>
<always_on>true</always_on>
<pose relative_to="camera">0 0 0 0 0 0</pose>
<gz_frame_id>camera</gz_frame_id>
<topic>/image_raw</topic>
<camera name="my_camera">
...
</camera>
</sensor>
雷達示例:
<sensor name="gpu_lidar" type="gpu_lidar">
<topic>scan</topic>
<update_rate>30</update_rate>
<always_on>true</always_on>
<visualize>true</visualize>
<pose relative_to="laser">0 0 0 0 0 0</pose>
<gz_frame_id>laser</gz_frame_id>
<lidar>
...
</lidar>
</sensor>
注意:pose relative_to 和 gz_frame_id 不是同一個概念。
pose relative_to:表示感測器的位姿相對於哪個 link/frame,解決“感測器放在哪裡”的問題。gz_frame_id:嘗試指定感測器訊息裡的 frame id,解決“訊息 header.frame_id 寫什麼”的問題。
建議同時採用 pose relative_to 和 <gz_frame_id>。


1.4.Launch 檔案
Jazzy 使用 ros_gz_sim 啟動 Gazebo,不再使用舊的 ros_ign_gazebo / ros_ign。
舊思路常見是:
pkg_ros_ign_gazebo = get_package_share_directory("ros_ign_gazebo")
Jazzy 推薦:
pkg_ros_gz_sim = get_package_share_directory("ros_gz_sim")
啟動 Gazebo 的 launch 寫法:
gz_sim = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(pkg_ros_gz_sim, "launch", "gz_sim.launch.py")),
launch_arguments={
"gz_args": "-r " + world_file
}.items(),
)
注意引數名也要改:
| Humble / Ignition | Jazzy / Gazebo Harmonic |
|---|---|
ign_args |
gz_args |
ign_version |
gz_version |
如果要 spawn URDF / robot_description,Jazzy 使用:
spawn = Node(
package="ros_gz_sim",
executable="create",
arguments=[
"-name", "mycar",
"-topic", "/robot_description",
],
output="screen",
)
1.5.ROS 和 Gazebo 訊息橋接
Jazzy 使用 ros_gz_bridge:
bridge = Node(
package="ros_gz_bridge",
executable="parameter_bridge",
arguments=[
"/cmd_vel@geometry_msgs/msg/Twist@gz.msgs.Twist",
"/scan@sensor_msgs/msg/LaserScan@gz.msgs.LaserScan",
"/image_raw@sensor_msgs/msg/Image@gz.msgs.Image",
],
)
檢查點:
- ROS 包名用
ros_gz_bridge - Gazebo 訊息名稱空間用
gz.msgs.* - 如果 topic 沒有橋出來,先執行
gz topic -l看 Gazebo 側真實 topic 名稱,再改 bridge 引數
1.6.package.xml 依賴
如果 launch 檔案裡用了 ros_gz_sim 和 ros_gz_bridge,package.xml 也要宣告執行依賴:
<exec_depend>ros_gz_sim</exec_depend>
<exec_depend>ros_gz_bridge</exec_depend>
<exec_depend>geometry_msgs</exec_depend>
<exec_depend>nav_msgs</exec_depend>
<exec_depend>tf2_msgs</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<exec_depend>rosgraph_msgs</exec_depend>
如果還啟動 RViz,也補:
<exec_depend>rviz2</exec_depend>
1.7.Fuel URL 和模型路徑
舊 Fuel URL(實際上舊的連結也生效,被重定向到新連結了):
<uri>https://fuel.ignitionrobotics.org/1.0/openrobotics/models/Playground</uri>
新 Fuel URL:
<uri>https://fuel.gazebosim.org/1.0/openrobotics/models/Playground</uri>
本地模型路徑不要盲目改。例如:
<uri>file:///home/xxx/ROS_WS/ign_models/bed</uri>
這裡的 ign_models 可能只是自己建的資料夾名,不是 Gazebo API 名稱。只要這個目錄真實存在,就可以保留。
如果想改成更通用的模型路徑,可以設定下面這個宏,宏從IGN_GAZEBO_RESOURCE_PATH修改為GZ_SIM_RESOURCE_PATH:
export GZ_SIM_RESOURCE_PATH=/path/to/model_parent
然後 SDF 中寫:
<uri>model://bed</uri>
1.8.命令列遷移
| Humble / Ignition 命令 | Jazzy / Gazebo Harmonic 命令 |
|---|---|
ign gazebo world.sdf |
gz sim world.sdf |
ign gazebo -r world.sdf |
gz sim -r world.sdf |
ign topic -l |
gz topic -l |
ign topic -e -t /scan |
gz topic -e -t /scan |
ROS launch 仍然用:
ros2 launch 包名 launch文件.py
1.9.遷移後的驗證順序
1.9.1.1. 檢查 XML / SDF 是否合法
xmllint --noout src/demo_gazebo_sim/world/house.sdf
xmllint --noout src/demo_gazebo_sim/world/visualize_lidar.sdf
xmllint --noout src/mycar_description/urdf/xacro/gazebo_sensor.urdf.xacro
1.9.2.2. 檢查 xacro 是否能生成 URDF
source /opt/ros/jazzy/setup.bash
xacro src/mycar_description/urdf/xacro/car.urdf.xacro -o /tmp/car_check.urdf
1.9.3.3. 檢查 Gazebo 轉 SDF 是否還有 warning
gz sdf -p /tmp/car_check.urdf
如果還有 gz_frame_id 或 alwaysOn warning,就回到感測器部分繼續改。
1.9.4.4. 構建工程
colcon build --symlink-install
source install/setup.bash
1.9.5.5. 啟動 Gazebo
ros2 launch demo_gazebo_sim gazebo_sim_world.launch.py
ros2 launch demo_gazebo_sim gazebo_sim_robot_world.launch.py
也可以只跑 Gazebo server 做快速檢查:
gz sim -s -r -v 2 src/demo_gazebo_sim/world/house.sdf --iterations 1
1.10.常見錯誤排查
1.10.1.外掛找不到
檢查是否還寫著:
ignition-gazebo-*
libignition-gazebo-*.so
ignition::gazebo::systems::*
Jazzy 應該改成:
gz-sim-*-system
gz::sim::systems::*
1.10.2.GUI 標籤 warning
檢查是否還有:
<ignition-gui>
Jazzy 應該改成:
<gz-gui>
1.10.3.感測器 warning
檢查是否還有:
<alwaysOn>
<ignition_frame_id>
建議改成:
<always_on>true</always_on>
<pose relative_to="laser">0 0 0 0 0 0</pose>
<gz_frame_id>laser</gz_frame_id>
或:
<pose relative_to="camera">0 0 0 0 0 0</pose>
<gz_frame_id>camera</gz_frame_id>
1.10.4.robot_state_publisher 的 KDL 根 link 慣性警告
如果日誌出現:
The root link base_footprint has an inertia specified in the URDF, but KDL does not support a root link with an inertia.
說明 URDF 根 link 帶了 <inertial>,KDL 不支援。
1.10.5.改了 xacro 但日誌仍顯示舊內容
先確認舊 launch 已經停止:
pgrep -af "gazebo|gz sim|robot_state_publisher|parameter_bridge"
如果舊的 robot_state_publisher 還在,同一個 ROS graph 裡 ros_gz_sim create 可能會從舊的 /robot_description 拿模型。
停止舊程序後重新構建、source、啟動:
colcon build --symlink-install
source install/setup.bash
ros2 launch demo_gazebo_sim gazebo_sim_robot_world.launch.py
1.10.6.QStandardPaths / libEGL warning
如果日誌裡只剩:
QStandardPaths: runtime directory '/run/user/1000' is not owned by UID 0
libEGL warning: egl: failed to create dri2 screen
這通常不是 Gazebo 遷移錯誤,而是用 root 啟動 GUI 或顯示卡渲染環境導致的 warning。建議用普通使用者執行 ROS/Gazebo,或者檢查顯示卡驅動、Mesa、EGL 環境。
1.11.最後再掃一遍舊引用
功能性舊引用檢查:
rg -n "filename=['\"](lib)?ignition|name=['\"]ignition::gazebo|<ignition-gui>|</ignition-gui>|<ignition_frame_id>|</ignition_frame_id>|<gz_frame_id>|</gz_frame_id>|fuel\\.ignitionrobotics\\.org|ros_ign|ign_args|ign_version|alwaysOn" src
官方文件提醒的誤替換檢查:
rg -n -i "gz-gazebo|gzition|an gz" src
如果只在中文註釋或教程裡搜到舊寫法,而功能程式碼裡沒有,一般就遷移乾淨了。