顯示具有 ROS2 標籤的文章。 顯示所有文章
顯示具有 ROS2 標籤的文章。 顯示所有文章

2025年9月11日 星期四

twowheel_amr 機器人模擬環境 node and topic

  以下是針對 twowheel_amr 機器人模擬環境中的節點和主題的說明:

節點 (Nodes)

這些節點代表模擬環境中的各個軟體元件,負責特定的功能。

  • /gazebo: 這是 Gazebo 模擬器的主要節點,負責執行物理引擎、渲染和處理所有模擬事件。

  • /gazebo_ros_ray_sensor: 這是模擬世界中一個特定於 twowheel_amr 的雷射掃描感測器節點。通常用於 Gazebo 世界中,以模擬雷射掃描儀的行為。

  • /robot_state_publisher: 這個節點會讀取機器人的 URDF 檔案,並結合 /joint_states 主題發布的關節資訊,計算並發布每個機器人連桿的 3D 姿態。

  • /rqt_gui_py_node_10542: 這是 ROS 2 的圖形化工具 rqt 的實例。它提供了一個圖形介面來監控和除錯 ROS 2 系統。

  • /twowheel_amr/diff_drive_controller: 這個是 twowheel_amr 機器人的差速驅動控制器節點。它訂閱 /twowheel_amr/cmd_vel 主題的指令,並根據這些指令計算每個車輪的轉速,以驅動機器人在 Gazebo 中移動。

  • /twowheel_amr/gazebo_ros_imu_sensor: 這是 twowheel_amr 機器人的 IMU(慣性測量單元)感測器節點。它模擬 IMU 的行為並將數據發布到 /twowheel_amr/imu/data 主題。

  • /twowheel_amr/gazebo_ros_ray_sensor: 這是 twowheel_amr 機器人的雷射掃描感測器節點。它模擬雷射掃描儀的行為並將數據發布到 /twowheel_amr/scan 主題。


主題 (Topics)

這些主題是節點之間交換數據的管道。

  • /clock: 在模擬環境中,這個主題發布模擬時間,取代了系統時鐘。

  • /joint_states: 這個主題發布機器人所有關節的當前位置、速度和力矩,通常由 Gazebo 模擬器發布。

  • /parameter_events: ROS 2 內部主題,用於廣播節點參數的變化。

  • /performance_metrics: 內部主題,提供關於 ROS 2 系統效能的數據。

  • /robot_description: 包含機器人完整的 URDF 或 SDF 描述,供 robot_state_publisher 等節點使用。

  • /rosout: ROS 2 的標準日誌主題,所有節點的日誌資訊都會發布到這裡。

  • /scan: 這是通用雷射掃描主題,可能與/gazebo_ros_ray_sensor節點相關,但由於有/twowheel_amr/scan主題,這個主題可能已經不再活躍使用。

  • /tf 與 /tf_static: 這些主題發布動態和靜態的座標轉換資訊,用於描述機器人連桿、感測器和世界坐標系之間的關係。

  • /twowheel_amr/cmd_vel: 這是指令速度主題,用於遠程控制 twowheel_amr 機器人。當您發布訊息到這個主題時,diff_drive_controller 會讀取並據此移動機器人。

  • /twowheel_amr/imu/datatwowheel_amr 機器人 IMU 感測器發布的數據,通常包含加速度和角速度資訊。

  • /twowheel_amr/scantwowheel_amr 機器人雷射掃描感測器發布的數據,通常用於建圖或避障。

工作流從 gazebo_ros 轉換到 ros_gz_sim

 

ROS 2 啟動 Gazebo 之後,您可以使用 ros2 run 指令,透過 gazebo_ros 套件中的 spawn_entity.py 工具來載入 URDF 檔案。


載入 URDF 到 Gazebo 的指令

要將名為 twowheel.urdf 的 URDF 檔案載入到 Gazebo Sim 中,標準的 ROS 2 指令格式如下:

ros2 run gazebo_ros spawn_entity.py -entity twowheel_amr -file /path/to/your/twowheel.urdf -x 0 -y 0 -z 0

