【ROS】ros学习笔记(3)——话题通信

📅 2026/7/15 21:36:39
【ROS】ros学习笔记(3)——话题通信
ros学习笔记——话题通信一、ros话题通信原理0.Talker注册1.Listener注册2.ROS Master实现信息匹配3.Listener向Talker发送请求4.Talker确认请求5.Listener与Talker件里连接6.Talker向Listener发送消息二、发布方创建创建工作空间编写程序创建功能包编写程序修改CMake文件运行发布方 添加新要求 以10Hz为频率发布数据三、接收方创建写cpp文件修改CMake文件测试四、查看节点关系一、ros话题通信原理话题通信实现模型是比较复杂的该模型如下图所示,该模型中涉及到三个角色:ROS Master (管理者)Talker (发布者)Listener (订阅者)ROS Master 负责保管 Talker 和 Listener 注册的信息并匹配话题相同的 Talker 与 Listener帮助 Talker 与 Listener 建立连接连接建立后Talker 可以发布消息且发布的消息会被 Listener 订阅。整个流程由以下步骤实现:0.Talker注册Talker启动后会通过RPC在 ROS Master 中注册自身信息其中包含所发布消息的话题名称。ROS Master 会将节点的注册信息加入到注册表中。1.Listener注册Listener启动后也会通过RPC在 ROS Master 中注册自身信息包含需要订阅消息的话题名。ROS Master 会将节点的注册信息加入到注册表中。2.ROS Master实现信息匹配ROS Master 会根据注册表中的信息匹配Talker 和 Listener并通过 RPC 向 Listener 发送 Talker 的 RPC 地址信息。3.Listener向Talker发送请求Listener 根据接收到的 RPC 地址通过 RPC 向 Talker 发送连接请求传输订阅的话题名称、消息类型以及通信协议(TCP/UDP)。4.Talker确认请求Talker 接收到 Listener 的请求后也是通过 RPC 向 Listener 确认连接信息并发送自身的 TCP 地址信息。5.Listener与Talker件里连接Listener 根据步骤4 返回的消息使用 TCP 与 Talker 建立网络连接。6.Talker向Listener发送消息连接建立后Talker 开始向 Listener 发布消息。注意1:上述实现流程中前五步使用的 RPC协议最后两步使用的是 TCP 协议注意2: Talker 与 Listener 的启动无先后顺序要求注意3: Talker 与 Listener 都可以有多个注意4: Talker 与 Listener 连接建立后不再需要 ROS Master。也即即便关闭ROS MasterTalker与 Listern 照常通信。二、发布方创建创建工作空间在终端输入mkdir-pdemo03_ws/src创建好工作空间后编译一下catkin_make然后进入工作空间cddemo03_ws code.打开文件后在.vscode下新建一个tasks.json配置文件写以下内容{// 有关 tasks.json 格式的文档请参见 // https://go.microsoft.com/fwlink/?LinkId733558version:2.0.0,tasks:[{label:catkin_make:debug, //代表提示的描述性信息type:shell, //可以选择shell或者process,如果是shell代码是在shell里面运行一个命令如果是process代表作为一个进程来运行command:catkin_make,//这个是我们需要运行的命令args:[],//如果需要在命令后面加一些后缀可以写在这里比如-DCATKIN_WHITELIST_PACKAGES“pac1;pac2”group:{kind:build,isDefault:true},presentation:{reveal:always//可选always或者silence代表是否输出信息},problemMatcher:$msCompile}]}这样按CtrlshiftB就可以实现编译了编写程序创建功能包选中demo03_ws下的src右击选择![[Pasted image 20260713163216.png]]功能包名字为piumbing_pub_sub需要的依赖有roscpprospystd_msgs编写程序在demo03_ws目录下的src下的src创建一个新的cpp文件命名为demo01_pub.cpp#includeros/ros.h#includestd_msgs/String.h/* 发布方实现 1.包含头文件 ros中文本类型--std_msgs/String.h 2.初始化ros节点 3.创建节点句柄 4.创建发布者对象 5.编写发布逻辑并发布数据 */intmain(intargc,char*argv[]){//2.初始化ros节点ros::init(argc,argv,erGouZi);//3.创建节点句柄ros::NodeHandle nh;//4.创建发布者对象nh.advertise消息类型(话题,数据缓冲区长度)ros::Publisher pubnh.advertisestd_msgs::String(fang,10);//5.编写发布逻辑并发布数据//先创建被发布的消息std_msgs::String msg;//编写循环循环中发布数据while(ros::ok){msg.datahello;pub.publish(msg);//发布数据}return0;}修改CMake文件修改demo03_ws目录下的src下的src下的cmake文件第136行取消注释add_executable(节点名 cpp文件)注意一般节点名选用和cpp文件名一致add_executable(demo01_pub src/demo01_pub.cpp)第149-151行target_link_libraries取消注释target_link_libraries(和上一条同名的节点名 ${catkin_LIBRARIES} )即target_link_libraries(demo01_pub${catkin_LIBRARIES})运行启动rosroscore开一个新的终端rosrun 功能包名 节点名source./devel/setup.bash rosrun plumbing_pub_sub demo01_pub这样后没有反应是正常的因为消息只是发出去了但是没有发到控制台我们可以通过rostopic echo 话题名称命令监听到数据rostopicechodemo01_pub发布方 添加新要求 以10Hz为频率发布数据修改cpp文件#includeros/ros.h#includestd_msgs/String.h#includesstream/* 发布方实现 1.包含头文件 ros中文本类型--std_msgs/String.h 2.初始化ros节点 3.创建节点句柄 4.创建发布者对象 5.编写发布逻辑并发布数据 */intmain(intargc,char*argv[]){setlocale(LC_ALL,);//2.初始化ros节点ros::init(argc,argv,erGouZi);//3.创建节点句柄ros::NodeHandle nh;//4.创建发布者对象nh.advertise消息类型(话题,数据缓冲区长度)ros::Publisher pubnh.advertisestd_msgs::String(fang,10);//5.编写发布逻辑并发布数据//要求以10HZ频率发布数据并且在文本后添加编号//先创建被发布的消息std_msgs::String msg;//发布频率 10hz发送ros::Raterate(10);//设置编号intcount0;//编写循环循环中发布数据while(ros::ok){count;std::stringstream ss;sshello--count;msg.datass.str();// msg.data hello;pub.publish(msg);//添加日志ROS_INFO(发布的数据是%s,ss.str().c_str());rate.sleep();}return0;}效果如下三、接收方创建写cpp文件在demo03_ws目录下的src下的src创建一个新的cpp文件命名为demo01_sub.cpp#includeros/ros.h#includestd_msgs/String.h#includesstream/* 订阅方实现 1.包含头文件 ros中文本类型--std_msgs/String.h 2.初始化ros节点 3.创建节点句柄 4.创建订阅者对象 5.处理订阅的数据 6.声明一个spin函数 *///用于处理订阅到的数据的回调函数 参数为订阅到的数据的ConstPtr常量指针voiddoMsg(conststd_msgs::String::ConstPtrmsg){//通过msg获取并操作订阅到的数据ROS_INFO(翠花订阅到的数据%s,msg-data.c_str());}intmain(intargc,char*argv[]){setlocale(LC_ALL,);// 2.初始化ros节点ros::init(argc,argv,cuiHua);//节点名称要具有唯一性// 3.创建节点句柄ros::NodeHandle nh;// 4.创建订阅者对象 nh.subscribe数据类型(话题类型,数据缓冲区长度,回调函数名称)ros::Subscriber subnh.subscribestd_msgs::String(fang,10,doMsg);//其实数据类型可以不写// 5.处理订阅的数据ros::spin();//“头“”函数为了使回调函数循环执行如果没有可能订阅不到return0;}修改CMake文件修改在demo03_ws目录下的src下的src下的CMake添加add_executable函数和target_link_libraries函数![[Pasted image 20260713215858.png]]测试编译 100%且没有报错就可以执行下一步开一个终端roscore再开一个新的终端运行发布者节点source./devel/setup.bash rosrun plumbing_pub_sub demo01_pub再开一个新的终端运行接收者节点source./devel/setup.bash rosrun plumbing_pub_sub demo01_sub效果如下四、查看节点关系在新的终端输入rqt_graph学习的为赵虚左老师的教程 1.老师的文档 2.老师的视频在笔记上理论部分大量参考了老师的文档