在 ROS 和 Gazebo 中,將 URDF 或 Xacro 格式轉換為 SDF (Simulation Description Format) 是一種常見的操作,因為 Gazebo 內部主要使用 SDF 來描述世界和模型。
SDF 格式包含了比 URDF 更多用於模擬的資訊(例如物理屬性、傳感器、插件等)。當您在 Gazebo 中載入一個 URDF 或 Xacro 檔案時,Gazebo 會在內部將其轉換為 SDF。
以下是將 URDF 或 Xacro 轉換為 SDF 的兩種主要方法:
方法一:使用 urdfdom_py
和 sdformat_urdf
工具 (推薦用於程式化轉換)
這是一種在 Python 環境下進行轉換的方法,特別適用於 Launch 檔案或腳本中。
確保安裝必要的 ROS 2 套件: 您需要安裝
urdfdom_py
和sdformat_urdf
(或其依賴項),這些通常會隨 ROS 2 的桌面完整版一起安裝。如果沒有,可以嘗試:Bashsudo apt update sudo apt install ros-humble-urdfdom-py ros-humble-sdformat-urdf
創建一個 Python 腳本進行轉換:
Pythonimport 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)
```
運行腳本: 將上述程式碼保存為
convert_to_sdf.py
,然後執行:Bashpython3 convert_to_sdf.py
它會將您指定的 URDF/Xacro 檔案轉換為 SDF,並保存在指定的路徑。
方法二:使用 Gazebo 的內部轉換機制 (最常見且推薦)
在大多數情況下,您不需要手動將 URDF/Xacro 轉換為 SDF。Gazebo 內建了轉換器,當您使用 robot_state_publisher
和 spawn_entity.py
將模型載入 Gazebo 時,它會自動處理。
步驟:
確保您的 URDF/Xacro 檔案是正確且完整的:
包含所有
<link>
的<inertial>
資訊。包含
<visual>
和<collision>
幾何體。最重要的是,包含 Gazebo 特定擴展標籤 (
<gazebo>
)。 這些標籤定義了 Gazebo 需要的物理屬性、傳感器和插件。沒有這些標籤,即使轉換成功,模型在 Gazebo 中也無法正確模擬。
使用
robot_state_publisher
發布 URDF/Xacro 內容: 在您的 Launch 檔案中,使用xacro
命令讀取 Xacro/URDF 檔案,並將其內容發布到/robot_description
話題。Pythonimport 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_publisher
和spawn_entity.py
。Gazebo 會在載入時自動將 URDF 轉換為其內部的 SDF 表示。這是最常見且推薦的方式。
無論您選擇哪種方式,URDF/Xacro 檔案中包含
必要的 Gazebo 擴展 (<gazebo>
) 是在 Gazebo 中成功模擬的關鍵。
如果缺少這些,模型可能只能顯示外觀,但沒有正確的物理行為或傳感器。
沒有留言:
張貼留言