第 11.4 節

將Ign Gazebo遷移至Gz Sim

0瀏覽次數0訪問次數--跳出率--平均停留

將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 標籤和環境變量的遷移。

官方參考:

遷移前先搜索舊寫法

在工程根目錄執行:

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 迁移结束:说明这里已经改成什么写法。 -->

SDF文件

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

插件要按新命名修改,例如:

  • ignition::gazebo 命名空間改為 gz::sim
  • ignition:: 改為 gz::
  • ignition-gazebo-XXX-system 改為 gz-sim-XXX-system
  • libignition-gazebo-XXX-system.so 改為 gz-sim-XXX-system

常見替換表:

Humble / Ignition 寫法Jazzy / Gazebo Harmonic 寫法示例場景
ignition-gazebo-*gz-sim-*插件文件名
libignition-gazebo-*.sogz-sim-*插件文件名
ignition::gazebo::*gz::sim::*插件命名空間
ros_ign_*ros_gz_*ROS-Gazebo 包名
ign_argsgz_argslaunch 參數
ign_versiongz_versionlaunch 參數
IGN_GAZEBO_RESOURCE_PATHGZ_SIM_RESOURCE_PATH模型/資源路徑
fuel.ignitionrobotics.orgfuel.gazebosim.orgGazebo Fuel URL
系統插件

舊寫法:

<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-systemgz-sim-physics-system
ignition-gazebo-sensors-systemgz-sim-sensors-system
ignition-gazebo-scene-broadcaster-systemgz-sim-scene-broadcaster-system
ignition-gazebo-user-commands-systemgz-sim-user-commands-system
ignition-gazebo-contact-systemgz-sim-contact-system
ignition-gazebo-diff-drive-systemgz-sim-diff-drive-system
ignition-gazebo-joint-state-publisher-systemgz-sim-joint-state-publisher-system
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

URDF / Xacro 裏的 Gazebo 傳感器

傳感器部分是 Jazzy 遷移時最容易留下 warning 的地方。

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.
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_togz_frame_id 不是同一個概念。

  • pose relative_to:表示傳感器的位姿相對於哪個 link/frame,解決“傳感器放在哪裏”的問題。
  • gz_frame_id:嘗試指定傳感器消息裏的 frame id,解決“消息 header.frame_id 寫什麼”的問題。

建議同時採用 pose relative_to<gz_frame_id>

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 / IgnitionJazzy / Gazebo Harmonic
ign_argsgz_args
ign_versiongz_version

如果要 spawn URDF / robot_description,Jazzy 使用:

spawn = Node(
    package="ros_gz_sim",
    executable="create",
    arguments=[
        "-name", "mycar",
        "-topic", "/robot_description",
    ],
    output="screen",
)

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 參數

package.xml 依賴

如果 launch 文件裏用了 ros_gz_simros_gz_bridgepackage.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>

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>

命令行遷移

Humble / Ignition 命令Jazzy / Gazebo Harmonic 命令
ign gazebo world.sdfgz sim world.sdf
ign gazebo -r world.sdfgz sim -r world.sdf
ign topic -lgz topic -l
ign topic -e -t /scangz topic -e -t /scan

ROS launch 仍然用:

ros2 launch 包名 launch文件.py

遷移後的驗證順序

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
2. 檢查 xacro 是否能生成 URDF
source /opt/ros/jazzy/setup.bash
xacro src/mycar_description/urdf/xacro/car.urdf.xacro -o /tmp/car_check.urdf
3. 檢查 Gazebo 轉 SDF 是否還有 warning
gz sdf -p /tmp/car_check.urdf

如果還有 gz_frame_idalwaysOn warning,就回到傳感器部分繼續改。

4. 構建工程
colcon build --symlink-install
source install/setup.bash
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

常見錯誤排查

插件找不到

檢查是否還寫着:

ignition-gazebo-*
libignition-gazebo-*.so
ignition::gazebo::systems::*

Jazzy 應該改成:

gz-sim-*-system
gz::sim::systems::*
GUI 標籤 warning

檢查是否還有:

<ignition-gui>

Jazzy 應該改成:

<gz-gui>
傳感器 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>

如果日誌出現:

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 不支持。

改了 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
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 環境。

最後再掃一遍舊引用

功能性舊引用檢查:

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

如果只在中文註釋或教程裏搜到舊寫法,而功能代碼裏沒有,一般就遷移乾淨了。

音乐页