ros消息类型,即是ros话题的格式,可视为ros的数据类型,基本上是指同一个意思。ros消息类型是基于C++基本类型封装为.msg文件实现,rosmsg指令用于消息管理。
一. ros预定义的消息类型
所谓预定义消息类型是可以直接引用,不需要自己实现,ros自定义数据类型通常包括两类,一类是在 std_msgs 包下,包含基本数据类型,例如字符型、整型以及浮点型等;一类是在 common_msgs 包下,包含常用的数据类型、例如传感器数据类型、导航数据类型以及几何数据类型等。
1. 基本数据类型
基本数据类型位于 std_msgs包,在ROS 话题篇,我们使用了ros字符串类型 std_msgs/String,就是一种基本类型,可使用 rosls 查看其消息文件路径:
rosls std_msgs/msg/String.msg
如图:
使用 roscat 通过消息文件查看其具体实现:
roscat std_msgs String.msg
如图:
也可直接使用 rosmsg 查看其具体实现:
rosmsg show std_msgs/String
如图:
可以通过 rosmsg 查看 ros 所有的基本数据类型:
rosls std_msgs/msg/
也可以通过如下网页查看:http://wiki.ros.org/std_msgswiki.ros.org
2. 常用数据类型
常用数据类型基本上是基于基本数据类型封装而成,按照功能,封装在不同的包内,例如图像数据封装在 sensor_msgs包 下,通过 rosls 和 rosmsg 指令查看如下:
rosls sensor_msgs/msg/Image.msg
rosmsg show sensor_msgs/Image
如图:
除了图像基本数据外,还包含一个消息类型:std_msgs/Header,此消息类型包含三项:序列号, 时间戳 以及 帧id, 帧id表示消息类别,例如 camera,表示相机数据;序列号表示是第几帧数据,时间戳常用语与其他消息做同步使用。基本上所有的常用数据类型都会包含此数据类型。
可以通过如下链接查看所有的常用消息类型:https://wiki.ros.org/common_msgs?distro=kineticwiki.ros.org
二. 自定义消息类型
虽然ros提供了较为丰富的预定义消息类型,但是在实际开发中,经常需要自己定义合适的数据类型以满足自己的需求,下面通过创建两个节点,介绍下如何自定义消息,以及如何使用自定义消息。
1. 创建自定义消息
roscd beginner_tutorials/
mkdir msg
touch msg/Num.msg
Num.msg文件内容如下:
int32 a
int32 b
至此我们创建了一个自定义消息。
文件链接:https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/msg/Num.msggithub.com
这里我们创建的消息格式是 .msg,在c++程序中,消息是以头文件形式出现,所以需要把 .msg 文件编译为 .h 文件。
2. 配置package.xml
在 package.xml 文件中添加如下三行,使用任何自定义消息,都必须使用这三行。
message_generation
message_runtime
message_runtime
文件链接:https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/package.xmlgithub.com
第一行表示编译时依赖,第二行导出依赖,即其他包中程序可以使用本消息,第三行表示运行时依赖。
3. 配置CMakeLists.txt
将 message_generation 加入到 find_package(), find_package() 要与 package.xml 文件中的 build_depend 一致,表示编译时依赖的包。
将 Num.msg 加入 add_message_files(),表示要编译的消息文件。放开 generate_messages(),表示生成消息头文件。
将 message_runtime 加入 catkin_package() 表示导出运行时依赖。
这里看不明白也没关系,在添加消息时,按照这个套路配置就可以了。至此我们完成自定义消息配置。
4. 检测自定义消息是否完成
rosmsg show beginner_tutorials/Num
输出:
int32 a
int32 b
表示自定义消息成功。在这一步我们还没有编译消息文件,下一步编译消息文件。
三. 编译消息文件
catkin_make
编译完之后,会生成相应的头文件:./devel/include/beginner_tutorials/Num.h
四. 使用自定义消息
1. 创建订阅节点listener_msg
cp listener.cpp listener_msg.cpp
做如下修改:
第13行,将节点名 listener 改为 listener_msg
第16行,将话题名 chatter 改为 chatter_msg
第5行,修改回调函数参数。
第2行,引入消息头文件。修改后内容如下:
#include "ros/ros.h" //ros.h 包含ros程序常用的头文件。
#include "beginner_tutorials/Num.h" //自定义消息类型。
//回调函数定义,参数类型需要与所订阅的消息类型保持一致
void chatterCallback(const beginner_tutorials::Num::ConstPtr& msg)
{
ROS_INFO("I heard: [%d %d %d]", msg->a,msg->b,msg->a+msg->b);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener_msg"); //初始化ros,并命令节点名。
ros::NodeHandle n; //初始化节点,调用ros api接口句柄。
ros::Subscriber sub = n.subscribe("chatter_msg", 1, chatterCallback); //定义一个订阅者。
ros::spin(); //不返回函数,监听订阅者中的回调队列,并执行回调函数。
return 0; //正常运行时,不会执行到。
}
可参考链接:https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/src/listener/listener_msg.cppgithub.com
2. 创建发布节点talker_msg
cp talker.cpp talker_msg.cpp
做如下修改:
第2行引入消息头文件,注意格式,需要包含包名。
第6行修改节点名。
第9行修改话题名,以及消息类型,消息类型与头文件格式保持一致,都要添加包名。
第12行,定义一个消息变量。
第14和15行,更新消息内容。
第16行打印消息。
第17行发布消息。修改后如下:
#include "ros/ros.h" //ros.h 包含ros程序常用的头文件。
#include "beginner_tutorials/Num.h" //自定义消息类型。
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker_msg"); //初始化ros,并命令节点名。
ros::NodeHandle n; //初始化节点,调用ros api接口句柄。
//定义一个发布者
ros::Publisher chatter_pub = n.advertise<:num>("chatter_msg", 1);
ros::Rate loop_rate(10); //设置发布频率
int count = 0; //发布消息计数
beginner_tutorials::Num num; //定义一个消息变量。
while (ros::ok()){ //检测节点是否正常运行
num.a = count;
num.b = count+1;
ROS_INFO("%d %d %d", num.a,num.b,num.a+num.b); //打印消息
chatter_pub.publish(num); //发布消息
ros::spinOnce(); //处理回调函数,会返回,这里也可以不加,因为此节点没有回调函数。
loop_rate.sleep(); //与Line 11配套使用,用于控制发布频率。
++count; //消息计数。
}
return 0;
}
可参考链接:https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/src/talker/talker_msg.cppgithub.com
3. 添加到CMakeLists.txt
添加如下指令:
add_executable(listener_msg src/listener/listener_msg.cpp)
target_link_libraries(listener_msg ${catkin_LIBRARIES})
add_dependencies(listener_msg ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_executable(talker_msg src/talker/talker_msg.cpp)
target_link_libraries(talker_msg ${catkin_LIBRARIES})
add_dependencies(talker_msg ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
完成文件参考链接:https://github.com/ahuer2435/ros_program/blob/master/catkin_ws/src/beginner_tutorials/CMakeLists.txtgithub.com
五. 编译工程
catkin_make
六. 运行测试节点
roscore
rosrun beginner_tutorials listener_msg
rosrun beginner_tutorials talker_msg
运行效果如下如:
使用 rqt_graph 指令,如下图:
可以比较清晰看到节点话题之间的关联。
七. 小结
本篇介绍了ros预定义的消息类型,以及如何自定义消息类型,以及如何使用自定义消息类型。消息类型是话题独有,话题是ros最为常用的通信方式,属于异步通信,下一篇介绍ros同步通信方式:服务。