引言
其实从前几篇文章中我也有提及过ROS 工作空间,而且代码也是在工作空间中编译、运行的。
其实在 ROS 中,我们创建的软件代码,都会被组织成功能包的形式,所以在我们开始代码之前,第一步是创建一个容纳我们的工作空间。
因此本文将介绍ROS工作空间、package 及 catkin 编译系统。
ROS系列文章
ROS 工作空间
简单地说,ROS 工作空间(ROS workspace)就是统一存放 ROS 文件的地方,这里的文件包括源码、功能包、编译产生的中间文件等,一个项目的所有 ROS 文件最好都放在一个 workspace 中,便于统一管理、编译和调用。
一般来说,对于初学者,ROS的工作空间不需要经常建立,因为很多代码只是demo,一般只建立一个就好了,但是如果你的工作涉及大量的功能包,或者涉及几个相互独立的的项目,还是建立多个工作空间比较好,这东西看情况使用就好了。
我们可以在任意位置创建工作目录,一般来说工作空间都有4个文件夹:
src:代码空间,是用来放置我们的功能包的,包括功能包的代码、功能包的配置文件配置等,这个功能包可以是自己写的,也可以是别人的功能包,总之都放在这。
build:编译空间,里面会有编译时产生的一些中间的文件,这个文件夹大家基本上是不用去关心的。
devel:开发空间,里面会放置我们编译生成的一些可执行文件,还包括一些库、一些脚本等等都放在这里。
install: 安装空间,在编译成功后,可以使用
make install
命令将可执行文件安装到该空间中,这个文件夹并不一定需要,实际上很多工作空间都不需要这个文件夹。
创建工作空间
在任意目录下创建一个文件夹,名字你随意起,我就起ros_ws,然后在这个文件夹下创建src文件夹:
然后在这个src文件夹下运行以下命令去初始化工作空间:
catkin_init_workspace
然后你就会发现在src目录下生成了一个CMakeLists.txt
文件,这其实是CMake的构建规则的文件,这个文件包含了一系列的编译指令,包括应该生成哪种可执行文件,需要哪些源文件,以及在哪里可以找到所需的头文件和链接库。当然,这个文件表明 catkin 在内部使用了 CMake。有兴趣的可以去看看我以前的博文,就是讲解CMake的。
编译工作空间
工作空间里面虽然没有任何代码,但是你依然可以去编译啊,只不过是一个空的工程,那在这里我们一样可以针对ROS的空的空间做编译,大家可以来熟悉一下这个编译的方式,我们要回到你的这个工作空间的根目录ros_ws,在这个目录下进行编译。
cd ..
# 编译
catkin_make
# 输出内容
···
···
-- Using Python nosetests: /usr/bin/nosetests-2.7
-- catkin 0.7.23
-- BUILD_SHARED_LIBS is on
-- BUILD_SHARED_LIBS is on
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jie/ros_ws/build
看到有对应的内容输出了,就表示编译成功,然后你的ros_ws目录下回多了两个文件夹,分别为build、devel,这两个文件夹的作用就是前面讲解的了。
导出环境变量
devel目录就是我们的环境变量,假设我们当前的工作空间有代码,那么编译成功后会产生可执行文件,那么ROS如何去找到这个可执行文件呢,它不是全能的,需要我们去指定这个可执行文件在哪里,它才能找到,因此我们需要将编译产生的可执行文件、脚本等内容都要告诉系统,我称之为导出环境变量。
如果你查看一下在devel
文件夹里面你可以看到几个setup.sh文件。source这些文件中的任何一个都可以将当前工作空间设置在ROS工作环境的最顶层。
如果你的终端是bash(Ubuntu默认终端),那么就运行:
source devel/setup.bash
我个人用的终端是zsh,我是修改过了的,我运行以下命令:
source devel/setup.zsh
然后用echo $ROS_PACKAGE_PATH
命令去检查环境变量是否导出,当输出包含了你工作空间的目录就表示环境变量已经导出成功了:
➜ ros_ws echo $ROS_PACKAGE_PATH
/home/jie/ros_ws/src:/opt/ros/melodic/share
创建功能包
写代码就要创建一个功能包,放着源码文件,在工作空间的src目录下可以直接运行catkin_create_pkg
命令去创建功能包,这个命令有非常多的功能,你可以通过catkin_create_pkg -h
去细看它的功能,而我就简单讲解一下:
简单的命令用法:
catkin_create_pkg [功能包名称] [依赖功能包1] [依赖功能包2] [依赖功能包n]
创建mytopic001功能包,依赖roscpp、rospy、std_msgs这几个功能包,其实rospy不是必须的,我们目前写的是c++的代码,不过放进去都无所谓。
catkin_create_pkg mytopic001 roscpp rospy std_msgs
catkin_create_pkg
命令在创建用户功能包时会生成catkin构建系统所需的CMakeLists.txt和package.xml文件,还有存放代码的src文件夹,和include文件夹,注意这里的src并不是工作目录下的src,而是功能包的src文件夹。
你可以手动去修改功能包的依赖关系,比如编辑package.xml
文件:
添加源代码
我们将上一篇文章【ROS入门-4】嘴对嘴讲解ROS的核心概念——ROS话题通信机制的源代码添加到这个工作空间中,存放的位置是:ros_ws/src/mytopic001/src
,
修改构建规则
修改ros_ws/src/mytopic001
目录下的CMakeLists.txt
文件就是修改对应的构建规则,可以在这个文件中设置可执行文件的创建规则、依赖关系、连接关系等等。
add_executable(publisher_topic src/publisher_topic.cpp)
target_link_libraries(publisher_topic ${catkin_LIBRARIES})
add_executable(subscriber_topic src/subscriber_topic.cpp)
target_link_libraries(subscriber_topic ${catkin_LIBRARIES})
其实如果你会了CMake后,这东西是非常简单的。。。上面的操作起始就是编译两个可执行文件publisher_topic
和subscriber_topic
,分别执行发布与订阅的操作。
编译功能包
回到工作空间的根目录下ros_ws
,运行catkin_make
命令编译,当输出以下内容时,表示编译成功:
catkin_make
# 输出内容
···
···
Scanning dependencies of target subscriber_topic
Scanning dependencies of target publisher_topic
[ 50%] Building CXX object mytopic001/CMakeFiles/publisher_topic.dir/src/publisher_topic.cpp.o
[ 50%] Building CXX object mytopic001/CMakeFiles/subscriber_topic.dir/src/subscriber_topic.cpp.o
[ 75%] Linking CXX executable /home/jie/ros_ws/devel/lib/mytopic001/publisher_topic
[100%] Linking CXX executable /home/jie/ros_ws/devel/lib/mytopic001/subscriber_topic
[100%] Built target publisher_topic
[100%] Built target subscriber_topic
验证
步骤如下:
- 首先导出环境变量(注意根据你的终端配置运行命令)
source devel/setup.zsh
- 运行节点管理器
roscore
- 在新终端运行发布者节点,也是需要导出环境变量的,不然ROS找不到你的可执行程序位置
source ros_ws/devel/setup.zsh
rosrun mytopic001 publisher_topic
- 在新终端运行订阅者者节点
source ros_ws/devel/setup.zsh
rosrun mytopic001 subscriber_topic
最终效果: