2025年7月4日 星期五

ROS2 URDF DEMO video



這支影片是一個關於如何在 ROS 2 中建立 URDF (Unified Robot Description Format) 的速成課程。它是一個實用的、逐步的教學,從頭開始引導您建立一個行動機器人模型。

以下是您將學到的內容:

  • 建立 URDF 檔案: 您將了解到 URDF 檔案本質上是一個 XML 檔案,以及如何使用 <robot> 標籤設定基本結構。 [02:00, 02:36]

  • 定義連結 (Links): 您將了解如何建立「連結」,也就是機器人的剛性部分,例如底盤。這涉及使用 <link><visual><geometry> (例如 <box>) 等標籤。 [03:06, 04:11]

  • 設定原點 (Origins): 本教學涵蓋如何使用 <origin> 標籤來定義連結及其視覺元件的位置和方向(XYZ 和滾轉-俯仰-偏航)。 [04:50, 09:42]

  • 添加材料和顏色: 您將學習定義具有特定顏色 (RGBA) 的材料,並將它們應用於機器人的連結以實現更好的視覺化。 [11:04, 13:28]

  • 在 RViz 中視覺化: 影片演示了如何使用 urdf_tutorial 套件在 RViz 中啟動和視覺化您的 URDF。 [06:14, 07:29]

  • 建立關節 (Joints): 您將學習定義「關節」,它描述了連結之間的關係。這包括:

    • 固定關節 (Fixed Joints): 用於彼此之間不動的部分(例如,底座上的光達感測器)。 [18:47]

    • 連續關節 (Continuous Joints): 用於連續旋轉的部分,例如車輪。 [29:10, 32:36]

  • 建立行動機器人: 本教學逐步引導您添加以下組件:

    • 一個主底座/底盤。 [03:06]

    • 一個光達感測器(僅視覺組件)。 [14:42]

    • 兩個驅動輪。 [27:02]

    • 一個用於穩定的腳輪。 [45:55]

  • 理解 TF (Transformations): 影片解釋了關節如何定義連結之間的轉換 (TF),這對於 ROS 理解機器人結構至關重要。您還將看到如何視覺化 TF 樹。 [17:57, 56:31]

  • 定位的最佳實踐: 一個關鍵的收穫是連接組件定位的推薦過程:首先固定關節的原點,然後是關節的旋轉軸(如果適用),最後,如果需要,調整子連結的視覺原點。 [21:40, 41:12]

  • 建立虛擬連結: 引入了「base_footprint」虛擬連結的概念,以建立機器人的地面參考框架,這對於導航很有用。 [52:21, 53:30]

在本教學結束時,您將擁有一個行動機器人的 URDF,您可以在 RViz 中視覺化它,並帶有可移動的輪子。 [00:13, 55:55] 影片還提到了更全面的課程,供那些希望深入研究 URDF、TF、Gazebo 模擬等的人。 [00:53, 57:28]

為什麼 joint_state_publisher_gui 動不到 Gazebo 裡的 UR5?

為什麼 joint_state_publisher_gui 動不到 Gazebo 裡的 UR5?

元件作用實際訊號流向
joint_state_publisher_gui讓你用滑桿改「/joint_states」訊息只影響 TF/RVIZ,不發任何 command
Gazebo model透過 <gazebo_ros2_control> plugin 把機械手臂當 hardware_interface期待 controller 透過 /joint_trajectory_controller/joint_trajectorycommand topic 來驅動
結果GUI 只改 RViz 角度,Gazebo 仍停在 0°看起來「不互動」

一旦你在 URDF 裡引入 ros2_control plugin,Gazebo 會把所有關節鎖給控制器;
GUI 發出的 /joint_states 對物理模擬 完全無效


改善方案一覽

方案適用情境做法概要
A. Demo/教學,只想拉桿看手臂動不需要真實物理移除 ros2_control plugin → Gazebo 用預設關節馬達
或乾脆不開 Gazebo、只在 RViz 看
B. 真實模擬,要用控制器運動規劃 / MoveIt保留 ros2_control,但 關掉 GUI,改用
rqt_joint_trajectory_controller、MoveIt、或 CLI 送 trajectory
C. 仍想保留 GUI,但讓它驅動控制器研究/測試加一個小橋接節點:把 GUI 內 /joint_states 轉成
trajectory_msgs/JointTrajectory 丟給 /joint_trajectory_controller

