2025年7月2日 星期三

ROS2 URDF 或 Xacro 格式轉換為 SDF (Simulation Description Format)

 在 ROS 和 Gazebo 中,將 URDFXacro 格式轉換為 SDF (Simulation Description Format) 是一種常見的操作,因為 Gazebo 內部主要使用 SDF 來描述世界和模型。

SDF 格式包含了比 URDF 更多用於模擬的資訊(例如物理屬性、傳感器、插件等)。當您在 Gazebo 中載入一個 URDF 或 Xacro 檔案時,Gazebo 會在內部將其轉換為 SDF。

以下是將 URDF 或 Xacro 轉換為 SDF 的兩種主要方法:


方法一:使用 urdfdom_pysdformat_urdf 工具 (推薦用於程式化轉換)

這是一種在 Python 環境下進行轉換的方法,特別適用於 Launch 檔案或腳本中。

  1. 確保安裝必要的 ROS 2 套件: 您需要安裝 urdfdom_pysdformat_urdf(或其依賴項),這些通常會隨 ROS 2 的桌面完整版一起安裝。如果沒有,可以嘗試:

    Bash
    sudo apt update
    sudo apt install ros-humble-urdfdom-py ros-humble-sdformat-urdf
    
  2. 創建一個 Python 腳本進行轉換:

    Python
    import os
    from ament_index_python.packages import get_package_share_directory
    from urdf_parser_py.urdf import URDF
    from sdformat_urdf import urdf_to_sdf
    
    def convert_robot_model(package_name, urdf_file_name, output_sdf_file_name):
        try:
            # 獲取套件的 share 目錄
            package_share_directory = get_package_share_directory(package_name)
    
            # 組合 URDF 檔案的完整路徑
            urdf_path = os.path.join(package_share_directory, 'urdf', urdf_file_name)
    
            # 如果是 Xacro 檔案,先進行 Xacro 轉換
            if urdf_file_name.endswith('.xacro'):
                import xacro
                # 注意:xacro.process_file 需要在 Python 腳本中以這種方式呼叫
                # 這裡假設 xacro 已經安裝:pip install xacro
                # 或者 ros-humble-xacro 已經安裝
                doc = xacro.process_file(urdf_path)
                urdf_content = doc.toprettyxml(indent='  ')
            else:
                with open(urdf_path, 'r') as f:
                    urdf_content = f.read()
    
            # 解析 URDF 內容
            robot = URDF.from_xml_string(urdf_content)
    
            # 將 URDF 轉換為 SDF
            sdf_model = urdf_to_sdf.convert_urdf_to_sdf_model(robot)
    
            # 將 SDF 內容寫入檔案
            output_sdf_path = os.path.join(package_share_directory, 'models', output_sdf_file_name)
            with open(output_sdf_path, 'w') as f:
                f.write(sdf_model.to_xml_string(prettyprint=True))
    
            print(f"Successfully converted '{urdf_file_name}' to '{output_sdf_file_name}'")
            print(f"SDF file saved to: {output_sdf_path}")
    
        except Exception as e:
            print(f"Error during conversion: {e}")
    
    

if name == 'main': # --- 配置您的檔案資訊 --- # 您的 ROS 2 套件名稱 my_package = 'ur5_description' # 要轉換的 URDF 或 Xacro 檔案名稱 (在套件的 'urdf' 目錄下) input_urdf_xacro = 'ur5.urdf.xacro' # 例如 'ur5.urdf' 或 'my_robot.urdf.xacro' # 輸出 SDF 檔案的名稱 (會儲存在套件的 'models' 目錄下,如果沒有請手動創建) output_sdf = 'ur5.sdf'

# 確保 'models' 目錄存在
package_share_directory = get_package_share_directory(my_package)
models_dir = os.path.join(package_share_directory, 'models')
os.makedirs(models_dir, exist_ok=True) # 如果不存在則創建

convert_robot_model(my_package, input_urdf_xacro, output_sdf)

