目录
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文件修改
话题通信实现模型是比较复杂的,该模型如下图所示,该模型中涉及到三个角色:
整个流程由以下步骤实现:
注意1:上述实现流程中,前五步使用的 RPC协议,最后两步使用的是 TCP 协议
注意2: Talker 与 Listener 的启动无先后顺序要求
注意3: Talker 与 Listener 都可以有多个
注意4: Talker 与 Listener 连接建立后,不再需要 ROS Master。也即,即便关闭ROS Master,Talker 与 Listern 照常通信。
pub C++
#include "ros/ros.h"
#include "std_msgs/String.h"
#include
ros::init(argc,argv,"node_name");
//参数1与参数2 后期为节点传值使用
//参数3为节点名称(可随意取名),于rqt_graph命令中清晰查看节点信息
ros::NodeHandle nh;//该类中封装了一些常用的ros功能
ros::Publisher pub = nh.advertise("topic",10);
//参数1为要发布到的话题(话题名称可随意)
//参数2为队列中保存的消息数,超出此阈值的,先进的先销毁
std_msgs::String msg;//
ros::Rate rate(0.5);
//参数:每秒输出n次
//上述代码实现每0.5秒输出一次日志
int count = 0;
while(ros::ok())
{
//使用stringstream拼接字符串与编号
count++;
std::stringstream ss;
ss << "hello --->" << count;//1.把"hello --->"这串字符送入输入流,2.把count计数编号输入输入流
msg.data = ss.str();//把输入流中的统一为字符类型
pub.publish(msg); //发布消息
//添加日志
ROS_INFO("PUB DATA:%s",ss.str().c_str());
//根据前面制定的发送频率自动休眠 休眠时间 = 1/频率
rate.sleep();
//暂时无作用(官方推荐)
ros::spinOnce();
}
//为了防止中文乱码可于mian函数开头添加一句setlocale(LC_ALL,"");
//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}
)
sub C++
#include "ros/ros.h"
#include "std_msgs/String.h"
#include
ros::init(argc,argv,"node_name");
//参数1与参数2 后期为节点传值使用
//参数3为节点名称(可随意取名),于rqt_graph命令中清晰查看节点信息
ros::NodeHandle nh;//该类中封装了一些常用的ros功能
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());
}
ros::spin();//spin : back to doMsg
setlocale(LC_ALL,"");//防止中文乱码
//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
实现订阅方
pub Python
#! /usr/bin/env python
#1.import ros
import rospy
from std_msgs.msg import String #data class
if __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 = "hello" +str(count)
#output data
pub.publish(msg)
rospy.loginfo("pub data:%s",msg.data)
rate.sleep()
#176行
并且.py因为在linux操作系统中没有可执行权限,还需在scripts(就是放.py文件的文件夹,一般于功能包目录下创建,与src目录平行)目录下添加:
$ chmod +x *.py
catkin_install_python(PROGRAMS
scripts/demo01_pub_p.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
sub Python
#! /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()
#176行
并且.py因为在linux操作系统中没有可执行权限,还需在scripts(就是放.py文件的文件夹,一般于功能包目录下创建,与src目录平行)目录下添加:
$ chmod +x *.py
catkin_install_python(PROGRAMS
scripts/demo02_sub_p.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
到此实现C++和Python的话题通信