具體修改作法(推薦)

1 ️⃣ 替 launch 增加開關參數

python
# bringup_gazebo.launch.py from launch.conditions import UnlessCondition, IfCondition ... ld.add_action( DeclareLaunchArgument('use_gui', default_value='false') ) ld.add_action( DeclareLaunchArgument('use_control', default_value='true') ) ... # joint_state_publisher_gui 只有在 use_gui==true AND use_control==false 才啟動 joint_state_publisher_gui_node = Node( package='joint_state_publisher_gui', executable='joint_state_publisher_gui', condition=IfCondition(LaunchConfiguration('use_gui') & UnlessCondition(LaunchConfiguration('use_control'))) )

2 ️⃣ 在 URDF/Xacro 把 ros2_control plugin 包進條件

xml
<!-- ur5_ros2_control.xacro --> <xacro:arg name="use_control" default="true"/> <xacro:if value="${use_control}"> <gazebo> <plugin name="gazebo_ros2_control" filename="libgazebo_ros2_control.so"> <parameters>$(arg hardware_config)</parameters> </plugin> </gazebo> </xacro:if>

3 ️⃣ Demo 情境(僅 GUI)啟動指令

bash
ros2 launch ur5_description bringup_gazebo.launch.py use_control:=false use_gui:=true
  • Gazebo 會用內建關節馬達;GUI 能直接拖動,RViz/Gazebo 一起動。

4 ️⃣ 真實控制情境啟動指令

bash
ros2 launch ur5_description bringup_gazebo.launch.py use_control:=true use_gui:=false
  • /joint_trajectory_controller 接管,MoveIt 或腳本送軌跡。


想把 GUI 直接驅動控制器?(進階)

python
# gui_to_trajectory_bridge.py (簡化示例) import rclpy, yaml from sensor_msgs.msg import JointState from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint JOINTS = ["shoulder_pan_joint", "shoulder_lift_joint", ...] # ur5 joints def cb(msg, pub): traj = JointTrajectory() traj.joint_names = JOINTS point = JointTrajectoryPoint() point.positions = [msg.position[msg.name.index(j)] for j in JOINTS] point.time_from_start.sec = 1 traj.points.append(point) pub.publish(traj) rclpy.init() node = rclpy.create_node('gui_to_traj') pub = node.create_publisher(JointTrajectory, '/joint_trajectory_controller/joint_trajectory', 10) node.create_subscription(JointState, '/joint_states', lambda m: cb(m, pub), 10) rclpy.spin(node)

把這個 node 加進 launch,GUI 滑桿就真的能「推動」Gazebo 關節了。


小結 🚀

  • joint_state_publisher_gui ≠ 控制器
    它只改視覺化;有 ros2_control 時必須用對應 command topic。

  • launch 參數或 xacro 條件 乾淨地分離「示範 GUI」與「真實控制」兩種模式最簡單。

  • 若要兼得 GUI+物理,需額外橋接 /joint_states → trajectory

照以上改動後,joint_state_publisher_gui 的 “不互動” 問題就能釐清並依需求解決。如果還需要示範完整的修正檔或 MoveIt 控制範例,隨時告訴我!

2025年7月3日 星期四

ROS2 四輪車的 URDF/Xacro 檔案中定義 ros2_control 標籤

 舉例說明如何在四輪車的 URDF/Xacro 檔案中定義 ros2_control 標籤,特別是針對四個車輪的關節。

在 ROS 2 中,ros2_control 標籤用於描述機器人的硬體介面(hardware interfaces)以及它們如何與您的控制系統互動。對於四輪車來說,通常會控制每個輪子的轉速(速度介面)或位置(位置介面),並監測它們的狀態。


四輪車 ros2_control 標籤範例

這個範例假設您有一個名為 my_robot.urdf.xacro 的 Xacro 檔案,並且您想控制四個輪子(左前、右前、左後、右後)。

