ROS2 编译与运行基本流程:colcon build、source 与 ros2 run 一文搞懂
目录
摘要
一、colcon build 的作用
1.1 colcon build 是什么
1.2 colcon build 后会生成哪些目录
二、单独编译某一个功能包
2.1 为什么需要单独编译
2.2 使用 --packages-select 编译指定功能包
2.3 接口包和代码包的编译顺序
三、source install/setup.bash 的作用
3.1 为什么编译后还要 source
3.2 不 source 会出现什么问题
3.3 重新打开终端后还需要 source 吗
四、ros2 run 的基本流程
4.1 ros2 run 的基本格式
4.2 功能包名来自 package.xml
4.3 可执行文件名来自 add_executable
4.4 ros2 run 为什么能找到节点
(1)Package.xml 中功能包名称要正确
(2)CMakeLists.txt 中要生成可执行文件
(3)CMakeLists.txt 中把可执行文件安装到正确位置
(4)编译后要执行:
(5)完整链路可以理解为:
五、修改不同文件后是否需要重新编译
5.1 修改 C++ 源码
5.2 修改 CMakeLists.txt
5.3 修改 package.xml
5.4 修改 msg、srv、action 接口文件
5.5 修改 launch、config、Python 文件
5.6 修改文件后的编译总结表
六、常见问题总结
6.1 colcon build 成功但 ros2 run 找不到节点
6.2 修改代码后运行结果没有变化
6.3 ros2 pkg list 找不到功能包
6.4 找不到自定义 msg、srv、action 接口
七、本章总结
7.1 colcon build 的核心作用
7.2 source 的核心作用
7.3 ros2 run 的核心理解
摘要
前两篇文章已经分别讲解了 ROS2 工程结构基础,以及 ROS2 C++ 功能包中最重要的两个配置文件:package.xml和CMakeLists.txt。
第一篇主要讲:
工作空间 功能包 src、build、install、log msg、srv、action链接如下:
一文搞懂 ROS2 工程结构:工作空间、功能包、msg/srv/action 自定义接口-CSDN博客https://blog.csdn.net/m0_58954356/article/details/161802673?spm=1001.2014.3001.5501第二篇主要讲:
package.xml CMakeLists.txt find_package add_executable ament_target_dependencies install链接如下:
ROS2 功能包配置文件详解:package.xml 与 CMakeLists.txt 一文搞懂-CSDN博客https://blog.csdn.net/m0_58954356/article/details/161804636?spm=1001.2014.3001.5501但是,配置文件写完之后,ROS2 程序并不会自动运行。我们还需要理解完整的编译与运行流程。
本篇主要讲解 ROS2 中非常重要的几个命令和概念:
colcon build source install/setup.bash ros2 run --packages-select --symlink-install通过本篇文章,需要重点理解:
- colcon build 到底做了什么
- source install/setup.bash 为什么必须执行
- ros2 run 为什么能找到节点
- 修改不同文件后是否需要重新编译
- 编译成功但运行失败应该如何排查
具体的 Topic、Service、Action 小车控制代码,会放到下一篇代码实践中继续讲解。
除此之外ROS2其他相关学习博客链接如下:
ROS2 常见消息类型保姆级教程-CSDN博客https://blog.csdn.net/m0_58954356/article/details/161693378?spm=1001.2014.3001.5501ROS2 话题通信实战:消息对象、Publisher 发布器与 Subscriber 订阅器保姆级教程-CSDN博客
https://blog.csdn.net/m0_58954356/article/details/161702288?spm=1001.2014.3001.5501
史上最全 ROS2 常用命令保姆级教程:节点、话题、消息结构、参数、服务和动作一篇讲透-CSDN博客https://blog.csdn.net/m0_58954356/article/details/161726502?spm=1001.2014.3001.5501
一、colcon build 的作用
1.1 colcon build 是什么
colcon build是 ROS2 中最常用的编译命令。
一般需要在工作空间根目录执行。
例如:
cd ~/agilex_open_class_ws colcon build这里的agilex_open_class_ws是工作空间。
执行colcon build后,ROS2 会扫描工作空间src目录下的功能包,并根据每个功能包中的配置文件进行编译。
主要会读取:
package.xml CMakeLists.txt其中:
package.xml 用来识别功能包信息和依赖关系 CMakeLists.txt 用来描述 C++ 编译和安装规则1.2 colcon build 后会生成哪些目录
执行:
colcon build之后,工作空间中通常会出现三个目录:
build install log例如:
agilex_open_class_ws/ ├── src ├── build ├── install └── log这三个目录的作用如下:
| 目录 | 作用 |
|---|---|
| build | 存放编译过程中产生的中间文件 |
| install | 存放编译安装后的结果 |
| log | 存放编译过程中的日志 |
其中最重要的是:
install因为后面ros2 run、ros2 launch通常都会从 install 空间中查找已经安装好的程序、脚本、接口文件等。
二、单独编译某一个功能包
2.1 为什么需要单独编译
在实际开发中,一个工作空间中可能有很多功能包。
例如:
agilex_open_class_ws/ └── src ├── limo_learning ├── limo_msgs ├── robot_description ├── navigation_pkg └── sensor_driver如果每次都执行:
colcon build就会编译整个工作空间。
- 当功能包很多时,编译时间会比较长。
- 所以实际开发中,经常只编译当前修改的功能包。
2.2 使用 --packages-select 编译指定功能包
只编译limo_learning:
colcon build --packages-select limo_learning只编译limo_msgs:
colcon build --packages-select limo_msgs这个命令的意思是:
只选择指定功能包进行编译例如修改了小车控制代码:
src/limo_learning/src/limo_topic_cmd.cpp那么可以执行:
colcon build --packages-select limo_learning source install/setup.bash这样比完整编译整个工作空间更快。
2.3 接口包和代码包的编译顺序
如果修改的是自定义接口包,例如:
limo_msgs/msg/LimoStatus.msg limo_msgs/srv/LimoSrv.srv limo_msgs/action/LimoAction.action通常建议先编译接口包:
colcon build --packages-select limo_msgs source install/setup.bash如果代码包limo_learning依赖了limo_msgs,再编译代码包:
colcon build --packages-select limo_learning source install/setup.bash这样可以避免代码包找不到最新接口。
简单记忆:
- 先编译接口包
- 再编译依赖接口包的代码包
三、source install/setup.bash 的作用
3.1 为什么编译后还要 source
执行完:
colcon build之后,虽然程序已经编译并安装到了install空间,但当前终端还不一定知道这些新内容在哪里。
所以还需要执行:
source install/setup.bash这一步的作用是刷新当前终端环境
让终端知道:
- 有哪些新的功能包
- 有哪些新的可执行文件
- 有哪些新的自定义接口
- 这些内容安装在什么位置
所以完整流程通常是:
- cd ~/agilex_open_class_ws
- colcon build
- source install/setup.bash
3.2 不 source 会出现什么问题
如果编译完成后没有执行:
source install/setup.bash可能会出现这些问题:
- ros2 pkg list 找不到新功能包
- ros2 run 找不到新节点
- ros2 interface show 找不到新接口
- ros2 launch 找不到新启动文件
例如你刚创建了功能包limo_learning,并且已经编译成功。
但是执行:
ros2 pkg list | grep limo却没有看到limo_learning。
这时候很可能就是因为当前终端还没有 source 当前工作空间。
执行:
source install/setup.bash后,再查看功能包列表:
ros2 pkg list | grep limo一般就可以看到了。
3.3 重新打开终端后还需要 source 吗
- 需要
source install/setup.bash只对当前终端生效- 否则新终端可能找不到当前工作空间中的功能包和节点。
如果关闭终端再重新打开,通常需要重新执行:
cd ~/agilex_open_class_ws source install/setup.bash如果不想每次手动 source,可以把命令加入~/.bashrc:
echo "source ~/agilex_open_class_ws/install/setup.bash" >> ~/.bashrc source ~/.bashrc这样每次打开新终端时,会自动加载这个工作空间。
不过初学阶段建议先手动执行,方便理解当前终端到底加载了哪个工作空间。
四、ros2 run 的基本流程
4.1 ros2 run 的基本格式
ros2 run用来运行某个功能包中的单个可执行节点。
基本格式是:
ros2 run 功能包名 可执行文件名
例如:
ros2 run limo_learning limo_topic_cmd这里有两个关键参数:
| 参数 | 含义 | 来源 |
|---|---|---|
| limo_learning | 功能包名称 | package.xml 中的<name> |
| limo_topic_cmd | 可执行文件名称 | CMakeLists.txt 中的add_executable |
也就是说:
- ros2 run 的第一个参数看 package.xml
- ros2 run 的第二个参数看 CMakeLists.txt
4.2 功能包名来自 package.xml
例如package.xml中写:
<name>limo_learning</name>那么运行节点时,第一个参数就是:
ros2 run limo_learning ...如果功能包名称写错,或者当前终端没有 source 当前工作空间,ros2 run就可能找不到这个功能包。
4.3 可执行文件名来自 add_executable
例如CMakeLists.txt中写:
add_executable(limo_topic_cmd src/limo_topic_cmd.cpp)那么运行节点时,第二个参数就是:
ros2 run limo_learning limo_topic_cmd注意:
- ros2 run 后面写的不是 cpp 文件名
- 而是 add_executable 中定义的可执行文件名
错误理解:
ros2 run limo_learning limo_topic_cmd.cpp正确写法:
ros2 run limo_learning limo_topic_cmd如果add_executable写成:
add_executable(my_cmd_node src/limo_topic_cmd.cpp)那么运行命令应该是:
ros2 run limo_learning my_cmd_node4.4 ros2 run 为什么能找到节点
ros2 run能找到节点,需要满足几个条件。
(1)Package.xml 中功能包名称要正确
例如:
<name>limo_learning</name>(2)CMakeLists.txt 中要生成可执行文件
add_executable(limo_topic_cmd src/limo_topic_cmd.cpp)(3)CMakeLists.txt 中把可执行文件安装到正确位置
install(TARGETS limo_topic_cmd DESTINATION lib/${PROJECT_NAME} )(4)编译后要执行:
source install/setup.bash(5)完整链路可以理解为:
package.xml 定义功能包名 ↓ CMakeLists.txt 生成可执行文件 ↓ install 安装到 install 空间 ↓ source 刷新当前终端环境 ↓ ros2 run 找到并运行节点所以ros2 run能找到节点,并不是偶然的,而是前面每一步都配置正确后的结果。
五、修改不同文件后是否需要重新编译
5.1 修改 C++ 源码
如果修改了 C++ 源码,例如:
src/limo_learning/src/limo_topic_cmd.cpp需要重新编译。
因为 C++ 源码需要重新生成可执行文件。
推荐命令:
colcon build --packages-select limo_learning source install/setup.bash否则运行的还是 install 空间中的旧程序。
5.2 修改 CMakeLists.txt
如果修改了:
CMakeLists.txt也需要重新编译。
例如新增了:
add_executable(...)或者修改了:
install(...)都属于编译规则发生变化。
这时候必须重新执行:
colcon build --packages-select limo_learning source install/setup.bash5.3 修改 package.xml
如果修改了:
package.xml例如新增依赖:
<depend>sensor_msgs</depend>也建议重新编译并重新 source。
因为依赖声明发生了变化。
推荐流程:
colcon build --packages-select limo_learning source install/setup.bash5.4 修改 msg、srv、action 接口文件
如果修改了自定义接口文件:
msg/LimoStatus.msg srv/LimoSrv.srv action/LimoAction.action一定要重新编译接口包。
例如:
colcon build --packages-select limo_msgs source install/setup.bash因为.msg、.srv、.action文件本身只是接口描述文件。
ROS2 需要根据这些文件生成 C++、Python 等语言可用的代码。
如果不重新编译,程序里就无法使用新的接口字段。
如果代码包依赖了接口包,建议再编译代码包:
colcon build --packages-select limo_learning source install/setup.bash5.5 修改 launch、config、Python 文件
修改launch、config、Python 脚本时,是否需要重新编译,要看安装方式。
如果使用普通编译方式,修改后重新编译最稳妥:
colcon build source install/setup.bash如果使用:
colcon build --symlink-install那么 launch、config、Python 脚本等文件通常会以软链接方式安装到 install 空间。
这样修改后更容易立即生效。
但是需要注意:
C++ 源码修改后仍然需要重新编译 msg/srv/action 接口修改后仍然需要重新编译5.6 修改文件后的编译总结表
| 修改内容 | 是否需要重新编译 | 原因 |
|---|---|---|
| C++ 源码 | 需要 | 需要重新生成可执行文件 |
| CMakeLists.txt | 需要 | 编译规则变了 |
| package.xml | 需要 | 依赖声明可能变了 |
| msg/srv/action 接口文件 | 需要 | 需要重新生成接口代码 |
| Python 脚本 | 一般需要 | 使用--symlink-install时可能不需要 |
| launch 文件 | 一般不需要 | 使用--symlink-install更方便 |
| config 配置文件 | 一般不需要 | 多数情况是运行时读取 |
最稳妥的做法是:
colcon build source install/setup.bash如果只改了某一个功能包,可以使用:
colcon build --packages-select 功能包名 source install/setup.bash六、常见问题总结
6.1 colcon build 成功但 ros2 run 找不到节点
常见原因包括:
- CMakeLists.txt 中没有 add_executable
- CMakeLists.txt 中没有 install
- install 的目标路径写错
- 编译后没有 source install/setup.bash
- ros2 run 后面的可执行文件名写错
重点检查CMakeLists.txt中是否有:
add_executable(limo_topic_cmd src/limo_topic_cmd.cpp) install(TARGETS limo_topic_cmd DESTINATION lib/${PROJECT_NAME} )然后重新编译并刷新环境:
colcon build --packages-select limo_learning source install/setup.bash再运行:
ros2 run limo_learning limo_topic_cmd6.2 修改代码后运行结果没有变化
最常见原因是:
修改了 src 里的代码,但是没有重新 colcon build因为 ROS2 运行的是 install 空间里的结果,不是直接运行 src 里的源代码。
解决方法:
colcon build --packages-select limo_learning source install/setup.bash然后重新运行节点。
6.3 ros2 pkg list 找不到功能包
可能原因:
- 功能包没有放在工作空间 src 目录下
- 功能包结构不完整
- 没有执行 colcon build
- 编译后没有 source install/setup.bash
可以按下面流程检查:
cd ~/agilex_open_class_ws colcon build source install/setup.bash ros2 pkg list | grep limo如果还找不到,需要检查功能包目录中是否有:
package.xml CMakeLists.txt6.4 找不到自定义 msg、srv、action 接口
常见原因包括:
- 接口包没有编译
- 接口文件修改后没有重新编译
- 没有 source install/setup.bash
- 代码包没有依赖接口包
- CMakeLists.txt 中没有 find_package(limo_msgs REQUIRED)
解决方法:
colcon build --packages-select limo_msgs source install/setup.bash colcon build --packages-select limo_learning source install/setup.bash检查接口是否生成成功:
ros2 interface show limo_msgs/msg/LimoStatus ros2 interface show limo_msgs/srv/LimoSrv ros2 interface show limo_msgs/action/LimoAction七、本章总结
7.1 colcon build 的核心作用
colcon build用来编译 ROS2 工作空间。
它会根据功能包中的:
package.xml CMakeLists.txt完成依赖解析、编译、安装等过程。
执行后通常会生成:
build install log其中最关键的是:
install因为 ROS2 运行时通常会从 install 空间中查找可执行文件、接口文件和启动文件。
7.2 source 的核心作用
source install/setup.bash用来刷新当前终端环境。
它让当前终端知道:
- 有哪些新的功能包
- 有哪些新的节点
- 有哪些新的接口
- 这些内容安装在哪里
如果没有 source,就可能出现:
编译成功了,但终端找不到功能包或节点7.3 ros2 run 的核心理解
ros2 run的基本格式是:
ros2 run 功能包名 可执行文件名
其中:
- 功能包名来自 package.xml 中的 <name>
- 可执行文件名来自 CMakeLists.txt 中的 add_executable
所以完整链路是:
package.xml 定义功能包名 ↓ CMakeLists.txt 生成可执行文件 ↓ install 安装到 install 空间 ↓ colcon build 执行编译安装 ↓ source 刷新终端环境 ↓ ros2 run 运行节点