ROS2学习笔记之创建工作空间篇
- 背景
- 前期准备
- 学习内容
- 1. Source ROS 2 环境变量
- 2. 创建一个新的文件夹
- 3. 下载一个简单的例子
- 4. 解决依赖关系
- 5. 使用colcon编译工作空间
- 6. 加载新建的工作空间
- 7. 修改新建的工作空间中的包
- 总结
学习目标:创建一个工作空间,并对如果进行开发和测试有一个全面的了解
背景
工作空间是一个包含ROS2功能包的一个文件夹。在我们使用ROS2的时候我们必须在终端source安装目录的工作空间的配置文件,这样我们才可以正常使用ROS2的各种功能。
关于ROS的工作空间,我们称ROS安装时候系统的工作空间为底层的工作空间,我们可以新建一个新的工作空间,在这个空间中编写自己的功能包,不对安装的底层工作空间产生干扰。底层的工作空间需要包含新建工作空间的所有依赖,这样就形成了一种类似继承的关系。子工作空间会覆盖父工作空间的包。我们可以建立多个工作空间,他们的关系像一栋搂一样,最底层为系统安装的工作空间,每建立一个新的工作空间依次往上,每一层工作空间继承他的上一场工作空间。
前期准备
首先需要安装git
sudo apt install git
然后我们还需要安装编译工具colcon
sudo apt install python3-colcon-common-extensions
安装rosdep
sudo apt install python-rosdep
学习内容
1. Source ROS 2 环境变量
在这篇教程中我们以系统安装的工作空间作为底层(并不是底层的工作空间一定要是系统的工作空间,前面我们说过也可以是依次继承下来的工作空间)
source /opt/ros/eloquent/setup.bash
2. 创建一个新的文件夹
我们创建一个新的文件夹作为新的工作空间的开始
给每个新的工作空间创建一个新的文件夹是一个好习惯,取上面名字无关紧要,但是最好能从这个名字上看出这个工作空间是干什么的。我们取名dev_ws意为development workspace
mkdir dev_ws
mkdir dev_ws/src
cd dev_ws/src
将功能包放入src也是一个比较好的习惯。我们建立一个工作空间同时建立一个src文件夹,然后进入这个文件夹内。
3. 下载一个简单的例子
在接下来的教程当中我们会自己建立功能包,但是这本教程中我们主要练习如何将现有的包放入到工作空间中。ROS2改动还是不少,我们一步一来。
我们接下来会使用一个已有的包叫做ros_tutorials
和我们之前接触的turtlesim
差不多
我们下载例程需要的代码,通过-b
选项我们选择我们当前ros版本的分支。注意这个操作要在dev_ws/src
文件夹下执行
git clone https://github.com/ros/ros_tutorials.git -b eloquent-devel
现在我们已经下载了ros_tutorials
,通过下面命令查看功能包中的内容
ls ros_tutorials
我们看到该功能包的内容如下
roscpp_tutorials rospy_tutorials ros_tutorials turtlesim
现在我们已经将一个包放入了工作空间,但是目前这个工作空间还不是一个完整的工作空间,我们还需要解决依赖关系。
4. 解决依赖关系
在我们对工作空间进行编译之前,我们首先需要解决相关功能包的依赖关系。
虽然我们可能已经拥有了我们下载的功能包的所有的依赖,但是每次克隆下载包的时候检查相关依赖是一个好习惯。我们并不希望在编译了很长时间过后突然报错。
我们在工作空间的根目录(例如dev_ws
)运行下面的命令可以检查安装工作空间中的包的依赖。
sudo rosdep install -i --from-path src --rosdistro eloquent -y
如果我们已经安装了所有的依赖,控制台会返回下面的结果,提示我们已经按照了所有的依赖。
#All required rosdeps installed successfully
每个包会在package.xml
声明相关的依赖,这个命令会根据这个文件检查是否所有依赖都安装了。
5. 使用colcon编译工作空间
在我们检查依赖安装过后,我们就可以在工作空间的根目录(例如dev_ws
)通过下面的命令编译工作空间了,
colcon build
终端显示下面的消息表示编译成功
Starting >>> turtlesim
Finished <<< turtlesim [5.49s]
Summary: 1 package finished [5.58s]
colcon build
其他一些参数
--packages-up-to
编译我们指定的包,及其所有依赖项,而不是整个工作区(节省时间)--symlink-install
避免了每次更改Python脚本时都需要重新编译--event-handlers console_direct+
在编译时是否在控制台显示输出(如果不显示我们还是可以在log文件夹看到输出)
编译完成过后我们通过下面命令查看工作空间
ls ~/dev_ws
我们可以看到编译新建了几个文件夹
build install log src
install
文件夹是当前工作空间存放配置文件的地方,这一点和ros1不同,我们通过source
相关配置文件可以加载当前工作空间。
6. 加载新建的工作空间
有一点值得注意在我们source
我们自己的工作空间的时候不要在编译工作空间的终端进行,这可以造成一些比较麻烦的问题。
新打开一个终端,我们首先source
系统的工作空间,将其作为底层,如果我们将这句话写在了.bashrc
中我们就不需要再次.bashrc
了
source /opt/ros/eloquent/setup.bash
切换到工作空间内
cd dev_ws
在工作空间的根目录我们source
新的工作空间,这相当于第二层(overlay)
source install/local_setup.bash
关于
source
ros1和ros2有很大的不同,在install
目录下会有local_setup
和setup
两个文件。local_setup
只会把当前工作空间中的可用包添加到环境当中,setup
则会把新建该工作空间时候的底层的工作空间也加入到环境当中,这样就可用同时使用两个工作空间中的包。
因此,先source
ROS2安装时系统的setup
,然后再source
dev_ws
的local_setup
,和source
dev_ws
的setup
的效果是相同的,应为dev_ws
这个工作空间的创建时的底层就是系统的setup
对于存在多个工作空间的情况这种区别就会体现出来,官网对于新的工作空间叫overlay,也就是这个一个每个工作空间之间是存在覆盖累计的情况。
个人推荐首先source
系统,然后对于自己创建的工作空间选择local_setup
这样就会减少自己建立的多个工作空间之间的干扰。这解决了ros1上一个很头疼的问题。
现在我们可以在覆盖层的工作空间(overlay)运行turtlesim
ros2 run turtlesim turtlesim_node
现在有关新的问题我们运行的这个turtlesim
是系统安装的还是刚刚编译的。
我们通过修改上层的turtlesim
,以便我们可以观察效果:
- 修改并且重新编译时不
source
系统的工作空间 - 修改并且重新编译时
source
系统的工作空间
7. 修改新建的工作空间中的包
我们可以修改turtlesim
包中海龟界面显示的标题来进行这个实验。
我们打开~/dev_ws/src/ros_tutorials/turtlesim/src
中的turtle_frame.cpp
我们找打52行的一个函数 setWindowTitle("TurtleSim");
更改其中的”TurtleSim”
为”MyTurtleSim”
后保存退出
我们返回我们刚刚编译的终端再次colcon build
进行编译
然后我们返回刚刚我们source
过我们新建的工作空间的终端,重新运行海龟。
ros2 run turtlesim turtlesim_node
我们可以看到窗口的标题栏现在窗口的标题变为了“MyTurtleSim”
尽管我们之前成功source了系统安装的部分,但是作为新source的工作空间会优先于之前的,这就是覆盖的概念。
我们为了验证系统底层的包还是完成的,我们打开一个新的终端,这时候只source系统的配置文件,然后我们再次运行海龟
ros2 run turtlesim turtlesim_node
通过标题我们可以看到我们修改的部分并不影响底层部分的功能。
总结
在这个例程当中我们将系统的工作空间作为底层空间,我们新建的作为上层空间,通过修改标题实验,我们得出了一个结论上层优先于底层。
通常建议每个工作空间不要放太多的包,如果把所有的包都放入一个工作空间的时候编译会非常慢。