首先,確保您的 Xacro 檔案頂部有必要的 XML 命名空間聲明,尤其是 xmlns:ros2_control="http://ros.org/schema/ros2_control/1.0"

XML
<?xml version="1.0"?>
<robot name="four_wheel_robot" xmlns:xacro="http://www.ros.org/wiki/xacro"
       xmlns:gazebo="http://gazebosim.org/schema/gazebo/1.0"
       xmlns:ros2_control="http://ros.org/schema/ros2_control/1.0">

    <joint name="left_front_wheel_joint" type="continuous">
        <parent link="base_link"/>
        <child link="left_front_wheel_link"/>
        <origin xyz="0.1 0.1 0" rpy="0 0 0"/>
        <axis xyz="0 1 0"/>
        </joint>
    <link name="left_front_wheel_link">
        </link>

    ---

    <ros2_control name="FourWheelDriveController" type="system">
        <hardware>
            <plugin>diff_drive_arduino/ArduinoSystem</plugin>
        </hardware>

        <joint name="left_front_wheel_joint">
            <command_interface name="velocity">
                <param name="min">-10</param>
                <param name="max">10</param>
            </command_interface>
            <state_interface name="velocity"/>
            <state_interface name="position"/>
        </joint>

        <joint name="right_front_wheel_joint">
            <command_interface name="velocity">
                <param name="min">-10</param>
                <param name="max">10</param>
            </command_interface>
            <state_interface name="velocity"/>
            <state_interface name="position"/>
        </joint>

        <joint name="left_rear_wheel_joint">
            <command_interface name="velocity">
                <param name="min">-10</param>
                <param name="max">10</param>
            </command_interface>
            <state_interface name="velocity"/>
            <state_interface name="position"/>
        </joint>

        <joint name="right_rear_wheel_joint">
            <command_interface name="velocity">
                <param name="min">-10</param>
                <param name="max">10</param>
            </command_interface>
            <state_interface name="velocity"/>
            <state_interface name="position"/>
        </joint>

    </ros2_control>

    ---

    <gazebo>
        <plugin filename="libgazebo_ros2_control.so" name="gazebo_ros2_control">
            <parameters>$(find four_wheel_robot)/config/my_controllers.yaml</parameters>
        </plugin>
    </gazebo>

</robot>

範例解釋:

  1. xmlns:ros2_control="http://ros.org/schema/ros2_control/1.0": 這是必要的 XML 命名空間聲明,它告訴解析器 <ros2_control> 標籤的定義來自何處。

  2. <ros2_control name="FourWheelDriveController" type="system">:

    • 這是 ros2_control 框架的主入口點。

    • name: 為這個控制硬體介面定義一個名稱 (例如 FourWheelDriveController)。

    • type: 指明這個控制器是哪種類型。常見的有:

      • system: 這是一個完整的機器人系統,包含多個關節和感測器。

      • actuator: 單個執行器。

      • sensor: 單個感測器。

  3. <hardware>:

    • 這個區塊定義了與實際物理硬體溝通的硬體介面插件 (hardware interface plugin)

    • <plugin>diff_drive_arduino/ArduinoSystem</plugin>: 這是一個範例。您需要根據您實際使用的硬體驅動器或模擬器來指定這裡的插件。

      • 模擬中,通常會使用像 gazebo_ros2_control/GazeboSystem 這樣的插件。

      • 真實硬體中,這會是您自己為您的馬達驅動板或控制板編寫的 C++ 或 Python 插件,例如 my_custom_robot_hardware/MyRobotSystem。這個插件負責實際的 I/O 操作,將抽象的指令轉換為電氣訊號。

  4. <joint name="[joint_name]">:

    • 對於您的四輪車,您會為每個輪子的關節(left_front_wheel_joint, right_front_wheel_joint, left_rear_wheel_joint, right_rear_wheel_joint)定義一個 <joint> 區塊。

    • name: 這裡的名稱必須與您在 URDF 其他部分定義的 <joint> 標籤的 name 屬性完全一致。

  5. <command_interface name="velocity">:

    • 這定義了該關節接受哪種類型的指令 (command)。對於車輪,velocity(速度)是最常見的指令,因為您通常會告訴車輪以多快的速度旋轉。

    • name="velocity": 指定這是一個速度指令介面。ros2_control 支援多種標準介面,例如 positionvelocityeffort

    • <param name="min">-10</param><param name="max">10</param>: 定義了該指令的最小值和最大值,通常是角速度(弧度/秒)或力矩/力。

  6. <state_interface name="velocity"/><state_interface name="position"/>:

    • 這定義了該關節提供哪種類型的狀態 (state) 讀數。

    • name="velocity": 指明這個介面提供當前輪子的角速度。

    • name="position": 指明這個介面提供當前輪子的累積角度位置(例如從編碼器讀取)。

    • 重要: ros2_control 會從硬體介面讀取這些狀態,並讓控制器和 joint_state_broadcaster(將關節狀態發布到 ROS Topic)使用它們。

  7. <gazebo> 插件整合:

    • plugin filename="libgazebo_ros2_control.so" name="gazebo_ros2_control": 這是將 ros2_control 與 Gazebo 模擬器連接起來的標準 Gazebo 插件。它允許 ros2_control 的硬體介面在 Gazebo 模擬中運行,而不是依賴實際硬體。

    • <parameters>$(find four_wheel_robot)/config/my_controllers.yaml</parameters>: 這指示 gazebo_ros2_control 插件去載入一個 YAML 設定檔,該檔案定義了要使用的控制器及其參數。您需要創建這個 my_controllers.yaml 檔案。


