linux|ROS话题通信章节总结

ROS话题通信章节总结 目录

ROS话题通信章节总结
前言
一、理论模型
1.Talker注册
2.Listener注册
3.ROS Master实现信息匹配
4.Listener向Talker发送请求
5.Talker确认请求
6.Listener与Talker件里连接
7.Talker向Listener发送消息
二、话题通信基本操作(C++)
1.发布方实现
CMakeList.TXT文件修改
2.订阅方实现
CMakeList.TXT文件修改
三、话题通信基本操作(Python)
1.发布方实现
CMakeList.TXT文件修改
2.发布方实现
CMakeList.TXT文件修改
前言 一、理论模型

  • 话题通信实现模型是比较复杂的,该模型如下图所示,该模型中涉及到三个角色:
  • ROS Master (管理者)
  • Talker (发布者)
  • Listener (订阅者)
  • linux|ROS话题通信章节总结
    文章图片
  • ROS Master 负责保管 Talker 和 Listener 注册的信息,并匹配话题相同的 Talker 与 Listener,帮助 Talker 与 Listener 建立连接,连接建立后,Talker 可以发布消息,且发布的消息会被 Listener 订阅。
  • 整个流程由以下步骤实现:
  • 1.Talker注册
  • Talker启动后,会通过RPC在 ROS Master 中注册自身信息,其中包含所发布消息的话题名称。ROS Master 会将节点的注册信息加入到注册表中。
  • 2.Listener注册
  • Listener启动后,也会通过RPC在 ROS Master 中注册自身信息,包含需要订阅消息的话题名。ROS Master 会将节点的注册信息加入到注册表中。
  • 3.ROS Master实现信息匹配
  • ROS Master 会根据注册表中的信息匹配Talker 和 Listener,并通过 RPC 向 Listener 发送 Talker 的 RPC 地址信息。
  • 4.Listener向Talker发送请求
  • Listener 根据接收到的 RPC 地址,通过 RPC 向 Talker 发送连接请求,传输订阅的话题名称、消息类型以及通信协议(TCP/UDP)。
  • 5.Talker确认请求
  • Talker 接收到 Listener 的请求后,也是通过 RPC 向 Listener 确认连接信息,并发送自身的 TCP 地址信息。
  • 6.Listener与Talker件里连接
  • Listener 根据步骤4 返回的消息使用 TCP 与 Talker 建立网络连接。
  • 7.Talker向Listener发送消息
  • 连接建立后,Talker 开始向 Listener 发布消息。
注意1:上述实现流程中,前五步使用的 RPC协议,最后两步使用的是 TCP 协议
注意2: Talker 与 Listener 的启动无先后顺序要求
注意3: Talker 与 Listener 都可以有多个
注意4: Talker 与 Listener 连接建立后,不再需要 ROS Master。也即,即便关闭ROS Master,Talker 与 Listern 照常通信。
二、话题通信基本操作(C++)
  • 1.发布方实现
  • 基本流程:
pub C++
  • 1.include ros(包含ros的头文件)
#include "ros/ros.h" #include "std_msgs/String.h" #include

  • 2.ros_node init(ros节点初始化)
ros::init(argc,argv,"node_name"); //参数1与参数2 后期为节点传值使用 //参数3为节点名称(可随意取名),于rqt_graph命令中清晰查看节点信息

  • 3.create node_handle(ros句柄创建)
ros::NodeHandle nh; //该类中封装了一些常用的ros功能

  • 4.create pub(创建发布者对象)
ros::Publisher pub = nh.advertise("topic",10); //参数1为要发布到的话题(话题名称可随意) //参数2为队列中保存的消息数,超出此阈值的,先进的先销毁

  • 5.write pub data,output data(组织被被发布的数据,并编写发布的数据)
  • 5-1.pub data write(数据动态)
std_msgs::String msg; //

  • 5-2.output speed set (输出频率设置)
ros::Rate rate(0.5); //参数:每秒输出n次 //上述代码实现每0.5秒输出一次日志

  • 5-3.number set(输出次数计数)
int count = 0;

  • 5-4.while(输出循环)
