首页 > 编程语言 >ROS机器人编程<六>:了解ROS系统及使用VScode实现话题通信(C++)

ROS机器人编程<六>:了解ROS系统及使用VScode实现话题通信(C++)

时间:2024-11-05 21:18:30浏览次数:5  
标签:订阅 VScode 话题 C++ 消息 发布者 ROS hello

目录

ROS中基本的通信机制:

一、话题通信:

1.话题通信定义与基本概念

2.核心要素

3.工作流程

4.消息接口与数据类型

二、vscode实现话题通信

三、C++实现话题通信 

要求:编写发布订阅实现,要求发布方以10HZ(每秒10次)的频率发布文本消息,订阅方订阅消息并将消息内容打印输出

1.在功能包下的src文件夹下新建文件,分别命名为:hello_pub.cpp及hello_sub.cpp

2.hello_pub.cpp为发布者,循环发布信息:HelloWorld 后缀数字编号

3. 实现流程:

发布者:

订阅者:

4.发布者代码:

5.订阅者代码:

6.编辑配置文件:编辑 ros 包下的 CamkeLists.txt 文件 

7.编译并执行

8.通过实验我们可以观察到,hello_pub成功的发送了信息而hello_sub也成功地接收到了信息。

ROS中基本的通信机制:

1.话题通信(发布订阅模式)
2.服务通信(请求响应模式)
3.参数服务器(参数共享模式)
4.动作通信(话题和服务的配合)

一、话题通信:

1.话题通信定义与基本概念

话题通信是ROS(Robot Operating System,机器人操作系统)中使用频率最高的一种通信模式,话题通信是基于发布与订阅模式的通信方式,其中一个节点(发布者)发布消息,而另一个或多个节点(订阅者)订阅并接收这些消息。发布者和订阅者通过共同的话题(Topic)建立联系,实现数据的传输与交流。话题通信的应用场景也极其广泛,像雷达、摄像头、GPS.... 等等一些传感器数据的采集,也都是使用了话题通信,换言之,话题通信适用于不断更新的数据传输相关的应用场景。

2.核心要素

发布方(Talker):负责发布消息的节点,它将数据发布到特定的话题上。

订阅方(Listener):负责订阅并接收来自特定话题的消息的节点。

话题(Topic):发布方和订阅方之间建立联系的桥梁,是数据传输的通道。

3.工作流程

话题通信的工作流程通常包括以下几个步骤:

  1. 发布者注册:发布者启动后,会在ROS Master(管理者)中注册自身信息,包括所发布消息的话题名称和远端调用地址(RPC)。ROS Master会将节点的注册信息加入到注册表中。

  2. 订阅者注册:订阅者也会通过RPC在 ROS Master 中注册自身信息自己的话题。

  3. 匹配与连接:ROS Master会将订阅者与发布者的话题进行对比,发现有匹配的两者时,会把发布者的RPC地址发送给订阅者。订阅者根据RPC地址远程访问发布者,获取发布者的TCP地址,并建立连接。

  4. 消息发布与接收:建立连接后,发布者可以发布消息,这些消息会被订阅者接收并处理。

  5. Listener向Talker发送请求:Listener 根据接收到的 RPC 地址,通过 RPC 向 Talker 发送连接请求,传输订阅的话题名称、消息类型以及通信协议(TCP/UDP)。

  6. Talker确认请求:Talker 接收到 Listener 的请求后,也是通过 RPC 向 Listener 确认连接信息,并发送自身的 TCP 地址信息。

  7. Listener与Talker件里连接:Listener 根据步骤6返回的消息使用 TCP 与 Talker 建立网络连接。

  8. Talker向Listener发送消息:连接建立后,Talker 开始向 Listener 发布消息。

4.消息接口与数据类型

在ROS中,话题通信的消息接口和数据类型具有多样性。ROS2通过std_msgs包封装了一些原生的数据类型,如String、Int8、Int16等,这些数据类型可以作为话题通信的载体。此外,ROS2还预定义了许多标准话题消息接口,如sensor_msgs包中定义了关于传感器消息的接口,geometry_msgs包中定义了关于几何消息相关的接口。当这些预定义的消息接口无法满足需求时,用户还可以自定义接口消息。

二、vscode实现话题通信

按照之前的教程,直接打开test02_ws的vscode

cd test02_ws
code .

三、C++实现话题通信 

要求:编写发布订阅实现,要求发布方以10HZ(每秒10次)的频率发布文本消息,订阅方订阅消息并将消息内容打印输出

1.在功能包下的src文件夹下新建文件,分别命名为:hello_pub.cpp及hello_sub.cpp

