工作空间和package.xml

创建package后,package.xml不需要再修改

创建package命令是catkin_create_pkg nodeName

package名称

package的名称对应CMakeLists中的project(package)package.xml中的<name>package</name>

package的命名是有官方规范的,我意外地发现test这个名字往往会带来问题,可能是因为带test的package都是用于测试的,所以要避免使用。基本规则如下:

  1. 只能使用字母数字下划线
  2. 字母只能用小写,开头必须是字母
  3. 至少有两个字符长度
  4. 只做消息的package以_msg结尾,只含launch的以_launch结尾,以此类推

不要轻易用msg, launch, test这样的字符串做名称,容易出问题。如果命名不规范,编译时会告警,影响编译时间。查看官方package列表,发现除了tf这样一个单词做名称的例子外,其他基本都是a_ba_b_c这样的名称,例如tuw_geometry_rviz,所以这样命名比较稳妥。

package.xml

每个package.xml文件必须包含的标签包括:

  • <package> : 最高级tag,属性:format,用于指定格式
  • <name> :package名称
  • <version> :当前版本
  • <description>:package的基本描述
  • <maintainer>(至少一个):维护者
  • <license>(至少一个):协议
  • <buildtool_depend>(至少一个): 一般情况下只需要指定catkin作为编译工具, 在需要交叉编译的情况下需要增加目标机器的编译工具

可选标签包括:

  • <build_depend> (多个):编译时需要依赖的其它package,适用于静态库
  • <exec_depend> (多个):运行时需要依赖的其它package,适用于静态库
  • build_export_depend: 编译时需要链接(build against)的package
  • <export>:用于添加额外的信息,比如需要嵌入的其它package的插件,或者一些说明信息。

使用depend可以表示同时包括buildexec依赖,也就是说<depend>roscpp</depend>相当于

1
2
<build_depend>roscpp</build_depend>
<exec_depend>roscpp</exec_depend>

一般都包括的几个是

1
2
3
4
5
6
<buildtool_depend>catkin</buildtool_depend>
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
<!-- 可能还有其他msgs类型 -->
<depend>std_msgs</depend>
<build_export_depend>std_msgs</build_export_depend>

几个重要路径

4个ROS的重要路径,可在CMakeLists中用message函数查看:

  • CATKIN_PACKAGE_LIB_DESTINATION: lib库的路径

  • CATKIN_PACKAGE_BIN_DESTINATION: 可执行文件的路径

  • CATKIN_PACKAGE_SHARE_DESTINATION:共享文件的路径,就是CMakeLists中的INSTALL生成的两个cmake文件的路径

  • catkin_INCLUDE_DIRS: 跟catkin有关文件的路径,不仅仅是ROS相关的

在代码中包含另一个package的头文件时,经常写成#include<robot_api/robot_api.h>,注意程序目录结构必须是这样:

多工作空间的问题

尽量只用一个工作空间,如果用到两个以上,不要出现同名package,也不要出现不同工作空间的包有依赖的情况

如果在/opt/ros/kinetic/之外,如果我们创建了多个工作空间且需要在多个工作空间中来回地工作,比如/home/user/catkin_ws1/home/user/catkin_ws2

ROS_PACKAGE_PATH环境变量中的多个目录是有先后顺序的。如果工作空间1和2中的所有包之间没有依赖关系,那么将下面两句话放在bashrc文件中合适的位置(至少应该放在source /opt/ros/kinetic/setup.*sh后)。

1
2
source /home/user/catkin_ws1/devel/setup.*sh --extended
source /home/user/catkin_ws2/devel/setup.*sh --extended

后面source的工作空间会遮蔽之前工作空间的同名包,比如opt/ros/indigo/share/中安装了move_base包,又在/home/user/catkin_ws1中通过下载源代码的方式安装了move_base,由于ROS_PACKAGE_PATH环境变量的遮蔽效果,我实际用的是/home/user/catkin_ws1/中的move_base,这正是我们常常的目的

环境变量中这样设置:

1
2
source /opt/ros/kinetic/setup.zsh
source /home/xiaoqiang/catkin_ws/devel/setup.zsh

ROS_PACKAGE_PATH结果是/home/xiaoqiang/catkin_ws/src:/opt/ros/kinetic/share,也就是说后source的工作空间会排在ROS_PACKAGE_PATH的靠前部分,也就是优先级高

source工作空间的顺序会影响链接的so文件

source devel/setup.bash,再source /opt/ros/melodic/setup.bash,没有source install/setup.bash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# libmove_base.so 所链接的 libcostmap_2d.so 是deve/lib里的
user@user:~/catkin_ws/install/lib$ ldd libmove_base.so | grep user
libcostmap_2d.so => /home/user/my_ws/devel/lib/libcostmap_2d.so (0x00007f1d87062000)

user@user:~/catkin_ws/install/lib$ locate libcostmap_2d
# 有5个 libcostmap_2d.so
/home/user/catkin_ws/devel/lib/libcostmap_2d.so
/home/user/catkin_ws/install/lib/libcostmap_2d.so

/home/user/my_ws/devel/lib/libcostmap_2d.so
/home/user/my_ws/install/lib/libcostmap_2d.so

/opt/ros/melodic/lib/libcostmap_2d.so
# 删除 devel/lib/libcostmap_2d.so
user@user:~/catkin_ws/install/lib$ rm /home/user/my_ws/devel/lib/libcostmap_2d.so
# 此时就会链接到 ros 自带的 libcostmap_2d.so
# 如果ros自带的也被删除,就会链接失败,不去链接其他的 libcostmap_2d.so
user@user:~/catkin_ws/install/lib$ ldd libmove_base.so | grep cost
libcostmap_2d.so => /opt/ros/melodic/lib/libcostmap_2d.so (0x00007f15a177a000)

编译时寻找其他工作空间的包


很奇怪,我编译的工作空间已经有voxel_grid,结果会去另一个工作空间找同名的包,但那个包已经被我删了,所以找不到,结果报错。

看catkin_make开头的信息,发现这里就涉及到了xju_ws这个包了


发现build文件夹里的几个文件涉及了xju_ws,但是如果删除再编译,还是会生成一模一样的文件。

最后只有重建一个工作空间,执行catkin_init_workspace,再编译,问题解决。