my_controllers.yaml 檔案範例 (放在 config 目錄下)

這個 YAML 檔案會告訴 controller_manager 您要啟用哪些控制器,以及它們如何配置。

YAML
# my_controllers.yaml
controller_manager:
  ros__parameters:
    update_rate: 100  # 控制器管理器更新頻率 (Hz)

    # 關節狀態發布器:負責將來自硬體介面的關節狀態發布為 ROS Topic
    joint_state_broadcaster:
      type: joint_state_broadcaster/JointStateBroadcaster

    # 差速驅動控制器:用於控制兩輪驅動的機器人 (四輪差速驅動通常也用這個)
    diff_drive_controller:
      type: diff_drive_controller/DiffDriveController # 或者您可以自定義控制器
      ros__parameters:
        left_wheel_names: ["left_front_wheel_joint", "left_rear_wheel_joint"]
        right_wheel_names: ["right_front_wheel_joint", "right_rear_wheel_joint"]

        # 機器人輪子半徑和輪距
        wheel_radius: 0.033 # 替換為您的輪子半徑
        wheel_separation: 0.17 # 替換為您的輪距 (左右輪中心距離)

        # 速度 PID 參數 (可選,如果控制器支持)
        # publish_cmd_vel: true
        # publish_wheel_tf: true
        # left_wheel_velocity_filter: 0.1
        # right_wheel_velocity_filter: 0.1
        # linear:
        #   x:
        #     has_velocity_limits: true
        #     max_velocity: 0.5
        #     min_velocity: -0.5
        #     has_acceleration_limits: true
        #     max_acceleration: 1.0
        #     min_acceleration: -1.0
        # angular:
        #   z:
        #     has_velocity_limits: true
        #     max_velocity: 1.0
        #     min_velocity: -1.0
        #     has_acceleration_limits: true
        #     max_acceleration: 2.0
        #     min_acceleration: -2.0

總結

這個 Xacro 範例中的 ros2_control 標籤定義了四輪車的四個輪子關節將如何通過 velocity 指令介面和 velocity/position 狀態介面與 ros2_control 框架互動。同時,gazebo 插件部分則確保在 Gazebo 模擬中,ros2_control 能夠載入控制器並控制這些關節。

這是為四輪車設置 ros2_control 的基礎架構,您可以根據您的具體需求和硬體特性進一步擴展和調整。

ROS 2 Control (通常簡稱為 ros2_control)。

 


ROS 2 Control (通常簡稱為 ros2_control)。


什麼是 ROS 2 Control?

ROS 2 Control 是一個為機器人控制系統設計的框架,它提供了一個標準化的介面,讓您可以輕鬆地連接不同類型的硬體(如馬達、感測器、機器手臂)到您的 ROS 2 應用程式

