笔者根据 古月居 · ROS入门21讲 学习整理,并参考《ROS机器人开发实践》一书。
相关课件及源码可参考 Github/huchunxu/ros_21_tutorials
自定义话题消息
- 创建 learning_topic/msg/Person.msg 文件
- 在 Person.msg 文件中添加自定义话题消息结构如下
string name
uint8 sex
uint8 age
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
- 编译相关(注:若使用RobowareStudio则会自动添加以下内容)
- 在 package.xml 中添加功能包依赖
- 编译依赖:
<build_depend>message_generation</build_depend>
- 运行依赖:
<exec_depend>message_runtime</exec_depend>
- 编译依赖:
- 在 CMakeLists.txt 添加编译选项
- 在
find_package
中添加功能包message_generation
- 在相应注释位置添加
add_message_files(FILES Person.msg) generate_messages(DEPENDENCIES std_msgs)
- 在
catkin_package
中的CATKIN_DEPENDS
添加message_runtime
。注:要去掉该行的“#”注释符号才可编译成功。
- 在
- 编译生成语言相关文件
- 在 package.xml 中添加功能包依赖
发布Person结构的话题消息
- 右键点击 catkin_ws/src/learning_topic/src 文件夹,点击 “新建CPP源文件” 输入文件名
person_publisher
,点击回车键弹出列表,选择 “加入到新的可执行文件中” ,则会创建一个与cpp文件同名的可执行文件(ROS节点)。该文件编辑如下。
/**
* 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
*/
#include <ros/ros.h>
#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结构的话题消息
- 右键点击 catkin_ws/src/learning_topic/src 文件夹,点击 “新建CPP源文件” 输入文件名
person_subscriber
,点击回车键弹出列表,选择 “加入到新的可执行文件中” ,则会创建一个与cpp文件同名的可执行文件(ROS节点)。该文件编辑如下。
/**
* 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
*/
#include <ros/ros.h>
#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;
}
运行测试
- 在主界面左上角,修改资源管理器旁的构建方式为“Debug”,并点击小锤子进行构建。
- 点击主界面上方“ROS-运行roscore”
- 在主界面右侧下方点击“+”创建新终端,输入
$ source devel/setup.bash
。输入$ rosrun learning_topic person_subscriber
运行 person_subscriber 进行等待。 - 在主界面右侧下方点击“+”创建新终端,输入
$ source devel/setup.bash
。输入$ rosrun learning_topic person_publisher
运行 person_publisher 发布话题。 - 实验结果如下