while(ros::ok()) { //使用stringstream拼接字符串与编号 count++; std::stringstream ss; ss << "hello --->" << count; //1.把"hello --->"这串字符送入输入流,2.把count计数编号输入输入流 msg.data = https://www.it610.com/article/ss.str(); //把输入流中的统一为字符类型pub.publish(msg); //发布消息//添加日志 ROS_INFO("PUB DATA:%s",ss.str().c_str()); //根据前面制定的发送频率自动休眠 休眠时间 = 1/频率 rate.sleep(); //暂时无作用(官方推荐) ros::spinOnce(); }


//为了防止中文乱码可于mian函数开头添加一句setlocale(LC_ALL,"");


CMakeList.TXT文件修改
//136行 //demo01_pub和demo01_pub.cpp分别为两个需要配置的参数,为.C文件映射的名称 add_executable(demo01_pub src/demo01_pub.cpp)//154行 //demo01_pub为需要配置的参数,一般与文件名一致 target_link_libraries(demo01_pub ${catkin_LIBRARIES} )


  • 2.订阅方实现
  • 基本流程:
sub C++

  • 1.include ros(包含ros头文件)
#include "ros/ros.h" #include "std_msgs/String.h" #include

  • 2.ros_node init(ros节点初始化)
ros::init(argc,argv,"node_name"); //参数1与参数2 后期为节点传值使用 //参数3为节点名称(可随意取名),于rqt_graph命令中清晰查看节点信息

  • 3.create node_handle(创建句柄)
ros::NodeHandle nh; //该类中封装了一些常用的ros功能

  • 4.create sub (创建订阅者对象)
ros::Subscriber sub = nh.subscribe("topic_name",10,doMsg); 参数1为话题名称 参数2为队列中保存消息数 参数3为回调函数//回调函数: void doMsg(const std_msgs::String::ConstPtr &msg) { ROS_INFO("SUB DATA:%s",msg->data.c_str()); }

  • 注意:发布方与订阅方话题名称需要相同,否则无法进行话题通信
  • 5.solve sub data(处理发布者数据)
  • 6.spain del (回调函数)
ros::spin(); //spin : back to doMsg

setlocale(LC_ALL,""); //防止中文乱码

CMakeList.TXT文件修改
//138行 //demo02_2ub和demo02_sub.cpp分别为两个需要配置的参数,为.C文件映射的名称 add_executable(demo02_sub src/demo02_sub.cpp)//157行 //demo02_sub为需要配置的参数,一般与文件名一致 target_link_libraries(demo2_sub ${catkin_LIBRARIES} )

实现运行:
于工作空间下: $ source ./devel/setup.bash $ rosrun plumbing_pub_sub demo01_pub 实现发布方新开一个terminal窗口 $ source ./devel/setup.bash $ rosrun plumbing_pub_sub demo02_sub 实现订阅方

linux|ROS话题通信章节总结
文章图片

三、话题通信基本操作(Python)
  • 1.发布方实现
  • 基本流程:
pub Python

  • 1.import rospy(导入ros包)
  • 2.ros_node init(ros节点初始化)
  • 3.create pub(创建发布者对象)
  • 4.wirte pub date and output data(组织被被发布的数据,并编写发布的数据)
  • 因为Python代码实现较为简单,原理上的东西就不重复说,这里主要说一下用到的函数中的参数
  • Python代码实现发布方如下
#! /usr/bin/env python #1.import ros import rospy from std_msgs.msg import String #data classif __name__ == "__main__": #2.ros_node init rospy.init_node("zhangsan")//参数1:节点名 #3.create pub pub = rospy.Publisher("car",String,queue_size=10) #参数1:话题名称 #参数2:"msgs.data class" (发布数据的数据类型) #参数3:队列中保存消息数 #4.wirte pub date and output data #4-1create data msg = String() #4-2set rate rate = rospy.Rate(1) #4-3set number count = 0 #4-4while rospy.sleep(3)#一开始先休眠3秒 while not rospy.is_shutdown(): count += 1 msg.data = "https://www.it610.com/article/hello" +str(count) #output data pub.publish(msg) rospy.loginfo("pub data:%s",msg.data) rate.sleep()

CMakeList.TXT文件修改
#176行 并且.py因为在linux操作系统中没有可执行权限,还需在scripts(就是放.py文件的文件夹,一般于功能包目录下创建,与src目录平行)目录下添加: $ chmod +x *.pycatkin_install_python(PROGRAMS scripts/demo01_pub_p.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} )

  • 2.发布方实现
  • 基本流程:
sub Python
  • 1.import rospy(导入ros包)
  • 2.ros_node init(ros节点初始化)
  • 3.create sub(创建订阅者对象)
  • 4.back del (编写回调函数)
  • 5.spin()
  • 代码如下:
#! /usr/bin/env python #1.import ros import rospy from std_msgs.msg import String #data class#4.back del:(回调函数的编写) def doMsg(msg): rospy.loginfo("sub data:%s",msg.data)if __name__ == "__main__": #2.ros_node init rospy.init_node("huahua")#参数1.节点名称 #3.create sub sub = rospy.Subscriber("car",String,doMsg,queue_size=10) #参数1.topic_name, (话题名称) #参数2.data_class, (接收到的数据类型) #参数3.callback=None(回调函数) #参数4.que_size(队列可容纳的数据的长度) #5.spin() rospy.spin()

CMakeList.TXT文件修改
#176行 并且.py因为在linux操作系统中没有可执行权限,还需在scripts(就是放.py文件的文件夹,一般于功能包目录下创建,与src目录平行)目录下添加: $ chmod +x *.pycatkin_install_python(PROGRAMS scripts/demo02_sub_p.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} )

到此实现C++和Python的话题通信
【linux|ROS话题通信章节总结】

    推荐阅读