指令參數說明

  • ros2 run gazebo_ros spawn_entity.py: 這是用來執行 gazebo_ros 套件中,負責產生實體的 Python 腳本。

  • -entity twowheel_amr: 指定您要產生的實體名稱。這在 Gazebo 內部會被用作模型的名稱。

  • -file /path/to/your/twowheel.urdf: 指定您 URDF 檔案的完整路徑。 非常重要:您需要將 /path/to/your/ 替換為 twowheel.urdf 檔案在您系統中的實際路徑。

  • -x 0 -y 0 -z 0: 這是可選參數,用來設定模型在 Gazebo 世界中的初始位置。您可以根據需要調整這些值。

備註

  • 環境變數: 為了確保 ros2 指令能找到 gazebo_ros 和其他 ROS 2 套件,請確認您已在終端機中 source 過您的工作空間設定檔 (setup.bash)。

  • Gazebo Sim 運行中: 這個 spawn_entity.py 指令需要 Gazebo Sim 已經在運行中才能成功執行。您通常會先使用一個 launch 檔案啟動 Gazebo,然後在另一個終端機中執行此 spawn 指令。

  • URDF 檔案: 確保您的 twowheel.urdf 檔案內容有效且沒有錯誤。如果 URDF 本身有問題,Gazebo 可能會無法正確載入模型並給出錯誤訊息。




gazebo_ros 是針對 Gazebo 9 (舊版) 和 Gazebo Classic 設計的

而 ros_gz_sim 則是針對新的 Gazebo (GZ) Sim 所設計的

且是 ROS 2 官方推薦的整合方式。

這兩者是不同的套件,提供了不同 Gazebo 版本的 ROS 2 橋接功能。


為什麼推薦使用 ros_gz_sim

  • 官方支持ros_gz_sim 是 Gazebo 專案的官方橋接工具,旨在提供 Gazebo Sim 與 ROS 2 之間的無縫整合。

  • 新功能與效能: Gazebo Sim (或稱 GZ Sim) 提供了許多相較於舊版 Gazebo 的新功能和效能改進,例如更現代的物理引擎和渲染技術。

  • 跨平台相容性ros_gz_sim 提供了 ROS 2 和 Gazebo Sim 之間的通用橋接,可用於任何 ROS 2 支援的平台。

如何將您的工作流從 gazebo_ros 轉換到 ros_gz_sim

您需要將原先使用 gazebo_ros 的命令和啟動檔案替換成 ros_gz_sim 對應的工具。

1. 安裝 ros_gz_sim 套件

您需要先安裝 ros_gz_sim 橋接套件,確保其版本與您的 ROS 2 和 Gazebo Sim 版本相容。

Bash
sudo apt-get install ros-<distro>-ros-gz-sim

將 <distro> 替換為您的 ROS 2 版本,例如 humble 或 iron

2. 啟動 Gazebo Sim

您可以使用 ros_gz_sim 提供的啟動檔案來開啟 Gazebo Sim。

Bash
ros2 launch ros_gz_sim_demos gz_sim.launch.py

這會開啟一個空的 Gazebo 世界。您也可以指定一個世界檔案來啟動 Gazebo:

Bash
ros2 launch ros_gz_sim_demos gz_sim.launch.py gz_args:="-r /path/to/your/world.sdf"

3. 載入模型

ros_gz_sim 使用 ros_gz_sim 套件中的 create 節點來產生實體,而不是舊版的 spawn_entity.py。您通常會在啟動檔案中完成此步驟。

例如,在您的 .launch.py 檔案中加入以下內容:

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

def generate_launch_description():
    pkg_ros_gz_sim = get_package_share_directory('ros_gz_sim')
    
    # 載入 URDF/SDF 模型
    urdf_path = os.path.join(
        get_package_share_directory('your_robot_description_package'),
        'urdf',
        'twowheel.urdf'
    )
    
    spawn_entity_node = Node(
        package='ros_gz_sim',
        executable='create',
        output='screen',
        arguments=[
            '-file', urdf_path,
            '-name', 'twowheel_amr',
            '-x', '0',
            '-y', '0',
            '-z', '0.5'
        ]
    )
    
    return LaunchDescription([
        spawn_entity_node
    ])

總結:從 gazebo_ros 轉移到 ros_gz_sim 是正確且符合未來的方向。它需要您更改啟動指令和啟動檔案的內容,但能讓您使用最新版本的 Gazebo 和其提供的所有功能。





ROS 2 cmd_vel 指令從 gazebo_ros 轉換到 ros_gz_sim

  將您的 ROS 2 cmd_vel 指令從 gazebo_ros 轉換到 ros_gz_sim

主要是要將 topic 名稱從 /twowheel_amr/cmd_vel 調整為 ros_gz_sim 預設的橋接格式。



