2025年6月25日 星期三

ROS2 建立 ROS 2 URDF 模型套件

 建立 ROS 2 URDF 模型套件主要涉及以下步驟:

  1. 建立套件: 使用 ros2 pkg create 指令建立一個 ROS 2 套件。
  2. 建立 URDF 檔案: 撰寫或將您的機器人 URDF 模型檔案放置在套件內適當的位置。
  3. 建立啟動檔案 (Launch File): 撰寫一個 ROS 2 啟動檔案,用於啟動 robot_state_publisher 節點來發布機器人的狀態,並可選地啟動 Rviz2 來視覺化模型。
  4. 設定 package.xmlCMakeLists.txt 配置這兩個檔案以確保套件正確構建和安裝,並將 URDF 和啟動檔案安裝到正確的位置。

以下是一個詳細的範例,展示如何建立一個名為 my_robot_description 的 ROS 2 套件,其中包含一個簡單的 URDF 模型:


範例情境:

我們將建立一個 ROS 2 套件,包含一個非常簡單的 URDF 模型(一個固定在世界座標系中的立方體),並提供一個啟動檔案來在 Rviz2 中顯示它。


步驟 1:建立工作空間 (如果尚未建立)

Bash
mkdir -p ~/ros2_urdf_ws/src
cd ~/ros2_urdf_ws

步驟 2:建立 ROS 2 套件

在您的工作空間的 src 目錄中建立一個名為 my_robot_description 的 ROS 2 套件。我們將使用 ament_cmake 作為構建工具,因為通常處理 URDF 模型會涉及一些 C++ 依賴或工具。

Bash
cd ~/ros2_urdf_ws/src
ros2 pkg create --build-type ament_cmake my_robot_description

步驟 3:建立 URDF 檔案

my_robot_description 套件中,建立一個 urdf 子目錄來存放您的 URDF 檔案。

Bash
mkdir -p ~/ros2_urdf_ws/src/my_robot_description/urdf

創建 my_robot.urdf 檔案:

Bash
touch ~/ros2_urdf_ws/src/my_robot_description/urdf/my_robot.urdf

將以下簡單的 URDF 內容複製貼上到 my_robot.urdf 中:

XML
<?xml version="1.0"?>
<robot name="my_simple_robot">

  <link name="world"/>

  <link name="base_link">
    <visual>
      <geometry>
        <box size="0.2 0.2 0.2"/>
      </geometry>
      <material name="blue">
        <color rgba="0 0 1 1"/>
      </material>
    </visual>
    <collision>
      <geometry>
        <box size="0.2 0.2 0.2"/>
      </geometry>
    </collision>
    <inertial>
      <mass value="1.0"/>
      <inertia ixx="0.01" ixy="0.0" ixz="0.0" iyy="0.01" iyz="0.0" izz="0.01"/>
    </inertial>
  </link>

  <joint name="world_to_base_link" type="fixed">
    <parent link="world"/>
    <child link="base_link"/>
    <origin xyz="0 0 0.1" rpy="0 0 0"/>
  </joint>

</robot>

這個 URDF 定義了一個名為 my_simple_robot 的機器人,它只有一個 base_link(一個藍色立方體),並通過一個 fixed 關節連接到 world 座標系。

步驟 4:建立啟動檔案 (Launch File)

my_robot_description 套件中,建立一個 launch 子目錄來存放您的啟動檔案。

Bash
mkdir -p ~/ros2_urdf_ws/src/my_robot_description/launch

創建 display.launch.py 檔案:

Bash
touch ~/ros2_urdf_ws/src/my_robot_description/launch/display.launch.py

將以下內容複製貼上到 display.launch.py 中:

Python
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node

def generate_launch_description():
    # 宣告用於 URDF 檔案路徑的啟動參數
    urdf_file_name = 'my_robot.urdf'
    urdf_path = os.path.join(
        get_package_share_directory('my_robot_description'),
        'urdf',
        urdf_file_name
    )

    # 宣告 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': LaunchConfiguration('robot_description_content', default=open(urdf_path).read())}],
        arguments=[urdf_path] # 如果robot_description參數是檔案路徑,可以這樣傳遞
    )

    # 宣告 joint_state_publisher_gui 節點 (可選,用於手動控制關節)
    # joint_state_publisher_gui_node = Node(
    #     package='joint_state_publisher_gui',
    #     executable='joint_state_publisher_gui',
    #     name='joint_state_publisher_gui',
    #     output='screen',
    # )

    # 宣告 Rviz2 節點
    rviz_config_dir = os.path.join(get_package_share_directory('my_robot_description'), 'rviz')
    # 創建一個簡單的 Rviz 配置檔案 (如果您沒有現有的)
    # 推薦的做法是先啟動 Rviz2,配置好後保存 .rviz 檔案到這個路徑
    default_rviz_config_path = os.path.join(rviz_config_dir, 'display.rviz')
    if not os.path.exists(default_rviz_config_path):
        os.makedirs(rviz_config_dir, exist_ok=True)
        # 簡單的 Rviz 配置範例內容,您需要手動創建這個文件或自行配置 Rviz
        # echo '你需要手動創建或配置 Rviz2 的 display.rviz 檔案' > ${default_rviz_config_path}
        # For this example, we will just launch Rviz without a specific config if it doesn't exist
        pass

    rviz_node = Node(
        package='rviz2',
        executable='rviz2',
        name='rviz2',
        output='screen',
        arguments=['-d', default_rviz_config_path] # 加載 Rviz 配置檔案
    )

    return LaunchDescription([
        # DeclareLaunchArgument(
        #     'use_sim_time',
        #     default_value='false',
        #     description='Use simulation (Gazebo) clock if true'),
        robot_state_publisher_node,
        # joint_state_publisher_gui_node, # 如果需要,請取消註解
        rviz_node,
    ])

