话题通信可以简单的理解为发布者发布消息,订阅者订阅发布者发布的消息。发布者和订阅者需要定义相同的话题名才可实现通信。
一、编写代码
以下是代码示例实现了简单的消息发布与消息订阅:
1、创建pub.cpp、sub.cpp两个文件
2、pub.cpp发布消息,sub.cpp订阅消息
pub.cpp
//发布方 pub.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
int main(int argc, char *argv[])
{
//初始化ros节点 "pub"为节点名,此节点名必须唯一
ros::init(argc,argv,"pub");
//实例化ros句柄
ros::NodeHandle nh;
//实例化发布者对象 "topic":发布到的话题名,10:设置队列中最大保存的消息数
ros::Publisher pub = nh.advertise<std_msgs::String>("topic",10);
std_msgs::String msg;
msg.data = "hello sub!";//定义需要发布的消息内容
//设置休眠频率
ros::Rate r(1);
while (ros::ok())
{
//发布消息
pub.publish(msg);
//加入打印
ROS_INFO("send:%s",msg.data.c_str());
//设置休眠
r.sleep();
}
return 0;
}
sub.cpp
//订阅方 sub.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
//回调函数 (每订阅到新的消息都会调用此函数)
void callBack(const std_msgs::String::ConstPtr& msg_p)
{
//打印订阅到的信息
ROS_INFO("receive:%s",msg_p->data.c_str());
}
int main(int argc, char *argv[])
{
//初始化ros节点,节点名称必须唯一
ros::init(argc,argv,"sub");
//实例化ros句柄
ros::NodeHandle nh;
//实例化订阅者对象 话题名必须与发布方一致,否则订阅不到
ros::Subscriber sub = nh.subscribe<std_msgs::String>("topic",10,callBack);
//回头处理回调函数订阅的消息
ros::spin();
return 0;
}
二、编写CMakeLists.txt
add_executable(pub src/pub.cpp)
add_executable(sub src/sub.cpp)
target_link_libraries(pub
${catkin_LIBRARIES}
)
target_link_libraries(sub
${catkin_LIBRARIES}
)
三、编译运行
1、vscode中 使用快捷键 Ctrl + Shift + B 编译
2、编译成功后生成pub、sub两个可执行文件
3、在工作空间目录下程序注册,输入命令:
source ./devel/setup.bash
3、运行pub、sub(运行前需要先运行起来roscore),我的功能包名为pub_sub输入命令:
roscore
rosrun pub_sub pub
rosrun pub_sub sub
注意:这里有可能运行时报错 “package xxxx not found”的错误。只需要在每个终端窗口中都运行一遍source ./devel/setup.bash ,再次运行时就没有报错了。
4、终端运行效果(左侧为roscore,右上为rosrun pub_sub pub,右下rosrun pub_sub sub),可以看出发布者(pub)在周期性的发布消息,订阅者(sub)在接收发布者(pub)发布的消息
5、使用rqt_graph查看节点拓扑图:新开一个终端输入命令:
rqt_graph
图中pub是我们在pub.cpp初始化ros节点时定义的名称。名称唯一。
图中sub是我们在sub.cpp初始化ros节点时定义的名称。名称唯一。
图中topic是我们在pub.cpp、sub.cpp实例化发布者或订阅者对象时定义的话题名,这里的话题名在发布者和订阅者之间名称必须相同。
(END)