問題分析

gazebo_ros 和 ros_gz_sim 兩者之間最大的不同在於 ROS Topic 和 Gazebo Topic 之間的命名約定

  • gazebo_ros: 舊版的 Gazebo 橋接器通常會為每個機器人模型創建一個獨立的命名空間,例如 /twowheel_amr。因此,cmd_vel topic 的完整名稱會是 /twowheel_amr/cmd_vel

  • ros_gz_sim: 新版 ros_gz_sim 的橋接器,預設的 Topic 命名格式為 /model/<model_name>/cmd_vel。這提供了一種更標準且可預測的命名模式,方便跨不同模型進行控制。


解決方案

根據 ros_gz_sim 的命名慣例,您需要修改 ROS Topic 的名稱。

將原來的指令:

Bash
ros2 topic pub -r 5 /twowheel_amr/cmd_vel geometry_msgs/Twist "{linear: {x: 0.2}, angular: {z: 0.0}}"

更改為:

Bash
ros2 topic pub -r 5 /model/twowheel_amr/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.2}, angular: {z: 0.0}}"

額外注意事項

  1. 確保橋接正常運作: 在 gz_sim 中,您需要確保 ros_gz_bridge 橋接節點已經運行,並正確設定了從 ROS 2 /model/twowheel_amr/cmd_vel Topic 到 Gazebo 的 cmd_vel Topic 的轉發。

  2. Twist 訊息類型: 請注意,ros_gz_bridge 的 ROS 2 訊息類型是 geometry_msgs/msg/Twist,與舊版指令中的 geometry_msgs/Twist 略有不同。在 ROS 2 中,通常會加上 /msg 子目錄以明確指定訊息類型。

  3. 模型與驅動: 您的 Gazebo 模型 (twowheel_amr) 必須包含能夠接收 cmd_vel 命令並驅動車輪的 Gazebo 插件(例如 libignition-gazebo-diff-drive-system)。如果沒有這個插件,即使您發布了正確的 Topic,模型也不會移動。


2025年9月10日 星期三

Gzserver 和 Gzclient 確實可以在不同 IP 的主機上運行

 Gzserver 和 Gzclient 確實可以在不同 IP 的主機上運行,這是 Gazebo 模擬器設計的核心優勢之一,允許您將複雜的物理模擬(在 Gzserver 上)與圖形化視覺化(在 Gzclient 上)分開。這對於遠端控制、高效能計算或多使用者協作非常有用。

如何建立 Gzserver 與 Gzclient 的遠端連線

要讓 Gzserver 和 Gzclient 在不同 IP 的主機上成功連線,您需要確保以下條件和步驟:

步驟一:設定環境變數

這是最關鍵的步驟。Gzserver 和 Gzclient 預設會尋找一個名為 GAZEBO_MASTER_URI 的環境變數來建立連線。這個變數會告訴客戶端伺服器的位置。

  • 在運行 Gzserver 的主機上:

    Gzserver 在啟動時會綁定一個主機位址和埠號。您可以透過 export 設定 GAZEBO_MASTER_URI,也可以讓它使用預設值。預設的埠號是 11345

    # 這行指令是選擇性,如果未指定,Gazebo會自動使用預設的 'localhost:11345'
    export GAZEBO_MASTER_URI=http://<伺服器IP位址>:11345
    

    然後,啟動伺服器:

    gzserver --verbose empty.world
    
  • 在運行 Gzclient 的主機上:

    這是最重要的一步。您必須將客戶端的 GAZEBO_MASTER_URI 設定為伺服器的 IP 位址。

    # 這裡的 <伺服器IP位址> 是運行 gzserver 的主機的實際 IP
    export GAZEBO_MASTER_URI=http://<伺服器IP位址>:11345
    

    接著,啟動客戶端:

    gzclient
    

如果一切設定正確,Gzclient 將會連線到遠端伺服器,並開始顯示模擬畫面。

步驟二:確保網路連線暢通

  • 防火牆設定:請確保伺服器主機的防火牆允許來自客戶端主機的連線,特別是 Gazebo 使用的 11345 埠號。如果需要,您可能需要新增一條防火牆規則。

  • IP 位址:確保客戶端填寫的 IP 位址是伺服器主機在網路中的可達位址。如果兩台主機在同一個區域網路,通常是 192.168.x.x10.0.x.x 這樣的位址。


