4. 工作空间与功能包:创建ROS2工作空间,使用colcon构建功能包,理解package.xml和setup.py
好,咱们正式开始动手了。
前面聊了那么多概念,什么节点、话题、服务……说白了,它们都得有个“家”才能住进去。这个“家”,就是工作空间和功能包。
我个人习惯,拿到一个新机器人或者新项目,第一件事就是搭好工作空间。就像程序员写代码前先建好文件夹一样,这是基本功。
4.1 什么是工作空间?
工作空间(Workspace),你可以把它想象成一个项目文件夹。里面装着你的代码、依赖的库、编译后的文件等等。
ROS2里最常用的是 colcon 工作空间。它的典型结构长这样:
ros2_ws/ # 工作空间根目录
├── src/ # 源代码目录(放功能包)
├── build/ # 编译中间文件(自动生成)
├── install/ # 安装文件(自动生成,可执行文件在这里)
└── log/ # 编译日志(自动生成)
你只需要手动创建 src 文件夹,剩下的 build、install、log 都是 colcon build 命令自动生成的。
ros2_ws,简单好记。你叫 my_robot_ws 也行,别用中文和空格。
4.2 创建你的第一个工作空间
打开终端,跟着我敲:
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
嗯,就两行。现在你有了一个空的工作空间。
但光有壳子不行,得往里面放功能包。
4.3 功能包:ROS2的最小单元
功能包(Package)是ROS2里组织代码的基本单位。一个功能包可以包含节点、配置文件、启动文件、消息定义等等。
你可以把它理解成一个独立的软件模块。比如一个“摄像头驱动包”、一个“激光雷达数据处理包”。
创建功能包,我推荐用 ros2 pkg create 命令。举个例子:
cd ~/ros2_ws/src
ros2 pkg create my_first_pkg \
--build-type ament_python \
--node-name my_first_node
这条命令干了三件事:
- 创建了
my_first_pkg文件夹 - 指定了构建类型为
ament_python(Python包) - 自动生成了一个叫
my_first_node的节点模板
来看看里面有什么:
my_first_pkg/
├── my_first_pkg/ # 同名的Python包目录
│ ├── __init__.py
│ └── my_first_node.py # 节点文件
├── resource/
│ └── my_first_pkg
├── test/ # 测试文件夹
│ ├── test_copyright.py
│ ├── test_flake8.py
│ └── test_pep257.py
├── package.xml # 包描述文件(重要!)
├── setup.py # 安装配置文件(重要!)
├── setup.cfg # setup工具配置
└── package.xml # 包描述文件
package.xml 和 setup.py(Python包)或 CMakeLists.txt(C++包)。少了任何一个,colcon都会报错。
4.4 理解 package.xml:包的“身份证”
打开 package.xml,你会看到类似这样的内容:
<?xml version="1.0"?>
<package format="3">
<name>my_first_pkg</name>
<version>0.0.0</version>
<description>我的第一个ROS2功能包</description>
<maintainer email="your_email@example.com">your_name</maintainer>
<license>Apache-2.0</license>
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
这个文件说白了就是告诉ROS2:
- 你是谁(包名、版本)
- 谁维护你(维护者信息)
- 你依赖谁(运行时依赖,比如
rclpy) - 你怎么编译(构建类型)
package.xml 里声明依赖,结果编译通过,但运行时提示找不到模块。所以,每引入一个外部库,都要在 <exec_depend> 里加上。
4.5 理解 setup.py:Python包的“安装说明书”
对于Python功能包,setup.py 负责告诉系统:
- 哪些文件需要被安装
- 安装到哪个目录
- 入口点(entry_points)在哪里
看一个典型的 setup.py:
from setuptools import find_packages, setup
package_name = 'my_first_pkg'
setup(
name=package_name,
version='0.0.0',
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='your_name',
maintainer_email='your_email@example.com',
description='我的第一个ROS2功能包',
license='Apache-2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'my_first_node = my_first_pkg.my_first_node:main',
],
},
)
这里最关键的,是 entry_points 里的 console_scripts。它定义了可执行命令。
格式是:'命令名 = 包名.文件名:函数名'
比如上面这行,意思就是:你在终端输入 my_first_node,系统就会去执行 my_first_pkg.my_first_node 文件里的 main 函数。
setup.py 或 package.xml,我都会重新编译一次。别偷懒,不然改了不生效,排查起来很头疼。
4.6 使用 colcon 构建功能包
文件写好了,怎么让它跑起来?用 colcon build。
cd ~/ros2_ws
colcon build --packages-select my_first_pkg
解释一下参数:
--packages-select:只编译指定的包,省时间- 如果不加这个参数,会编译整个工作空间的所有包
编译成功后,你会看到 build、install、log 三个文件夹出现。
但这时候还不能直接运行。你需要source环境:
source install/setup.bash
这条命令把编译好的包注册到ROS2环境里。之后你就可以运行节点了:
ros2 run my_first_pkg my_first_node
source install/setup.bash。我建议把它加到 ~/.bashrc 里,一劳永逸:
echo "source ~/ros2_ws/install/setup.bash" >> ~/.bashrc
source ~/.bashrc
4.7 知识体系总览
下面这张图,帮你理清工作空间和功能包的关系:
从这张图可以看得很清楚:
- 你在
src里写代码(功能包) - 用
colcon build编译,生成build、install、log source install/setup.bash让系统找到你的包- 最后用
ros2 run启动节点
嗯,流程就是这么简单。但很多新手会卡在“编译成功但找不到包”这一步。说白了,就是忘了 source。
4.8 本章小结
今天我们干了三件事:
- 创建了工作空间——ROS2代码的根目录
- 创建了功能包——用
ros2 pkg create一键生成 - 理解了核心配置文件——
package.xml管依赖,setup.py管安装 - 用 colcon 编译并运行——
colcon build+source install/setup.bash
这些是ROS2开发的基石。后面的所有章节,都会建立在这个工作空间之上。所以,务必亲手敲一遍,别只看不练。
ModuleNotFoundError,先检查 package.xml 里有没有加依赖。如果遇到 command not found: ros2,说明ROS2环境没 source。这两个坑,我当年都踩过。