ROS实践笔记3
ROS话题通信模型
角色:
1. master---->管理者
2. talker---->发布者
3. listener---->订阅者
流程:
管理者可以通过话题建立发布者与订阅者之间的连接
流程实现:
1. 发布者将话题与RPC地址发送给管理者进行注册。
2. 订阅者在管理者处注册自己关注的话题。
3. 将发布者和订阅者的话题进行对比,如果二者一致,则将发布者的RPC地址发送给订阅者。
4. 订阅者根据RPC地址访问发布者
5. 发布者对订阅者的访问进行响应,并将自己的TCP地址发送给订阅者。
6. 订阅者根据TCP地址访问发布者。
7. 发布者将消息发送至订阅者
注意:
1. 使用的协议有RPC和TCP
2. 步骤1和步骤2没有顺序关系
3. talker 和listener 都可以存在很多个
4. talker 和listener 建立连接后,master就可以关闭
话题通信应用时的关注点:
1. 大部分实现已经被封装
2. 话题设计
3. 发布者实现
4. 订阅者实现
5. 消息载体
ROS中文本消息需要使用头文件
std_msgs/String.h
c++
创建一个发布者的流程:
- 包含头文件。
ros/ros.h //消息类型的头文件,下面是文本文件的消息类型 std_msgs/String.h
- 初始化ROS节点
- 创建节点句柄 NodeHandle
- 创建发布者对象,使用advertise函数需要范型,话题名称和队列长度为函数的参数
- 创建发布的消息内容并发布
代码如下
# include"ros/ros.h"
# include"std_msgs/String.h"
int main(int argc, char *argv[])
{
ros::init(argc,argv,"pub");
ros::NodeHandle nh;
ros::Publisher pub=nh.advertise<std_msgs::String>("topic",10);
std_msgs::String msg;
ros::Duration(3).sleep();
while(ros::ok())
{
msg.data="hello";
pub.publish(msg);
}
return 0;
}
其中
ros::Duration(3).sleep();
用来延迟第一条数据的发送三秒钟
使用rostopic echo 话题名称,可以打印出发布者发布的信息
rostopic echo topic
订阅方实现
- 包含头文件,其中需要包含订阅的消息类型
- 初始化ROS节点
- 创建节点句柄
- 创建订阅者对象
- 处理订阅到的数据 需要手写函数
- spin()函数(回头,调用回调函数);
代码如下:
# include"ros/ros.h"
# include"std_msgs/String.h"
# include<sstream>
void Domsg(const std_msgs::String::ConstPtr &msg)
{
ROS_INFO("topic is %s",msg->data.c_str());
return ;
}
int main(int argc, char *argv[])
{
ros::init(argc,argv,"sub");
ros::NodeHandle nh;
ros::Subscriber sub=nh.subscribe("topic",10,Domsg);
ros::spin();
return 0;
}
使用rqt_graph命令,可以画出通信图
rqt_graph
python
发布者实现:
#! /usr/bin/env python
from ast import While
import rospy
from std_msgs.msg import String #发布消息的类型
if __name__=="__main__":
rospy.init_node("pub") #传入节点名称
pub=rospy.Publisher("topic",String,queue_size=10) #创建发布者对象
msg=String() #创建消息对象
rate=rospy.Rate(1) #制定发布频率
count=1 #计数器
rospy.sleep(3)
while not rospy.is_shutdown():
msg.data="topic"+str(count) #将数字转化为字符串
pub.publish(msg)
rospy.loginfo("topic is %s---->",msg.data)
rate.sleep()
count+=1
#创建并发布消息
订阅者实现:
#! /usr/bin/env python
import rospy
from std_msgs.msg import String
def DoMsg(msg):# 回调函数
rospy.loginfo("topic is -----> %s",msg.data)
if __name__=="__main__":
rospy.init_node("sub") #初始化节点
sub=rospy.Subscriber("topic",String,DoMsg,queue_size=10)
rospy.spin()
其中 python 发布者中的
rospy.sleep(3)
与 c++ 发布者中的
ros::Duration(3).sleep();
作用都是让程序在发布第一条信息之前休眠3秒,使其完成注册后再发布信息,防止订阅者错过信息。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)