打开catkin_ws/src/learning_topic/src路径:
~$ cd ~/catkin_ws/src/learning_topic/src
然后创建msg文件夹存放自定义的消息文件Person.msg。
string name
uint8 sex
uint8 age
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
定义好之后依次修改learning_topic下的package.xml和CMakeList.txt文件,以让刚创建的msg文件可以被编译。
在pachage.xml中添加两行代码:
message_generation
message_runtime
这两行代码声明了编译和执行时所依赖的包。
package.xml文件修改如下:
同样的,在CMakeList.txt中做对应修改,在find_package下添加message_generation:
并在 ## Declare ROS messages, services and actions## 下添加下列代码:
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)
完成后,回到工作空间下,并编译整个工作空间。
~$ cd ~/catkin_ws
~$ catkin_make
至此,自定义消息的工作就完成了,总结一下,流程为:
1、创建文件夹,自定义消息类型(本质是结构体的定义,消息是以结构体为单位传输的,但要符合ros的规则,如uint8等关键字);
2、修改pakage.xml和CMakeList.txt文件,本质就是修改编译规则,自定义的消息类型要在编译时可以被正确编译、解读。
在learning_topic/src下添加发布者代码person_publisher.cpp:
/**
* 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
*/
#include
#include "learning_topic/Person.h"
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "person_publisher");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);
// 设置循环的频率
ros::Rate loop_rate(1);
int count = 0;
while (ros::ok())
{
// 初始化learning_topic::Person类型的消息
learning_topic::Person person_msg;
person_msg.name = "Tom";
person_msg.age = 18;
person_msg.sex = learning_topic::Person::male;
// 发布消息
person_info_pub.publish(person_msg);
ROS_INFO("Publish Person Info: name:%s age:%d sex:%d",
person_msg.name.c_str(), person_msg.age, person_msg.sex);
// 按照循环频率延时
loop_rate.sleep();
}
return 0;
}
同路径下添加订阅者代码person_subscriber.cpp:
/**
* 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
*/
#include
#include "learning_topic/Person.h"
// 接收到订阅的消息后,会进入消息回调函数
void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
{
// 将接收到的消息打印出来
ROS_INFO("Subcribe Person Info: name:%s age:%d sex:%d",
msg->name.c_str(), msg->age, msg->sex);
}
int main(int argc, char **argv)
{
// 初始化ROS节点
ros::init(argc, argv, "person_subscriber");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
// 循环等待回调函数
ros::spin();
return 0;
}
修改CMakeList.txt,添加下面六行代码,说明编译规则:
完成后编译,启动订阅者和发布者,运行成功。
不管是自定义的消息还是订阅者和发布者,其流程都是一样的:
1、建立规则文件:
订阅者和发布者就是建立cpp源文件,定义名称、规则、回调函数等;
消息就是建立消息文件,定义新的消息类型应该是什么样的消息,具有什么样的规则;
2、建立好规则文件或者说源文件后,就是修改package.xml和CMakeList.txt文件,添加运行和编译应该依赖的包、编译时应该链接的库。