ROS2 與 Gazebo Sim (新版) 的連線

對於 ROS2 和 Gazebo Sim(例如 Fortress 或 Garden),連線機制更加簡化。它依賴於 ROS2 的 DDS (Data Distribution Service) 通訊協定。

ROS2 的節點(包括 Gazebo Sim 的 ROS 插件)使用 DDS 進行發現和通訊。只要兩台電腦在同一個網路中,且 ROS2 的環境變數(例如 ROS_DOMAIN_ID)設定一致,它們就能自動找到彼此並建立連線。

因此,在 ROS2 環境中,您通常只需要確保:

  1. ROS2 環境變數一致:在兩台主機上執行 source 指令來載入相同的 ROS2 版本,並確保 ROS_DOMAIN_ID 環境變數相同。

  2. 啟動 Gazebo Sim

    • 在伺服器主機上啟動 Gazebo Sim,通常是透過 ROS2 啟動檔案:

      Bash
      ros2 launch my_robot_pkg my_robot.launch.py
      
    • 在客戶端主機上,您只需要啟動一個 ROS 節點來處理資料或發送命令,例如啟動 RVIZ2 來視覺化:

      Bash
      ros2 run rviz2 rviz2
      

總之,Gzserver 和 Gzclient 可以在不同主機上連線。在 Gazebo Classic 中,這需要手動設定 GAZEBO_MASTER_URI;而在 ROS2 的新版 Gazebo Sim 中,它則透過更先進的 DDS 機制自動完成。



2025年9月8日 星期一

ROS2 pakeage node 目錄說明

:~/ros2_compose/ros2_data/ros2_ws4/src/twowheel_bot

├── CMakeLists.txt

├── package.xml

├── setup.cfg

├── setup.py

├── <rviz>
├──  <resource>
├──< include >
├── <launch>
├── <src>
├── <twowheel_bot>
└── <urdf>

CMakeLists.txt
ROS 2(ament_cmake)的建置設定。即使主要寫 Python,也常放一個最小 CMake 以相容      colcon build;若有 C++ 節點/庫,就在這裡 add_executable()/install()。

package.xml
套件中繼資料與相依(<depend>rclpy</depend> 等)。rosdep、建置系統與發佈都依此辨識。

setup.cfg
Python 套件安裝行為的輔助設定(例如安裝腳本路徑)。可有可無,視專案需求。

setup.py
Python 套件打包/安裝腳本(ament_python)。在這裡宣告:
要安裝的資料檔(URDF、launch、rviz…)
entry_points.console_scripts:把 Python 函式掛成可執行檔(如 simple_controller = twowheel_bot.simple_controller:main)

include/
C++ 標頭檔放這裡(例如 include/twowheel_bot/xxx.hpp)。若只做 Python 可留空或不使用。

launch/
/放啟動檔(.launch.py),用來一次啟多個節點/參數,例如:
display.launch.py:載入 URDF、啟 robot_state_publisher、開 RViz。
teleop_demo.launch.py:啟 Python 控制節點並帶參數。
resource/
ament 資源索引目錄;裡面通常有一個與套件同名的空檔(resource/twowheel_bot),讓 ros2 pkg 能發現此套件。

rviz/
RViz 設定檔(.rviz)。例如 tf_view.rviz:預先配置 Fixed Frame、Grid、RobotModel 等。

src/
C++ 原始碼目錄(與 include/ 一起用)。例如 src/driver.cpp、src/node.cpp;最後由 CMakeLists.txt 生成可執行檔。

twowheel_bot/
Python 套件模組根目錄(對應 setup.py 的 packages=[...])。常見內容:
__init__.py:標記為 Python 套件。
simple_controller.py:發佈 /cmd_vel 的 Python 節點(rclpy),支援參數與鍵盤控制等。
其他共用程式(utils、drivers)。

urdf/
機器人描述檔(.urdf / .xacro)、網格 meshes/(若有)。例如 twowheel.urdf.xacro:底盤+左右輪的連結、關節、慣性、材質。

Python + C++ 可共存:twowheel_bot/ 走 Python;src//include/ 走 C++。兩邊分別由 setup.py 與 CMakeLists.txt 負責安裝。
新增/改檔後記得:colcon build → source install/setup.bash。
要讓 RViz/URDF/launch 等隨套件安裝,記得在 setup.py 的 data_files 把相對路徑列進去(或在 CMake 用 install(DIRECTORY ...))。