```
  1. 運行腳本: 將上述程式碼保存為 convert_to_sdf.py,然後執行:

    Bash
    python3 convert_to_sdf.py
    

    它會將您指定的 URDF/Xacro 檔案轉換為 SDF,並保存在指定的路徑。


方法二:使用 Gazebo 的內部轉換機制 (最常見且推薦)

在大多數情況下,您不需要手動將 URDF/Xacro 轉換為 SDF。Gazebo 內建了轉換器,當您使用 robot_state_publisherspawn_entity.py 將模型載入 Gazebo 時,它會自動處理。

步驟:

  1. 確保您的 URDF/Xacro 檔案是正確且完整的:

    • 包含所有 <link><inertial> 資訊。

    • 包含 <visual><collision> 幾何體。

    • 最重要的是,包含 Gazebo 特定擴展標籤 (<gazebo>)。 這些標籤定義了 Gazebo 需要的物理屬性、傳感器和插件。沒有這些標籤,即使轉換成功,模型在 Gazebo 中也無法正確模擬。

  2. 使用 robot_state_publisher 發布 URDF/Xacro 內容: 在您的 Launch 檔案中,使用 xacro 命令讀取 Xacro/URDF 檔案,並將其內容發布到 /robot_description 話題。

    Python
    import os
    from ament_index_python.packages import get_package_share_directory
    from launch import LaunchDescription
    from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
    from launch.substitutions import LaunchConfiguration, Command
    from launch.launch_description_sources import PythonLaunchDescriptionSource
    from launch_ros.actions import Node
    from launch_ros.parameter_descriptions import ParameterValue # 確保有這行
    
    def generate_launch_description():
        # 獲取套件的路徑
        description_package_path = get_package_share_directory('ur5_description') # 替換為您的套件名稱
    
        # 組合 xacro 檔案的路徑
        xacro_file = os.path.join(description_package_path, 'urdf', 'ur5.urdf.xacro') # 替換為您的檔案名稱
    
        # 使用 Command 替換 Xacro 預處理
        robot_description_content = ParameterValue(Command(['xacro ', xacro_file]),
                                                value_type=str)
    
        # 啟動 robot_state_publisher 節點
        robot_state_publisher_node = Node(
            package='robot_state_publisher',
            executable='robot_state_publisher',
            name='robot_state_publisher',
            output='screen',
            parameters=[{'robot_description': robot_description_content}],
        )
    
        # 啟動 Gazebo 伺服器
        gazebo_server_cmd = IncludeLaunchDescription(
            PythonLaunchDescriptionSource([os.path.join(
                get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py'
            )]),
            launch_arguments={'world': os.path.join(get_package_share_directory('gazebo_ros'), 'worlds', 'empty.world')}.items()
        )
    
        # 啟動 Gazebo 客戶端
        gazebo_client_cmd = ExecuteProcess(
            cmd=['gzclient'],
            output='screen'
        )
    
        # 使用 spawn_entity.py 將機器人模型載入 Gazebo
        # 這個工具會從 /robot_description 話題讀取 URDF/SDF,並將其插入 Gazebo
        spawn_entity_cmd = Node(
            package='gazebo_ros',
            executable='spawn_entity.py',
            arguments=['-entity', 'my_robot', '-topic', 'robot_description', '-x', '0', '-y', '0', '-z', '0.1'],
            output='screen'
        )
    
        return LaunchDescription([
            gazebo_server_cmd,
            gazebo_client_cmd,
            robot_state_publisher_node,
            spawn_entity_cmd,
        ])
    

總結

  • 手動轉換 (方法一):當您需要一個實際的 .sdf 檔案用於其他 Gazebo 外部工具,或者出於某些除錯目的時,可以使用 Python 腳本手動轉換。但請記住,手動轉換的 SDF 可能不如直接在 Gazebo 中啟動 URDF/Xacro 那樣方便,因為後者會自動處理所有必要的內部配置。

  • 自動轉換 (方法二):在大多數 ROS 2 Gazebo 模擬的場景中,您只需要準備好包含 Gazebo 擴展的 URDF/Xacro 檔案,然後使用 robot_state_publisherspawn_entity.py。Gazebo 會在載入時自動將 URDF 轉換為其內部的 SDF 表示。這是最常見且推薦的方式。

無論您選擇哪種方式,URDF/Xacro 檔案中包含

必要的 Gazebo 擴展 (<gazebo>) 是在 Gazebo 中成功模擬的關鍵。 

如果缺少這些,模型可能只能顯示外觀,但沒有正確的物理行為或傳感器。




沒有留言:

張貼留言