想像一下,您正在開發一個新的機器人,它可能使用各種品牌的馬達和驅動器。如果沒有 ros2_control,您每次換硬體,就得重寫一大堆程式碼來和這些新的硬體溝通。ros2_control 的目的就是為了解決這個問題,它在硬體和高階控制演算法之間建立了一個抽象層

為什麼需要 ROS 2 Control?

  1. 硬體抽象化: 不管底層的馬達驅動器、感測器或 I/O 板是哪家製造商的,ros2_control 都提供了一致的介面讓您的控制器程式去操作它們。這大大簡化了硬體替換和新機器人開發的流程。

  2. 即時 (Real-time) 性能: ros2_control 設計時就考慮到了即時控制的需求。它將控制迴圈的關鍵部分與非即時的 ROS 2 基礎設施分開,讓您可以實現高頻率、低延遲的控制。

  3. 模組化和可重複使用: 您可以為不同的硬體或控制器開發獨立的模組,並在不同的機器人專案中重複使用這些模組。

  4. 社群和生態系統: 它是 ROS 2 的官方控制框架,擁有活躍的社群支援和豐富的工具鏈,例如:

    • 控制器 (Controllers): 已經有很多預建的控制器,例如差速驅動控制器 (differential_drive_controller)、關節軌跡控制器 (joint_trajectory_controller) 等,可以直接使用。

    • 硬體介面 (Hardware Interfaces): 提供了與不同硬體類型交互的標準方式。


ROS 2 Control 的核心組件

ros2_control 框架主要由以下幾個關鍵組件構成:

  1. 硬體介面 (Hardware Interface):

    • 這是 ros2_control 與實際機器人硬體互動的部分。每個硬體介面都負責將機器人的物理硬體(如馬達、編碼器、力感測器)的讀數轉換為 ros2_control 能理解的標準格式,並將控制指令(如設定馬達速度、位置)從 ros2_control 轉換為硬體能理解的格式。

    • 您需要為您的特定硬體實作 (implement) 一個硬體介面。

    • 它負責處理狀態 (states) 的讀取(例如:馬達目前的位置、速度、力矩)和指令 (commands) 的寫入(例如:設定馬達的目標位置、速度、力矩)。

  2. 控制器管理器 (Controller Manager):

    • 控制器管理器是 ros2_control 的核心,它是一個ROS 2 節點

    • 它負責載入、啟動、停止和卸載各種控制器 (Controllers)

    • 它也是控制器與硬體介面之間的橋樑,協調數據流動。

    • 控制器管理器本身是一個生命週期節點 (Lifecycle Node),這意味著它可以被程式化地控制其狀態,方便在機器人系統中進行管理。

  3. 控制器 (Controllers):

    • 控制器是執行特定控制邏輯的模組,也是 ROS 2 節點。它們從 ROS 2 Topic 接收高階指令(例如:讓機器人移動到特定位置,或讓機器手臂跟隨某個軌跡),然後將這些指令轉換為低階的硬體指令(例如:設定每個關節的目標角度)。

    • 控制器透過控制器管理器與硬體介面通訊,獲取硬體狀態並發送指令。

    • ros2_control 提供了許多標準控制器,例如:

      • joint_state_broadcaster:將硬體介面讀取的關節狀態發布到 ROS 2 話題。

      • joint_trajectory_controller:控制多個關節跟隨一個軌跡。

      • diff_drive_controller:用於差速驅動機器人。

      • force_torque_sensor_broadcaster:發布力/扭矩感測器的讀數。

    • 您也可以根據自己的需求開發自定義控制器。

  4. URDF/Xacro 中的 ros2_control 標籤:

    • 在機器人的 URDF 或 Xacro 描述檔中,您會看到特殊的 <ros2_control> 標籤。

    • 這些標籤用於定義機器人有哪些硬體介面(例如:hardware_interface/JointStateInterfacehardware_interface/VelocityJointInterface),以及它們對應到 URDF 中的哪些關節。

    • 它們還定義了機器人的傳動裝置 (Transmissions),說明了關節如何與電機和感測器連接。