Python + C++ 可共存:twowheel_bot/ 走 Python;src//include/ 走 C++。兩邊分別由 setup.py 與 CMakeLists.txt 負責安裝。
新增/改檔後記得:colcon build → source install/setup.bash。
要讓 RViz/URDF/launch 等隨套件安裝,記得在 setup.py 的 data_files 把相對路徑列進去(或在 CMake 用 install(DIRECTORY ...))。


__init__.py:讓此資料夾成為可匯入的 Python 套件。
nodes/:很薄的執行入口(main()),entry_points 指到這裡最清楚,例如 twowheel_bot.nodes.teleop:main。
controllers/:控制迴路、狀態機(PID、路徑追蹤、導航策略…)。
drivers/:硬體 I/O(馬達、IMU、里程計、序列埠、CAN、GPIO)。
utils/(或 common/):共用工具(參數處理、時間/座標換算、logging helper)。
kinematics/:運動學/座標轉換(差速/全向/逆運動學)。
teleop/:鍵盤/搖桿/遙控橋接。
interfaces/:對 ROS 介面(msg/service/action)的包裝、型別轉換。
simulation/:Gazebo/仿真專用節點或橋接(spawn、reset、時鐘)。
config/(也可放在套件根目錄):YAML 參數檔(啟動時 --ros-args --params-file 載入)。
tests/:單元/整合測試(pytest)

meshes/
用途:存放機器人 3D 幾何模型,供 URDF/SDF 在 visual(外觀)與 collision(碰撞)使用。
常見副檔名:.stl、.dae(Collada)、.obj、貼圖 .png/.jpg。
重點建議
單位與座標:URDF 以 公尺(m) 為單位;遵循 REP-103(X 前、Y 左、Z 上)。
原點:網格本身的原點最好在輪心/連結中心;若不在,改用 URDF <origin ...> 修正位置/角度。
視覺 vs 碰撞:碰撞模型要低面數。可分資料夾:
meshes/
  visual/    # 高精度外觀
  collision/ # 低多邊形碰撞
貼圖/材質:.dae 可綁貼圖;Gazebo 也可用 material script。把貼圖一併放進套件。
URDF 參考寫法:
<visual>
  <origin xyz="0 0 0" rpy="0 0 0"/>
  <geometry>
    <mesh filename="package://twowheel_bot/meshes/visual/base.stl" scale="1 1 1"/>
  </geometry>
</visual>
<collision>
  <geometry>
    <mesh filename="package://twowheel_bot/meshes/collision/base.stl"/>
  </geometry>
</collision>

scripts/
用途:存放可執行腳本(多為 Python 節點或 Shell 工具)。ROS 傳統慣例用 scripts/(複數)。
重點建議(ROS 2/ament_python)
Python 節點首選:把程式放 套件模組目錄(例 twowheel_bot/)並用 entry_points 暴露;scripts/ 通常放 shell 或不需作為 Python 模組匯入的工具。
Shebang & 權限:腳本需有 shebang、執行權限:
#!/usr/bin/env python3
chmod +x scripts/calibrate_wheels.py

安裝到套件(兩種方式):
entry_points(推薦):程式放在 twowheel_bot/ 內,於 setup.py:
entry_points={
  'console_scripts': [
    'simple_controller = twowheel_bot.simple_controller:main',
    'teleop_key = twowheel_bot.teleop.key:main',
  ],
}

安裝 scripts 資料夾:用 data_files 讓腳本以檔案形式安裝(適合 .sh、工具腳本):
data_files=[
  ('share/ament_index/resource_index/packages', ['resource/twowheel_bot']),
  ('share/twowheel_bot', ['package.xml']),
  ('share/twowheel_bot/launch', ['launch/display.launch.py']),
  ('share/twowheel_bot/rviz',   ['rviz/tf_view.rviz']),
  ('share/twowheel_bot/urdf',   ['urdf/twowheel.urdf.xacro']),
  ('share/twowheel_bot/scripts',['scripts/calibrate_wheels.py']),  # ←
]

執行時:
ros2 run twowheel_bot simple_controller         # entry_points
# 或(若用純 scripts 檔案)
ros2 pkg prefix twowheel_bot && ./install/.../share/twowheel_bot/scripts/calibrate_wheels.py