2.hello_pub.cpp为发布者,循环发布信息:HelloWorld 后缀数字编号

3. 实现流程:

发布者:

(1)包含头文件

(2)初始化 ROS 节点:命名(唯一)

(3)实例化 ROS 句柄

(4)实例化 发布者 对象

(5)组织被发布的数据,并编写逻辑发布数据

订阅者:

(1)包含头文件

(2)初始化 ROS 节点:命名(唯一) 

(3)实例化 ROS 句柄 

(4)实例化 订阅者 对象 

(5)处理订阅的消息(回调函数) 

(6)设置循环调用回调函数

4.发布者代码:

#include "ros/ros.h" // 引入ROS的核心头文件  
#include "std_msgs/String.h" // 引入标准消息类型中的字符串消息  
#include <sstream> // 引入字符串流库,用于字符串拼接  
  
int main(int argc, char  *argv[])  
{     
    // 设置程序的本地化环境,确保能够正确处理各种字符编码  
    setlocale(LC_ALL,"");  
  
    // 初始化ROS节点  
    // 参数1和参数2通常用于从命令行接收参数,这里暂时未使用  
    // 参数3是节点的名称,需要保证在ROS网络中唯一  
    ros::init(argc,argv,"talker");  
  
    // 实例化ROS节点句柄,用于与ROS系统通信  
    ros::NodeHandle nh;  
  
    // 创建一个发布者对象  
    // 泛型参数指定了发布的消息类型(std_msgs::String)  
    // 第一个参数指定了要发布到的话题名称("chatter")  
    // 第二个参数指定了消息队列的最大长度(10),超出此长度时,旧的消息会被丢弃  
    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10);  
  
    // 准备要发布的消息数据  
    std_msgs::String msg;  
    std::string msg_front = "Hello 你好!"; // 消息的前缀部分  
    int count = 0; // 用于计数,每次发布的消息都会附带一个递增的数字  
  
    // 设置发布频率(1Hz,即每秒发布一次)  
    ros::Rate r(1);  
  
    // 主循环,保持节点运行  
    while (ros::ok())  
    {  
        // 使用字符串流拼接前缀和计数器值,生成新的消息内容  
        std::stringstream ss;  
        ss << msg_front << count;  
        msg.data = ss.str(); // 将拼接后的字符串赋值给消息的数据部分  
  
        // 发布消息到指定的话题  
        pub.publish(msg);  
  
        // 打印调试信息,显示发送的消息内容  
        ROS_INFO("发送的消息:%s",msg.data.c_str());  
  
        // 根据设置的频率休眠,确保发布频率准确  
        r.sleep();  
  
        // 计数器自增,为下一次发布准备  
        count++;  
  
        // 调用ros::spinOnce()可以在循环中处理回调函数,虽然在这个简单示例中没有用到回调  
        ros::spinOnce();  
    }  
  
    // 程序结束  
    return 0;  
}

5.订阅者代码:

#include "ros/ros.h"
#include "std_msgs/String.h"

void doMsg(const std_msgs::String::ConstPtr& msg_p){
    ROS_INFO("我听见:%s",msg_p->data.c_str());
    // ROS_INFO("我听见:%s",(*msg_p).data.c_str());
}
int main(int argc, char  *argv[])
{
    setlocale(LC_ALL,"");
    //2.初始化 ROS 节点:命名(唯一)
    ros::init(argc,argv,"listener");
    //3.实例化 ROS 句柄
    ros::NodeHandle nh;

    //4.实例化 订阅者 对象
    ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg);
    //5.处理订阅的消息(回调函数)

    //     6.设置循环调用回调函数
    ros::spin();//循环读取接收的数据,并调用回调函数处理

    return 0;
}

6.编辑配置文件:编辑 ros 包下的 CamkeLists.txt 文件 

add_executable(hello_pub src/hello_pub.cpp)
add_executable(hello_sub src/hello_sub.cpp)

 target_link_libraries(hello_pub
   ${catkin_LIBRARIES}
 )
 target_link_libraries(hello_sub
   ${catkin_LIBRARIES}
 )

7.编译并执行

ctrl+shift+B编译,新建终端键入

roscore

新建终端

source ./devel/setup.bash
rosrun helloworld hello_pub

再新建一个终端,输入:

source ./devel/setup.bash
rosrun helloworld hello_sub

8.通过实验我们可以观察到,hello_pub成功的发送了信息而hello_sub也成功地接收到了信息。

通过更多的实验可以验证:

先启动roscore, 然后启动发布节点,然后启动订阅节点

可以发现,发布者正常发布信息,订阅者正常接收信息

