除了ROS内置消息外,我们还能自定义消息。这一次我们不再与海龟较劲,而是自定义一个订阅消息类型,让订阅者和发布者通过这个结构进行数据通信。
话题消息是以.msg结尾的文件,是一个用于描述ROS话题信息简单文本文件,用于生成不同语言消息的源代码。
msg文件一般存放在package下msg文件夹下,其数据类型可以是:
string first_name
string last_name
unit8 age
unit32 score
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
这是为了保证msg文件能够转换成C+,Python和其他语言的源文件代码,第一行是编译的时候的依赖,第二行是执行时依赖。
find_package语句增加message_generation
:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
catkin_package语句增加CATKIN_DEPENDS message_runtime
catkin_package(
...
CATKIN_DEPENDS message_runtime ...
...)
add_message_files语句增加自定义的msg文件
add_message_files(
FILES
Message1.msg
Message2.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
std_msgs其实是编译msg需要依赖的包,在早些版本,你只需要使用一句话即可generate_messages()
在package目录创建一个msg文件夹,并创建自己的自定义消息:
mkdir msg
cd msg
touch sensor.msg
消息如下(sensor.msg):
int8 id
float32 xacc
float32 yacc
float32 zacc
float32 temperture
package.xml添加固定的片段:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
一个用于编译时信息产生依赖
;
另一个用于执行时信息依赖
在find_package中增加红色框框部分:
catkin_package
命令增加了message_runtime
:
add_message_files
命令增加了sensor.msg
:
generate_messages
命令增加了:std_msgs
:
回到工作空间根目录,使用catkin_make
进行编译,如果出现以下打印,说明一切正常:
事实上,对于C++而言,编译器帮我们自动编写一个头文件:sensor.h
,文件位于workspace/devel/include
中,通过引用头文件就可以使用这个自定义数据了。
发布者程序代码:
#include
#include "selfmsg/sensor.h"
int main(int argc,char **argv)
{
ros::init(argc,argv,"PubMessage");//这个将会作为节点名
ros::NodeHandle n;
ros::Publisher pubSensorInfo=n.advertise<selfmsg::sensor>("/sensorInfo",10);//这个将作为话题名
ros::Rate loopRate(1);
int count=1;
while(ros::ok())
{
selfmsg::sensor msg;
msg.id=0;
msg.xacc=10;
msg.yacc=11;
msg.zacc=12;
msg.temperture=32;
pubSensorInfo.publish(msg);
ROS_INFO("Publish sensor Info: id=%d xacc=%f yacc=%f zacc=%f temperature=%f",
msg.id,msg.xacc,msg.yacc,msg.zacc,msg.temperture
);
loopRate.sleep();
}
}
订阅者程序代码:
#include
#include "selfmsg/sensor.h"
void printReceieveSensorInfo(const selfmsg::sensor::ConstPtr & msg)
{
ROS_INFO("Receieve sensor info id=%d,xacc=%f,yacc=%f,zacc=%f,temperatrue = %f",
msg->id,msg->xacc,msg->yacc,msg->zacc,msg->temperture
);
}
int main(int argc,char **argv)
{
ros::init(argc,argv,"GetSensorInfo");
ros::NodeHandle n;
ros::Subscriber sensorSub=n.subscribe("/sensorInfo",10,printReceieveSensorInfo);
ros::spin();
return 0;
}
OK,最后一步,往这个包对应的CMakeLists.txt中添加:
add_executable(sub src/sensorSub.cpp)
target_link_libraries(sub ${catkin_LIBRARIES})
add_executable(pub src/sensorPub.cpp)
target_link_libraries(pub ${catkin_LIBRARIES})
回到workspace目录,catkin_make!看到如下情况说明一切顺利:
你使用sensor.msg,最后会产生一个sensor.h。代码中表现是
package::sensor
。
开启第一个终端,用来启动roscore核心:
roscore
这个指令再复习一下:
Usage: rosrun [--prefix cmd] [--debug] PACKAGE EXECUTABLE [ARGS] rosrun will locate PACKAGE and try to find an executable named EXECUTABLE in the PACKAGE tree. If it finds it, it will run it with ARGS.
第二个终端,启动selfmsg中的应用sub
rosrun selfmsg sub
第三个终端,启动selfmsg中的应用pub
rosrun selfmsg pub