小結
meshes/:放 3D 模型;注意單位、原點、座標與「視覺/碰撞」分離。
scripts/:放可執行腳本;ROS 2 建議 Python 節點以 entry_points 方式發佈,scripts/ 多用於 shell/工具或非模組化 Python 腳本。

2025年9月7日 星期日

ROS2 建立 workapace , package node , build 範例說明

 下面給你「一步到位」的順序+可直接複製的範例(含 Python/C++ 兩種做法)。

範例使用工作區名:~/ros2_ws_demo,套件名:my_pkg.

1) 建立 Workspace

# 建立目錄結構 mkdir -p ~/ros2_ws_demo/src cd ~/ros2_ws_demo # 只載入系統 ROS 2 source /opt/ros/humble/setup.bash

2A) 建立 Python 套件 (rclpy)

cd ~/ros2_ws_demo/src ros2 pkg create my_pkg --build-type ament_python --dependencies rclpy std_msgs

最小節點(my_pkg/my_pkg/talker.py):

#!/usr/bin/env python3 import rclpy from rclpy.node import Node from std_msgs.msg import String class Talker(Node): def __init__(self): super().__init__('talker') self.pub = self.create_publisher(String, 'chatter', 10) self.create_timer(0.5, self.tick) def tick(self): msg = String(); msg.data = 'hello ros2' self.pub.publish(msg) def main(): rclpy.init(); rclpy.spin(Talker()); rclpy.shutdown() if __name__ == '__main__': main()

setup.pyentry_points 增加(已自帶,補一行即可):

'console_scripts': [ 'talker = my_pkg.talker:main', ],

2B) 建立 C++ 套件 (rclcpp)

cd ~/ros2_ws_demo/src ros2 pkg create my_pkg_cpp --build-type ament_cmake --dependencies rclcpp std_msgs

最小節點(my_pkg_cpp/src/talker.cpp):

#include "rclcpp/rclcpp.hpp" #include "std_msgs/msg/string.hpp" using std::placeholders::_1; int main(int argc, char** argv){ rclcpp::init(argc, argv); auto node = rclcpp::Node::make_shared("talker_cpp"); auto pub = node->create_publisher<std_msgs::msg::String>("chatter", 10); rclcpp::WallTimer<std::chrono::milliseconds> *timer; timer = new rclcpp::WallTimer<std::chrono::milliseconds>( std::chrono::milliseconds(500), [pub](){ auto msg = std_msgs::msg::String(); msg.data = "hello ros2"; pub->publish(msg); }); node->create_wall_timer(std::chrono::milliseconds(500), [pub](){ auto msg = std_msgs::msg::String(); msg.data = "hello ros2"; pub->publish(msg); }); rclcpp::spin(node); rclcpp::shutdown(); return 0; }

my_pkg_cpp/CMakeLists.txt 增加可執行檔與安裝:

add_executable(talker src/talker.cpp) ament_target_dependencies(talker rclcpp std_msgs) install(TARGETS talker DESTINATION lib/${PROJECT_NAME})

3)(可選)建立 Launch

~/ros2_ws_demo/src/my_pkg/launch/demo.launch.py

from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node(package='my_pkg', executable='talker', name='talker_py'), # Node(package='my_pkg_cpp', executable='talker', name='talker_cpp'), # 若用 C++ ])

4) 建置

cd ~/ros2_ws_demo colcon build --symlink-install

5) 載入環境

source install/setup.bash

6) 執行與檢查

# 直接跑節點 ros2 run my_pkg talker # Python # ros2 run my_pkg_cpp talker # C++ # 或用 launch ros2 launch my_pkg demo.launch.py # 檢查 ros2 node list ros2 topic echo /chatter

小提示

  • 每次更動程式後:colcon buildsource install/setup.bash

  • 若有多個 workspace,確保最後 source 的是你要用的那個。

  • 新增相依套件:rosdep install -i --from-paths src -y



2025年9月5日 星期五

URDF 內的 LiDAR 表示及 Gazebo 驅動模擬

 

1. URDF 內的 LiDAR 是怎麼表示的

  • 在 URDF/Xacro 中,LiDAR 本體會是一個 link(例如 lidar_link),通常是個小圓柱體(僅供視覺化)。

  • 接著用一個 joint(通常是 fixed)把 lidar_link 固定到 base_link 或車體上。

  • 在 LiDAR link 裡,用 <gazebo> 標籤附加 Gazebo 插件,這樣模擬才會真的產生雷射掃描資料。