先启动roscore, 然后启动订阅节点,然后启动发布节点

根据实验可知,订阅者没有信息,发布者启动后有发布信息,再观察订阅者可以接收到信息

先启动发布节点,然后启动订阅节点,然后启动roscore

根据实验观察,没有启动roscore时,启动发布者和订阅者都报错,最后启动roscore也能正常发送消息和接受消息。

正常启动后,关闭roscore终端,观察程序是否正常执行

可以观察到正常启动后,已经在发布者和订阅者之间建立了通信通道,关闭roscore对已经建立的话题通信没有影响。

另启终端,可以使用 rqt_graph 查看节点关系。

标签:订阅,VScode,话题,C++,消息,发布者,ROS,hello
From: https://blog.csdn.net/m0_68608816/article/details/143063500

相关文章

  • c++:智能指针
    文章目录前言一、内存泄漏1.1内存泄漏的定义1.2内存泄漏的常见原因1.3内存泄漏的危害二、智能指针的用法和模拟实现2.1RAII2.1.1RAII的工作原理2.1.2RAII的优点2.2智能指针的原理和设计思路2.3智能指针的种类和特点2.3.1std::auto_ptr2.3.2std::unique_ptr2.3......
  • 【Azure App Service】使用Microsoft.Office.Interop.Word来操作Word文档,部署到App Se
    问题描述在.NET项目中,使用Microsoft.Office.Interop.Word组件来操作Word文档,使用了Microsoft.Office.Interop.Word.Document对象中的Open和SaveAs方法。##打开文件doc=app.Documents.Open(refinputFile,refnullobj,refnullobj,refnullobj,refnullobj,refnullobj,......
  • 什么是C++模板,有哪些类型的模板?
    模板C++模板是一种强大的语言特性,允许开发者编写与类型无关的代码,从而实现代码的复用和灵活性。通过模板,可以定义函数和类,具体实现将由具体的类型实例化决定。函数模板函数模板(FunctionTemplates):函数模板用于定义一个通用的函数,该函数可以接受任意类型的参数。通过使用模......
  • c++知识及编译调试
    文章目录c++知识指针查找内存模型引用函数编译调试1.编译选项2.静态库和动态库3.gdb调试代码1.通讯录c++知识指针常量(的)指针constint*p=&a;指针指向可改,指向的值不可改。指针常量int*constp=&a;指针不能改,指向的值可改。查找unordered_setit!=uset.e......
  • C++20 STL CookBook 4:使用range在容器中创建view
    目录rangeviewrange_adaptor的三个概念以std::string和std::string_view为例子初次入手补充ranges的一些操作rangeviewrange_adaptor的三个概念新的范围库是C++20中更重要的新增功能之一。它为过滤和处理容器提供了新的范例。范围为更有效和可读的代码提供了简......
  • (分享源码)计算机毕业设计必看必学 上万套实战教程手把手教学JAVA、PHP,node.js,C++、pyth
    摘要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对校园疫情大学生防控出入系统等问题,对校园疫情大学生防控出入系统进行研究分析,然后开发设计......
  • ROS学习笔记5
    *回调函数回调函数是一种特殊的函数,它作为参数传递给另一个函数,并在被调用函数执行完毕后被调用。回调函数通常用于事件处理、异步编程和处理各种操作系统和框架的API。基本概念:回调:指被传入到另一个函数的函数。异步编程:指在代码执行时不会阻塞程序运行的方式。事件驱......
  • C++——用指向指针的指针的方法对5个字符串排序并输出。
    没注释的源代码#include<iostream>#include<string.h>usingnamespacestd;voidsort(char**p);intmain(){  constintm=20;  char**p,*pstr[5],str[5][m];  for(inti=0;i<5;i++)    pstr[i]=str[i];  cout<<"pleaseinput5......
  • 计算机毕业设计项目推荐,高校学生社团管理系统 00498(开题答辩+程序定制+全套文案 )上万
    摘要随着计算机科学技术的日渐成熟,人们已经深刻地认识到了计算机在各个领域中发挥的功能的强大,计算机已经进入到了人类社会发展的各个领域,并且发挥着十分重要的作用。目前学校学生社团的管理是一项系统而复杂的工作,它需要一个团队互相配合、分工协作。在该领域,传统的手工存取......
  • C++——用指向指针的指针的方法对n个整数排序并输出。要求将排序单独写成一个团数,整数
    没注释的源代码#include<iostream>usingnamespacestd;voidsortNumbers(int**arr,intn);intmain(){  intn;  cout<<"enterthenumberofintegers:";  cin>>n;  int**arr=newint*[n];  for(inti=0;i<n;i++)  {......