ROS中自定义消息的发布和订阅

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28306361/article/details/85243353


因为需要传输目标跟踪的结果,因此需要进行自定义消息的发布和订阅。

建立相关文件

首先,如果我们需要传输自定义消息的话,需要建立一系列的准备文件。我是直接修改的经典教程中的beginner_tutorials中的talker.cpp和listen.cpp文件,因此,均是在beginner_tutorials这个package的文件夹下进行的。
建立msg文件夹

cd catkin_ws/src/beginner_tutorials/
mkdir msg

在msg文件夹中新建一个t_d_m.msg文件,这个文件就是用来传输消息的。官方一点说,msg文件是ROS中定义消息类型的文件,一般放置在功能包根目录下的msg文件夹中,在功能包编译的过程中,可以使用msg文件生成不同编程语言使用的代码文件。
直接打开t_d_m.msg文件,复制粘贴

std_msgs/Header header
string name
int32 sex
int32 age

这些就是我们自定义的消息类型了。其中的std_msgs/Header header是一个标准格式的头信息(也可以不加),具体含义比较简单,可以自行百度。

修改CMakeList.txt和package.xml

修改这两个东西,是为了我们能够顺利地编译,比如要传递消息的话,就应该把消息的包包括进去,还有说明一下你的消息文件是什么等。
具体而言,对于package.xml,添加

  <!-- build 依赖。下面两句任选其1均可,也可以都写上 -->
  <build_depend>message_generation</build_depend>
  <build_export_depend>message_generation</build_export_depend>
 
  <!-- 执行依赖,必须加上以下这句:-->
  <exec_depend>message_runtime</exec_depend>

对于CMakeList.txt需要修改的地方较多,分别为:

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
## Generate messages in the 'msg' folder
add_message_files(
   FILES
   t_d_m.msg
)
generate_messages(
   DEPENDENCIES
   std_msgs
)
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES beginner_tutorials
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
   CATKIN_DEPENDS message_runtime
)

相关程序

talker.cpp

#include"ros/ros.h"
#include"std_msgs/String.h"
#include"beginner_tutorials/t_d_m.h"
#include<sstream>
#include<string.h>

int main(int argc, char** argv)
{
	ros::init(argc, argv, "talker");  // 节点名称
	ros::NodeHandle n;

	// 话题topic的名称
	ros::Publisher chatter_pub = n.advertise<beginner_tutorials::t_d_m>("chatter", 1000);
	ros::Rate loop_rate(10);
	int count = 0;
	std::string name("Allison");
	int age = 12;
	int sex = 1;

	while( ros::ok() )
	{
		beginner_tutorials::t_d_m msg;
		msg.header.seq = count;
		msg.header.stamp = ros::Time::now();
		msg.header.frame_id = "t_d_m";
		msg.sex = sex;
		msg.age = age;
		msg.name = name;
		
		ROS_INFO("Publish/\n");
		ROS_INFO("Header/\n");
		ROS_INFO("	seq [%d]\n", msg.header.seq);
		ROS_INFO("	frame_id [%s]\n", msg.header.frame_id.c_str() );
		ROS_INFO("	name [%s]\n", msg.name.c_str() );
		ROS_INFO("	sex [%d]\n", msg.sex);
		ROS_INFO("	age [%d]\n", msg.age);

		chatter_pub.publish(msg);

		ros::spinOnce();
		loop_rate.sleep();
		++count;
	}
	
	return 0;
}

listener.cpp

#include "ros/ros.h"
#include "std_msgs/String.h"

void chatterCalllback(const beginner_tutorials::t_d_m msg)
{
	ROS_INFO("Header/\n");
	ROS_INFO("	seq [%d]\n", msg.header.seq);
	ROS_INFO("	frame_id [%s]\n", msg.header.frame_id.c_str() );
	ROS_INFO("	name [%s]\n", msg.name.c_str() );
	ROS_INFO("	sex [%d]\n", msg.sex);
	ROS_INFO("	age [%d]\n", msg.age);
}

int main(int argc, char** argv)
{
	ros::init(argc, argv, "listener");
	ros::NodeHandle n;
	ros::Subscriber sub = n.subscribe( "chatter", 1000, chatterCalllback );
	ros::spin();
	return 0;
}

解释一下,
1: 我们并没有建立beginner_tutorials/t_d_m.h文件,却仍然可以将它包含进来,这个文件是在编译过程中由CMakeList自行生成的,不包含会报错的。
2:对于下面这句话

ros::Publisher chatter_pub = n.advertise<beginner_tutorials::t_d_m>("chatter", 1000);

两个<>中间填写的就是我们的自定义消息类型了,即为beginner_tutorials::t_d_m,简单理解为一个自己定义的结构体
3:在编写程序的过程中,可能会出现莫名其妙的红线报错,但是最终可以编译通过,我也搞不懂,程序写的有没有问题,至少还是编译一下看看吧

编译运行

cd catkin_ws/
catkin_make
roscore
rosrun beginner_tutorials talker 

可以看到在发布消息
在这里插入图片描述
在talker运行的同时,再打开一个终端,运行

rosrun beginner_tutorials listener

可以看到程序收到了我们发布的自定义消息
在这里插入图片描述
注意一定要同时打开,否则接受者是接受不到消息的,因为没有人发布消息,我在这里卡了好久,还是自己太笨了。

参考博客

1:ROS 发布和订阅自定义消息数组
2:ROS消息传递——自定义消息
3:package文件夹的解读
4:ROS中订阅(Subscribe)最新消息以及对消息队列的浅谈

猜你喜欢

转载自blog.csdn.net/qq_28306361/article/details/85243353