2. libgazebo_ros_ray_sensor.so 插件

這是 gazebo_ros 套件提供的 Ray Sensor Plugin。它會把 Gazebo 模擬的 Ray sensor(光線投射)封裝成 ROS 2 的 Topic。

主要功能:

  • 在 Gazebo 中模擬雷射掃描器(LiDAR)。

  • 透過 ROS 2 topic 輸出 sensor_msgs/msg/LaserScansensor_msgs/msg/PointCloud2

  • 可設定角度範圍、解析度、更新頻率、噪聲模型。


3. URDF / Xacro 實際範例

<!-- LiDAR 本體 link --> <link name="lidar_link"> <visual> <geometry> <cylinder length="0.05" radius="0.03"/> </geometry> <material> <color rgba="0 1 0 1"/> </material> </visual> </link> <!-- 固定在 base_link 上 --> <joint name="lidar_joint" type="fixed"> <parent link="base_link"/> <child link="lidar_link"/> <origin xyz="0.0 0.0 0.1" rpy="0 0 0"/> </joint> <!-- Gazebo 插件 --> <gazebo reference="lidar_link"> <sensor type="ray" name="lidar_sensor"> <pose>0 0 0 0 0 0</pose> <visualize>true</visualize> <update_rate>10</update_rate> <ray> <scan> <horizontal> <samples>360</samples> <resolution>1</resolution> <min_angle>-3.14159</min_angle> <max_angle>3.14159</max_angle> </horizontal> </scan> <range> <min>0.12</min> <max>12.0</max> <resolution>0.01</resolution> </range> <noise> <type>gaussian</type> <mean>0.0</mean> <stddev>0.01</stddev> </noise> </ray> <!-- 插件: ROS 2 雷射轉換 --> <plugin name="gazebo_ros_ray_sensor" filename="libgazebo_ros_ray_sensor.so"> <ros> <namespace>/</namespace> <remapping>scan:=/scan</remapping> </ros> <output_type>sensor_msgs/LaserScan</output_type> <frame_name>lidar_link</frame_name> </plugin> </sensor> </gazebo>

4. 關鍵說明

  • <sensor type="ray">:告訴 Gazebo 這是一個 Ray Sensor(雷射)。

  • <ray><scan>…</scan></ray>:定義雷射的掃描角度與分辨率(360 點、360°)。

  • <plugin filename="libgazebo_ros_ray_sensor.so">:把 Gazebo 的 Ray Sensor 綁定到 ROS 2。

  • <output_type>:決定輸出的資料型別(LaserScan / PointCloud2)。

  • <remapping>:改 ROS topic 名稱(這裡輸出到 /scan)。

  • <frame_name>:指定發送 TF 的 frame id(通常是 lidar_link)。


  • 常見主題名稱/scan(2D LaserScan)或 /points / /points_raw(PointCloud2)。實際名稱取決於你在 URDF/Gazebo 插件裡的 <remapping> 設定。

  • 如何確認

    ros2 topic list | grep -E 'scan|point' ros2 topic info /scan # 或 ros2 interface show sensor_msgs/msg/LaserScan
  • RViz2 顯示 LaserScan

    1. rviz2 → Fixed Frame 設 odom(或 base_link)。

    2. Add → By display type → LaserScan

    3. Topic 選剛剛找到的 …/scan;Frame 會用 frame_id(常是 lidar_link)。

    4. 若看不到:在 LaserScan display 裡把 Size (m) 調到 0.02~0.05、確認時間同步(/clock)與 TF 完整。

  • RViz2 顯示 PointCloud2(若輸出點雲):

    1. Add → PointCloud2

    2. Topic 選 /points(或你的點雲 topic)。

    3. Style 選 Points,Size 0.02~0.05。

小檢查:你現在 plugin 輸出的是 sensor_msgs/LaserScan 還是 sensor_msgs/PointCloud2?(告訴我型別,我幫你把 RViz 的設定精準化。)

2025年9月4日 星期四

ROS2 for gzserver , gzclient

 下面是 Gazebo Classicgzserver / gzclient 常用指令精簡表(不含新一代 gz sim):

