工作空間與套件結構
- ros2
- colcon
- workspace
- package
問題定義
前一節我們安裝好 ROS2 本體,但那只是「系統套件」——你自己寫的節點程式碼要放在哪裡?怎麼組織?這一節要建立的是你之後所有專案程式碼的容器:工作空間(workspace)與套件(package)。
核心概念說明
工作空間:一個獨立的編譯環境
ROS2 用 colcon 作為建置工具,一個「工作空間」就是一個特定結構的資料夾,裡面放著你要編譯的所有套件原始碼。標準結構長這樣:
ros2_ws/
├── src/ # 所有套件的原始碼放這裡
├── build/ # colcon build 產生的中繼檔案(自動產生,不需要手動管理)
├── install/ # 編譯完成後可執行的成果(自動產生)
└── log/ # 建置紀錄(自動產生)
你只需要手動管理 src/ 資料夾,其他三個都是 colcon build 自動產生的,甚至可以直接刪除重新編譯。
套件:ROS2 程式碼的最小單位
一個「套件」(package)是 ROS2 世界裡程式碼的最小組織單位,裡面至少包含一個 package.xml(描述套件的中繼資料:名稱、版本、依賴)。ROS2 支援兩種主要的建置類型:
ament_python:純 Python 套件,適合快速開發、原型驗證ament_cmake:C++ 套件(或混合 C++/Python),適合效能敏感的模組
package.xml 的角色類似其他語言生態系裡的 package.json(Node.js)或 pyproject.toml(Python)——宣告這個套件叫什麼名字、依賴哪些其他套件,讓 rosdep(依賴安裝工具)與 colcon(建置工具)知道怎麼處理它。
實作範例:建立第一個工作空間與套件
1. 建立工作空間資料夾
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
2. 建立一個 Python 套件
ros2 pkg create --build-type ament_python my_package
預期輸出
going to create a new package
package name: my_package
destination directory: /home/user/ros2_ws/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['user <user@todo.todo>']
licenses: ['TODO: License declaration']
build type: ament_python
dependencies: []
creating folder ./my_package
creating ./my_package/package.xml
creating source folder
creating folder ./my_package/my_package
creating ./my_package/setup.py
creating ./my_package/setup.cfg
creating folder ./my_package/resource
creating ./my_package/resource/my_package
creating ./my_package/my_package/__init__.py
creating folder ./my_package/test
creating ./my_package/test/test_copyright.py
creating ./my_package/test/test_flake8.py
creating ./my_package/test/test_pep257.py
用 tree 指令看整體結構會更清楚:
cd ~/ros2_ws/src
tree my_package
my_package
├── my_package
│ └── __init__.py
├── package.xml
├── resource
│ └── my_package
├── setup.cfg
├── setup.py
└── test
├── test_copyright.py
├── test_flake8.py
└── test_pep257.py
幾個關鍵檔案的角色:
| 檔案 | 用途 |
|---|---|
package.xml | 套件中繼資料:名稱、版本、維護者、依賴的其他套件 |
setup.py | Python 套件的安裝設定(entry points,也就是之後 ros2 run 找得到你節點的關鵺) |
my_package/ | 實際放你的節點程式碼(.py 檔)的資料夾 |
test/ | 自動產生的程式碼風格檢查測試,之後在 測試:launch_testing 會深入討論 |
3. 檢查 package.xml 內容
cat my_package/package.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_package</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="user@todo.todo">user</maintainer>
<license>TODO: License declaration</license>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
之後如果你的節點需要用到其他套件(例如 rclpy、std_msgs),就要在這裡加上 <depend>rclpy</depend> 這類宣告,rosdep 才知道要幫你安裝哪些依賴。
常見錯誤與除錯技巧
錯誤一:套件名稱包含不合法字元
ERROR:catkin_pkg.package:Package name "my-package" contains invalid characters
原因:ROS2 套件名稱只能用小寫英文字母、數字與底線,不能用連字號 - 或大寫字母。
排除方式:把名稱裡的 - 換成 _,例如 my-package 改成 my_package。
錯誤二:在錯誤的資料夾層級建立套件
ERROR: package.xml already exists at this directory level
原因:套件必須建立在工作空間的 src/ 資料夾「裡面」,而不是巢狀地在另一個套件內部建立套件。
排除方式:確認你目前所在的資料夾是 ~/ros2_ws/src,而不是 ~/ros2_ws/src/my_package 或更深層的路徑:
pwd
# 應該顯示 /home/user/ros2_ws/src
小結
一個工作空間管理多個套件,套件是程式碼的最小組織單位,package.xml 負責宣告依賴。這個結構看起來多一層資料夾,但好處是依賴管理與建置流程都能自動化——下一節會實際把這個套件編譯起來,並且處理依賴安裝的問題。
延伸閱讀
常見問題
- 一個工作空間裡可以放多少個套件?
- 沒有硬性限制,實務上一個工作空間常常放幾十個套件。大型專案通常會依功能拆成多個工作空間(例如驅動、演算法、應用各自一個),再視需要 source 對應的 overlay。
- src 資料夾裡的套件一定要用 git 管理嗎?
- 不一定,但強烈建議。實務上通常會用一個 .repos 檔案(搭配 vcstool)記錄所有子套件的 git 位置與版本,方便團隊成員或 CI 環境重建整個工作空間。
- ament_python 和 ament_cmake 選哪個?可以混用嗎?
- 同一個工作空間裡可以同時有 Python 套件和 C++ 套件,彼此透過標準的 ROS2 介面(主題、服務等)溝通即可,不需要語言一致。選擇上,原型驗證或邏輯較單純的節點適合 Python;效能敏感或要跟現有 C++ 函式庫串接的部分適合用 ament_cmake。