3、工作空间与功能包:从零搭建你的ROS项目骨架
好,咱们进入第三章。说实话,这一章是整个ROS开发的基石。你想想看,盖房子总得先搭个脚手架吧?工作空间和功能包就是ROS项目的脚手架。我见过太多新手一上来就写代码,结果编译报错找不到包,折腾半天才发现是工作空间没配好。嗯,咱们今天就把它彻底搞明白。
3.1 工作空间(Workspace)是什么?
工作空间,说白了就是一个文件夹。但它不是普通文件夹,它有一套固定的结构。ROS用它来组织、编译和管理你的代码。
我个人习惯把工作空间放在 ~/ros_ws 下。当然你也可以叫 catkin_ws,都行。关键是里面的结构要对。
一个标准的工作空间长这样:
~/ros_ws/
├── src/ # 源代码目录,放功能包
├── build/ # 编译中间文件(自动生成)
├── devel/ # 编译产物(可执行文件、库等,自动生成)
└── install/ # 安装目录(可选,catkin_make install 后生成)
你只需要手动创建 src 目录,其他都是编译工具自动生成的。
3.2 创建工作空间
来,跟着我敲一遍:
# 创建目录
mkdir -p ~/ros_ws/src
# 进入src目录
cd ~/ros_ws/src
# 初始化工作空间
catkin_init_workspace
# 回到工作空间根目录
cd ~/ros_ws
# 编译
catkin_make
第一次编译后,你会看到 build 和 devel 目录自动出现了。这时候工作空间就搭好了。
source ~/ros_ws/devel/setup.bash
我建议直接写到 ~/.bashrc 里,省得每次都敲。
3.3 功能包(Package)是什么?
工作空间是房子,功能包就是一个个房间。每个功能包完成一个独立的功能。比如一个包负责控制机器人底盘,另一个包负责处理激光雷达数据。
一个功能包必须包含两个文件:
- package.xml:包的元信息,像身份证一样
- CMakeLists.txt:编译规则,告诉编译器怎么编译
缺少任何一个,ROS都不认。我在项目中遇到过有人只复制了代码,忘了带 package.xml,结果编译报错找了半天原因。
3.4 创建功能包
用 catkin_create_pkg 命令创建,语法是:
cd ~/ros_ws/src
catkin_create_pkg 包名 [依赖1] [依赖2] ...
举个例子,创建一个叫 my_robot 的包,依赖 roscpp 和 std_msgs:
cd ~/ros_ws/src
catkin_create_pkg my_robot roscpp std_msgs
执行后,src/my_robot 目录下会自动生成:
my_robot/
├── include/ # 头文件目录
├── src/ # 源代码目录
├── CMakeLists.txt
└── package.xml
2d_robot 就不行,得改成 robot_2d。
3.5 编译功能包
回到工作空间根目录,执行:
cd ~/ros_ws
catkin_make
如果一切顺利,你会看到类似这样的输出:
Base path: /home/yourname/ros_ws
Source space: /home/yourname/ros_ws/src
Build space: /home/yourname/ros_ws/build
Devel space: /home/yourname/ros_ws/devel
...
[100%] Built target my_robot
看到 100% 就说明编译成功了。
roscpp,就执行 sudo apt install ros-noetic-roscpp。我曾经在项目里因为少装了一个 tf2 包,卡了整整一下午。
3.6 package.xml 解析
这个文件是包的身份证。打开看看:
<?xml version="1.0"?>
<package format="2">
<name>my_robot</name>
<version>0.0.0</version>
<description>我的第一个机器人包</description>
<maintainer email="yourname@example.com">yourname</maintainer>
<license>BSD</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>std_msgs</build_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>std_msgs</exec_depend>
</package>
关键字段说明:
| 标签 | 作用 |
|---|---|
<name> |
包名,必须和文件夹名一致 |
<version> |
版本号,方便管理 |
<description> |
描述这个包是干什么的 |
<maintainer> |
维护者信息,别人有问题可以找你 |
<license> |
开源协议,BSD、MIT、GPL等 |
<build_depend> |
编译时依赖 |
<exec_depend> |
运行时依赖 |
package.xml 里的 description 和 maintainer。不然时间久了,自己都忘了这个包是干嘛的。
3.7 CMakeLists.txt 解析
这个文件是编译说明书。ROS用CMake作为编译系统,所以这个文件遵循CMake语法。核心部分如下:
cmake_minimum_required(VERSION 3.0.2)
project(my_robot)
## 查找依赖包
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
)
## 声明头文件路径
include_directories(
include
${catkin_INCLUDE_DIRS}
)
## 声明可执行文件
add_executable(my_robot_node src/my_robot_node.cpp)
## 链接库
target_link_libraries(my_robot_node
${catkin_LIBRARIES}
)
关键部分解读:
- find_package:告诉CMake需要哪些依赖包
- include_directories:指定头文件搜索路径
- add_executable:声明要生成的可执行文件,以及它的源文件
- target_link_libraries:链接需要的库文件
你想想看,如果没有 target_link_libraries,你的代码里调用了ROS的函数,但编译器不知道去哪找这些函数的实现,就会报链接错误。嗯,这个坑我踩过。
3.8 完整流程回顾
咱们把整个流程串起来:
- 创建并初始化工作空间:
mkdir -p ~/ros_ws/src && cd ~/ros_ws/src && catkin_init_workspace - 创建功能包:
catkin_create_pkg my_robot roscpp std_msgs - 编写代码(放到
src/目录下) - 修改
CMakeLists.txt添加编译规则 - 编译:
cd ~/ros_ws && catkin_make - source环境:
source ~/ros_ws/devel/setup.bash
以后每次新增或修改代码,只需要重复第5步和第6步就行。
src 目录下直接 catkin_make。记住,catkin_make 必须在工作空间根目录执行,也就是 ~/ros_ws 下,而不是 ~/ros_ws/src 下。
好了,这一章的内容就到这。工作空间和功能包是ROS开发的起点,看似简单,但细节不少。你只要亲手创建一遍,后面就顺了。下一章咱们开始写真正的ROS节点代码,到时候你会回来感谢这一章的铺垫的。