gzserver(物理模擬伺服器)

  • 啟動空世界(純伺服器,無 GUI)
    gzserver /usr/share/gazebo-11/worlds/empty.world

  • 詳細輸出(除錯)
    gzserver --verbose <world.sdf|world>

  • 開始時暫停
    gzserver --pause <world>

  • 設定隨機種子(重現性)
    gzserver --seed <int> <world>

  • 只跑 N 個 step 後退出(批次/測試)
    gzserver --iters <N> <world>

  • 載入「伺服器插件」(e.g., ROS 工廠/控制)
    gzserver -s libgazebo_ros_factory.so <world>
    gzserver -s libgazebo_ros_init.so <world>

  • 顯示說明 / 版本
    gzserver --help gzserver --version

gzclient(圖形介面客戶端)

  • 連線到已啟動的 gzserver
    gzclient

  • 詳細輸出
    gzclient --verbose

  • 載入「GUI 插件」(面板/工具)
    gzclient -g libgazebo_gui_overlay.so

  • 說明 / 版本
    gzclient --help gzclient --version

常見啟動樣板

  • 伺服器與客戶端分開:

    export ALSOFT_DRIVERS=null # 避免 ALSA 音效錯誤(可選) gzserver /usr/share/gazebo-11/worlds/empty.world --verbose & gzclient

  • gzserver --verbose empty.world \
      -s libgazebo_ros_init.so \
      -s libgazebo_ros_factory.so \
      -s libgazebo_ros_force_system.so
         gzclient 

         # 直接用檔案(不用 topic)spawn:
         ros2 run gazebo_ros spawn_entity.py -entity (twowheel_amr) -file  (twowheel.urdf)

  • 直接用 wrapper 一起開(server+client):
    gazebo --verbose /usr/share/gazebo-11/worlds/empty.world

  • 與 ROS 2 整合(Classic):

    # 允許從 /robot_description 動態生成模型 gzserver -s libgazebo_ros_factory.so /usr/share/gazebo-11/worlds/empty.world & ros2 run gazebo_ros spawn_entity.py -entity my_bot -topic /robot_description

常用環境變數(Classic)

  • GAZEBO_RESOURCE_PATH:worlds、materials 等資源搜尋路徑

  • GAZEBO_MODEL_PATH:模型搜尋路徑(.sdf/.config 的目錄)

  • ALSOFT_DRIVERS=null:關閉 OpenAL 音效(無音效卡時很有用)


 

ROS2 apt install SLAM TOOL

 [SLAM建圖][儲存地圖][AMCL定位][Nav2導航][移動控制]


🔧 1. 安裝套件

bash
sudo apt update sudo apt install ros-humble-navigation2 ros-humble-nav2-bringup \ ros-humble-slam-toolbox ros-humble-map-server \ ros-humble-amcl ros-humble-rviz2

錯誤分析:ros-humble-map-server 找不到

您收到的錯誤訊息 E: Unable to locate package ros-humble-map-server 表示您的系統找不到名為 ros-humble-map-server 的套件。

這是一個非常常見的錯誤,原因有以下幾點:

  1. 套件名稱不正確:在 ROS2 Humble 中,map_server 套件已經被整合到 navigation2 框架中。它不再是一個獨立的套件,而是作為 navigation2 的一部分。

  2. 軟體庫未更新:您的 apt 套件列表可能已經過時,導致無法找到新套件。

  3. ROS2 軟體庫未添加:您可能沒有正確添加 ROS2 的軟體庫到您的 sources.list


解決方案

要解決這個問題,您應該安裝整個 navigation2 套件,因為 map_server 已經是其中的一部分。

步驟 1:更新套件列表

在安裝任何新套件之前,請務必更新您的本地套件清單。

Bash
sudo apt-get update

步驟 2:安裝 navigation2

navigation2 包含了 ROS2 的所有導航功能,其中也包含了 map_server

Bash
sudo apt-get install ros-humble-navigation2

這個指令會自動安裝 map_server 以及所有其他與導航相關的套件,例如:

  • amcl:自適應蒙特卡洛定位。

  • slam_toolbox:用於即時 SLAM。

  • nav2_bringup:包含許多啟動檔案。

步驟 3:確認 map_server 已安裝

安裝完成後,您可以使用 ros2 指令來確認 map_server 是否已經可用。

Bash
ros2 pkg list | grep map_server

如果命令返回 map_server,則表示套件已成功安裝。

總結:您不需要單獨安裝 map-server。在 ROS2 Humble 中,它已經被整合到 navigation2 中。通過安裝 ros-humble-navigation2,您將獲得所需的所有工具,不僅僅是 map-server,還包括一個完整的導航堆疊。