自定义msg或srv

类型说明

msg文件存放在package的msg目录下,直接自己创建就可以。msg文件实际上就是每行声明一个数据类型和变量名。可以使用的数据类型如下:

1
2
3
4
5
6
7
int8, int16, int32, int64 (以及uint开头的类型)
float32, float64
string
bool
time, duration
其他msg文件定义的类型 // 例如geometry_msgs/Pose
variable-length array[] and fixed-length array[C]

在ROS中有一个特殊的数据类型:Header,它含有时间戳和坐标系信息。在msg文件的第一行经常可以看到Header header的声明.

比如这样一个消息文件:

1
2
3
4
string name
float32 gridX
float32 gridY
geometry_msgs/Pose worldPos

编译准备

要确保msg文件被转换成为C++,Python和其他语言的源代码: 编辑package下面的package.xml , 确保它包含一下两条语句:

1
2
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

编辑CMakeLists.txt,利用find_packag函数,增加对message_generation的依赖:

1
find_package(REQUIRED COMPONENTS message_generation)

同时设置运行依赖:

1
2
3
4
catkin_package(
...
CATKIN_DEPENDS message_runtime ...
...)

还要确保添加了msg文件:

1
2
3
4
add_message_files(
FILES
test.msg
)

以及生成消息的依赖,也就是消息文件中的各个类型要依赖的消息库,一般要有std_msgs:
1
2
3
4
5
6
generate_messages(
DEPENDENCIES
nav_msgs
sensor_msgs
std_msgs
)

完成以上步骤之后,进行编译,msg文件都将转换为ROS所支持语言的源代码。生成的C++头文件将会放置在~/catkin_ws/devel/include/packageName/,然后使用rosmsg show packageName/msgName命令测试是否成功 ,其实有头文件就说明成功了。

include/功能包头文件目录:你可以把你的功能包程序包含的*.h头文件放在这里,include下之所以还要加一级路径是为了更好的区分自己定义的头文件和系统标准头文件

专门自定义消息的package

实际中一种消息类型会被多个package使用,这时再一次次定义消息就太麻烦了,多种消息分散在多个package里面,很不方便管理。此时应该创建一个package专门用于定义各类消息。比如定义一个名为myMsgs的package,然后在其msg文件夹中创建各个消息文件,继续按照上面的流程编辑package.xmlCMakeLists,最后编译这个package,才能供其他package使用。

使用

在其他package中调用myMsgs中的消息时,在package.xml中添加以下语句:

1
2
<build_depend>myMsgs</build_depend>
<exec_depend>myMsgs</exec_depend>

然后到CMakeLists中的find_package添加myMsgs不需要进行其他修改

在cpp文件中使用自定义的消息时,需要#include <packageName/msgName.h>。代码中这样使用:

1
2
ros::Publisher pub = n.advertise<packageName::msgName>("topic",1500);
packageName::msgName msg;

无法echo某个话题,报如下错误


此时对应的消息一般是自定义的,如果已经编译,一般执行source devel/setup.bash就能修复,如果不能执行下面操作:

  1. 确保自定义的消息文件加入到了CMakeLists.txt
  2. catkin_make clean
  3. catkin_make
  4. source devel/setup.bash
  5. 运行