說明:

  • get_package_share_directory('my_robot_description'):這個函數用於獲取 my_robot_description 套件的 share 目錄路徑。
  • robot_state_publisher 節點:這是 ROS 2 中一個關鍵的節點,它讀取 URDF 檔案並發布機器人的各個 linktf 樹中的轉換關係。Rviz2 和其他導航、規劃工具都依賴這個 tf 資訊。
  • rviz2 節點:用於視覺化機器人模型和 ROS 2 數據。

步驟 5:配置 package.xml

打開 my_robot_description/package.xml,並在 <build_type>ament_cmake</build_type> 之後,添加必要的依賴項。

XML
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>my_robot_description</name>
  <version>0.0.0</version>
  <description>A package containing the URDF description of my robot.</description>
  <maintainer email="your_email@example.com">Your Name</maintainer>
  <license>Apache License 2.0</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <exec_depend>robot_state_publisher</exec_depend>
  <exec_depend>rviz2</exec_depend>
  <exec_depend>xacro</exec_depend> <exec_depend>joint_state_publisher_gui</exec_depend> <exec_depend>urdf</exec_depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

說明:

  • <exec_depend>:這些是運行時的依賴,表示運行此套件中的可執行文件(例如啟動檔案)所需的其他 ROS 2 套件。

步驟 6:配置 CMakeLists.txt

打開 my_robot_description/CMakeLists.txt。您需要添加指令來安裝 URDF 檔案和啟動檔案。

CMake
# ~/ros2_urdf_ws/src/my_robot_description/CMakeLists.txt
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(my_robot_description)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
# find_package(rclcpp REQUIRED) # 如果您有 C++ 節點,則需要
# find_package(std_msgs REQUIRED) # 如果您有 C++ 節點使用 std_msgs,則需要

# 安裝 URDF 檔案
install(DIRECTORY urdf
  DESTINATION share/${PROJECT_NAME}
)

# 安裝啟動檔案
install(DIRECTORY launch
  DESTINATION share/${PROJECT_NAME}
)

ament_package()

說明:

  • install(DIRECTORY urdf DESTINATION share/${PROJECT_NAME}):這條指令會將 urdf 目錄中的所有內容安裝到 install/<package_name>/share/<package_name>/urdf/
  • install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}):這條指令會將 launch 目錄中的所有內容安裝到 install/<package_name>/share/<package_name>/launch/

步驟 7:建構工作空間

回到工作空間的根目錄,然後使用 colcon build 進行建構。

Bash
cd ~/ros2_urdf_ws
colcon build

步驟 8:Source 工作空間設定檔

在運行您的啟動檔案之前,您需要 source 工作空間的設定檔,以便 ROS 2 能夠找到您新建立的套件。

Bash
source install/setup.bash

注意: 每次打開新的終端機時,都需要執行此命令。

步驟 9:運行 URDF 模型

現在,您可以啟動您的 URDF 顯示啟動檔案:

Bash
ros2 launch my_robot_description display.launch.py

這將會啟動 robot_state_publisherrviz2。在 Rviz2 中,您應該能夠看到一個藍色的立方體模型。如果沒有,請在 Rviz2 中添加 RobotModel 顯示類型,並確保 Fixed Frame 設定為 world

常見問題和提示:

  • Rviz2 無法顯示模型: 確保 robot_state_publisher 正在運行,並且 Rviz2 的 Fixed Frame 設置正確(通常是 world 或您 URDF 的根 link)。也要確保在 Rviz2 中添加了 RobotModel 顯示類型。
  • URDF 語法錯誤: 如果 robot_state_publisher 啟動失敗,很可能是 URDF 檔案有語法錯誤。您可以手動檢查 URDF 檔案,或者使用 check_urdf 工具(如果已安裝)。
  • 視覺化或碰撞模型檔案: 如果您的 URDF 引用了 .stl.dae 等網格文件,您需要在 URDF 中使用相對路徑,並確保這些網格文件與 URDF 文件一起安裝到正確的位置(通常在 share/<package_name>/meshes 目錄中)。您也需要相應地更新 CMakeLists.txt 來安裝這些檔案。
  • XACRO: 對於更複雜的機器人模型,通常會使用 xacro 來編寫 URDF,因為它支持宏和參數化,提高了可讀性和重用性。如果您使用 xacro 檔案(例如 my_robot.urdf.xacro),您的啟動檔案需要額外步驟來將其處理成標準 URDF。通常會用到 xacro 工具,並且 robot_state_publisherparameters 中會使用 xacro.process_file() 來讀取處理後的 URDF 內容。
  • Joint State Publisher: 如果您的機器人有可動關節,您通常還會啟動 joint_state_publisher (如果沒有 GUI) 或 joint_state_publisher_gui (如果需要 GUI) 來發布關節狀態,以便 robot_state_publisher 可以更新機器人的姿態。

沒有留言:

張貼留言