ROS 2 Control 的工作流程簡化

  1. URDF 定義: 在機器人的 URDF/Xacro 檔案中,除了定義機器人的幾何形狀和運動學,還會添加 <ros2_control> 標籤,宣告哪些關節可以被控制,以及它們提供哪些狀態和接受哪些指令。

  2. 硬體介面實作: 開發者為實際的硬體編寫程式碼,實作 hardware_interface,將硬體讀數(如編碼器值)轉換為關節位置/速度狀態,並將關節指令(如目標速度)轉換為馬達驅動器指令。

  3. 啟動 Launch 檔案: 啟動一個 Launch 檔案,它會:

    • 載入機器人的 URDF 描述。

    • 啟動 controller_manager 節點。

    • 載入並啟動您所需的控制器(例如 joint_trajectory_controller)。

  4. 控制器運作:

    • 控制器從 ROS 2 Topic 接收高階指令。

    • 控制器向控制器管理器請求硬體狀態(例如當前關節位置)。

    • 控制器執行其控制演算法(例如 PID 控制)。

    • 控制器將計算出的低階指令傳遞給控制器管理器。

    • 控制器管理器將指令轉發給對應的硬體介面。

    • 硬體介面將指令轉換為硬體訊號,驅動馬達。

    • 硬體介面讀取新的硬體狀態,再傳回給控制器管理器,完成控制迴圈。


總之,ROS 2 Control 提供了一個強大且彈性的框架,讓您可以高效地開發和部署複雜的機

導航架構的詳細說明

 


機器人或自主系統中,導航(Navigation)功能的一個高層次架構。它解釋了導航如何依賴於不同的資訊來源和處理模組。

以下是這個導航架構的詳細說明:

1. Navigation (導航)

這是整個架構的最終目標,指引機器人從一個點移動到另一個點,同時避開障礙物並遵循預定的路徑。為了實現有效的導航,它需要兩個關鍵的輸入:

  • Robot Position Estimate (機器人位置估計):知道機器人在地圖上的確切位置。

  • Obstacle Awareness (障礙物感知):了解周圍環境中障礙物的位置和分佈。

2. Robot Position Estimate (機器人位置估計)

這個模組的職責是確定機器人在環境中的當前位置。它主要依賴於一個核心技術:

  • SLAM (Simultaneous Localization and Mapping)

    • 定義:SLAM 是一種讓機器人在未知環境中同時構建地圖並確定自身位置的技術。它通過整合來自各種感測器(如 LiDAR、攝影機、IMU 等)的數據來實現。

    • 重要性:對於機器人能夠在環境中移動而不迷失方向至關重要。

3. Obstacle Awareness (障礙物感知)

這個模組的職責是識別並追蹤環境中的障礙物,以確保機器人能夠安全地避開它們。它從兩個主要來源獲取資訊:

  • Static Map (靜態地圖)

    • 定義:這是一個預先構建或通過 SLAM 構建的環境地圖,其中包含了環境中固定不變的物體(如牆壁、家具、柱子等)。

    • 重要性:提供了環境的基本佈局和永久障礙物的位置資訊。

  • Live Lidar Data (即時光達數據)

    • 定義:光達(LiDAR)感測器發射雷射脈衝並測量反射回來的時間來計算距離,從而創建周圍環境的三維點雲。

    • 重要性:提供了環境的即時、動態資訊,可以檢測到靜態地圖中沒有的臨時或移動障礙物(例如,移動的人、其他機器人、臨時放置的物品等)。這對於動態避障至關重要。

架構流程總結:

  1. SLAM 提供機器人的位置估計

  2. Static Map 提供環境中靜態障礙物的資訊。

  3. Live Lidar Data 提供環境中動態或臨時障礙物的即時資訊。

  4. 靜態地圖和即時光達數據共同匯總成障礙物感知模組,提供完整的障礙物分佈。

  5. 機器人位置估計障礙物感知的資訊匯流到導航模組。

  6. 導航模組利用這些資訊來規劃路徑,避開障礙物,並引導機器人安全地到達目的地。

這個架構清晰地展示了現代機器人導航系統中,定位、地圖構建和障礙物避讓是如何相互協作,以實現自主移動的。