工作空間與套件結構

2026-07-18
  • ros2
  • colcon
  • workspace
  • package

問題定義

前一節我們安裝好 ROS2 本體,但那只是「系統套件」——你自己寫的節點程式碼要放在哪裡?怎麼組織?這一節要建立的是你之後所有專案程式碼的容器:工作空間(workspace)與套件(package)。

核心概念說明

工作空間:一個獨立的編譯環境

ROS2 用 colcon 作為建置工具,一個「工作空間」就是一個特定結構的資料夾,裡面放著你要編譯的所有套件原始碼。標準結構長這樣:

text
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. 建立工作空間資料夾

bash
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src

2. 建立一個 Python 套件

bash
ros2 pkg create --build-type ament_python my_package

預期輸出

text
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 指令看整體結構會更清楚:

bash
cd ~/ros2_ws/src
tree my_package
text
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.pyPython 套件的安裝設定(entry points,也就是之後 ros2 run 找得到你節點的關鵺)
my_package/實際放你的節點程式碼(.py 檔)的資料夾
test/自動產生的程式碼風格檢查測試,之後在 測試:launch_testing 會深入討論

3. 檢查 package.xml 內容

bash
cat my_package/package.xml
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>

之後如果你的節點需要用到其他套件(例如 rclpystd_msgs),就要在這裡加上 <depend>rclpy</depend> 這類宣告,rosdep 才知道要幫你安裝哪些依賴。

常見錯誤與除錯技巧

錯誤一:套件名稱包含不合法字元

text
ERROR:catkin_pkg.package:Package name "my-package" contains invalid characters

原因:ROS2 套件名稱只能用小寫英文字母、數字與底線,不能用連字號 - 或大寫字母。

排除方式:把名稱裡的 - 換成 _,例如 my-package 改成 my_package

錯誤二:在錯誤的資料夾層級建立套件

text
ERROR: package.xml already exists at this directory level

原因:套件必須建立在工作空間的 src/ 資料夾「裡面」,而不是巢狀地在另一個套件內部建立套件。

排除方式:確認你目前所在的資料夾是 ~/ros2_ws/src,而不是 ~/ros2_ws/src/my_package 或更深層的路徑:

bash
pwd
# 應該顯示 /home/user/ros2_ws/src

小結

一個工作空間管理多個套件,套件是程式碼的最小組織單位,package.xml 負責宣告依賴。這個結構看起來多一層資料夾,但好處是依賴管理與建置流程都能自動化——下一節會實際把這個套件編譯起來,並且處理依賴安裝的問題。

延伸閱讀

常見問題

faq_01.log
一個工作空間裡可以放多少個套件?
沒有硬性限制,實務上一個工作空間常常放幾十個套件。大型專案通常會依功能拆成多個工作空間(例如驅動、演算法、應用各自一個),再視需要 source 對應的 overlay。
faq_02.log
src 資料夾裡的套件一定要用 git 管理嗎?
不一定,但強烈建議。實務上通常會用一個 .repos 檔案(搭配 vcstool)記錄所有子套件的 git 位置與版本,方便團隊成員或 CI 環境重建整個工作空間。
faq_03.log
ament_python 和 ament_cmake 選哪個?可以混用嗎?
同一個工作空間裡可以同時有 Python 套件和 C++ 套件,彼此透過標準的 ROS2 介面(主題、服務等)溝通即可,不需要語言一致。選擇上,原型驗證或邏輯較單純的節點適合 Python;效能敏感或要跟現有 C++ 函式庫串接的部分適合用 ament_cmake。