ROS:话题通信机制详解

这篇具有很好参考价值的文章主要介绍了ROS:话题通信机制详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ROS:通信机制

一、话题通信简介

话题在ROS中使用最为频繁,其通信模型也较为复杂。在ROS中有两个节点:一个是发布者Talker,另一个是订阅着Listener。两个节点分别发布、订阅同一个话题,启动顺序没有强制要求,此处假设Talker首先启动,可分为如下七步分析建立通信的详细过程。
ROS:话题通信机制详解
0、Talker注册
Talker启动,通过1234端口使用RPC向ROS Master注册发布者的信息,包含所发布消息的话题名;ROS Master会将节点的注册信息加入注册列表中。
1、Listener注册
Listener启动,同样通过RPC向ROS Master注册订阅者的信息,包含需要订阅的话题名。
2、ROS Master进行信息匹配
Master根据Listener的订阅信息从注册列表中进行查找,如果没有找到匹配的发布者,则等待发布者的加入:如果找到匹配的发布者信息,则通过RPC向Listener发送Talker的RPC地址信息。
3、Listener发送连接请求
Listener接收到Master发回的Talker地址信息,尝试通过RPC向Talker发送连接请求,传输订阅的话题名、消息类型以及通信协议(TCP/UDP)
4、Talker确认连接请求
Talker接收到Listener发送的连接请求后,继续通过RPC向Listener确认连接信息,其中包含自身的TCP地址信息。
5、Listener尝试与Talker建立网络连接
Listener接收到确认信息后,使用TCP尝试与Talker建立网络连接。
6、Talker向Listener发布数据
成功建立连接后,Talker开始向Listener发送话题消息数据。
从上面的分析中可以发现,前五个步骤使用的通信协议都是RPC,最后发布数据的过程才使用到TCP。ROS Master在节点建立连接的过程中起到了重要作用,但是并不参与节点之间最终的数据传输。

二、话题通信实操(C++)

2.1分析

在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
发布方
接收方
数据(此处为普通文本)

流程:
编写发布方实现;
编写订阅方实现;
编辑配置文件;
编译并执行。

2.2发布方代码

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

/*
发布方实现:
1.包含头文件
ROS中文本类型--->td_msgs/String.h
2.初始化ros节点
3.创建节点句柄
4.创建发布者对象
5.编写发布逻辑并发布数据
*/



int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    //2.初始化ros节点
    ros::init(argc,argv,"erGouZi");
    //3.创建节点句柄
    ros::NodeHandle nh;
    //4.创建发布者对象
    ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
    //5.编写发布逻辑并发布数据
    //要求以10HZ的频率发布数据,并且文本后添加编号
    //先创建被发布的消息
    std_msgs::String msg;
    //发布频率
    ros::Rate rate(10);
    //设置编号
    int count =0;
    //编写循环,循环中发布数据
    while (ros::ok())
    {
        count++;
        //msg.data = "hello";
        //实现字符串拼接数字
        std::stringstream ss;
        ss << "hello ---> " <<count;
        msg.data = ss.str();
        pub.publish(msg);

        //添加日志
        ROS_INFO("发布的数据是:%s",ss.str().c_str());

        rate.sleep();根据前面制定的发送贫频率自动休眠 休眠时间 = 1/频率;

        ros::spinOnce();//官方建议添加回调函数
    }
    
    return 0;
}

2.3订阅方代码

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


/*
订阅方实现:
1.包含头文件
ROS中文本类型--->td_msgs/String.h
2.初始化ros节点
3.创建节点句柄
4.创建订阅者对象
5.处理订阅数据
6.sain()函数
*/

void doMsg(const std_msgs::String::ConstPtr &msg)
{
    //通过msg获取并操作订阅到的数据
    ROS_INFO("翠花订阅的数据:%s",msg->data.c_str());

}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    //2.初始化ros节点
    ros::init(argc,argv,"cuihua");
    //3.创建节点句柄
    ros::NodeHandle nh;
    //4.创建订阅者对象
    ros::Subscriber sub = nh.subscribe("fang",10,doMsg);
    //5.处理订阅数据

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




    return 0;
}

2.4配置CMakeLists.txt

add_executable(demo01_pub src/demo01_pub.cpp)
add_executable(demo02_sub src/demo02_sub.cpp)

target_link_libraries(demo01_pub
  ${catkin_LIBRARIES}
)
target_link_libraries(demo02_sub
  ${catkin_LIBRARIES}
)

2.5执行

1.启动 roscore;

2.启动发布节点;

3.启动订阅节点。
ROS:话题通信机制详解

2.6注意

补充0:

vscode 中的 main 函数 声明 int main(int argc, char const *argv[]){},默认生成 argv 被 const 修饰,需要去除该修饰符

补充1:

ros/ros.h No such file or directory …

检查 CMakeList.txt find_package 出现重复,删除内容少的即可

参考资料:https://answers.ros.org/question/237494/fatal-error-rosrosh-no-such-file-or-directory/

补充2:

find_package 不添加一些包,也可以运行啊, ros.wiki 答案如下

You may notice that sometimes your project builds fine even if you did not call find_package with all dependencies. This is because catkin combines all your projects into one, so if an earlier project calls find_package, yours is configured with the same values. But forgetting the call means your project can easily break when built in isolation.


补充3:

订阅时,第一条数据丢失

原因: 发送第一条数据时, publisher 还未在 roscore 注册完毕

解决: 注册后,加入休眠 ros::Duration(3.0).sleep(); 延迟第一条数据的发送

三、话题通信实操(python)

3.1分析

分析:

在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
发布方
接收方
数据(此处为普通文本)

流程:
编写发布方实现;
编写订阅方实现;
为python文件添加可执行权限;
编辑配置文件;
编译并执行。

3.2发布方代码

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

/*
发布方实现:
1.包含头文件
ROS中文本类型--->td_msgs/String.h
2.初始化ros节点
3.创建节点句柄
4.创建发布者对象
5.编写发布逻辑并发布数据
*/



int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    //2.初始化ros节点
    ros::init(argc,argv,"erGouZi");
    //3.创建节点句柄
    ros::NodeHandle nh;
    //4.创建发布者对象
    ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
    //5.编写发布逻辑并发布数据
    //要求以10HZ的频率发布数据,并且文本后添加编号
    //先创建被发布的消息
    std_msgs::String msg;
    //发布频率
    ros::Rate rate(10);
    //设置编号
    int count =0;
    //编写循环,循环中发布数据
    while (ros::ok())
    {
        count++;
        //msg.data = "hello";
        //实现字符串拼接数字
        std::stringstream ss;
        ss << "hello ---> " <<count;
        msg.data = ss.str();
        pub.publish(msg);

        //添加日志
        ROS_INFO("发布的数据是:%s",ss.str().c_str());

        rate.sleep();//根据前面制定的发送贫频率自动休眠 休眠时间 = 1/频率;

        ros::spinOnce();//官方建议添加回调函数
    }
    
    return 0;
}

3.3订阅方代码

#! /usr/bin/env python

import rospy
from std_msgs.msg import String #发布消息的类型

"""
使用py 实现消息订阅
1.导包
2.初始化ROS节点
3.创建订阅者对象
4.回调函数处理数据
spin

"""
def doMsg(msg):
    rospy.loginfo("我订阅的数据:%s",msg.data)


if __name__ == "__main__":
    # 2.初始化ROS节点
    rospy.init_node("huahua")#传入节点名称
    # 3.创建订阅者对象
    sub = rospy.Subscriber("che",String,doMsg,queue_size=10)
    # 4.回调函数处理数据
    #5.spin
    rospy.spin()

3.4添加可执行权限

终端下进入 scripts 执行:chmod +x *.py

3.5配置 CMakeLists.txt

catkin_install_python(PROGRAMS
  scripts/demo01_pub_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
catkin_install_python(PROGRAMS
  scripts/demo02_sub_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

3.6执行

1.启动 roscore;

2.启动发布节点;

3.启动订阅节点。
ROS:话题通信机制详解
注:可以使用 rqt_graph 查看节点关系。

四、话题通信自定义msg

在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如: 激光雷达的信息… std_msgs 由于描述性较差而显得力不从心,这种场景下可以使用自定义的消息类型

msgs只是简单的文本文件,每行具有字段类型和字段名称,可以使用的字段类型有:

int8, int16, int32, int64 (或者无符号类型: uint*)
float32, float64
string
time, duration
other msg files
variable-length array[] and fixed-length array[C]
ROS中还有一种特殊类型:Header,标头包含时间戳和ROS中常用的坐标帧信息。会经常看到msg文件的第一行具有Header标头。

4.1自定义msg实现

4.1.1需求

创建自定义消息,该消息包含人的信息:姓名、身高、年龄等。

4.1.2流程

按照固定格式创建 msg 文件
编辑配置文件
编译生成可以被 Python 或 C++ 调用的中间文件

4.1.3定义msg文件

功能包下新建 msg 目录,添加文件 Person.msg

string name
uint16 age
float64 height

4.1.4编辑配置文件

package.xml中添加编译依赖与执行依赖

  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>
  <!-- 
  exce_depend 以前对应的是 run_depend 现在非法
  -->

CMakeLists.txt编辑 msg 相关配置

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
# 需要加入 message_generation,必须有 std_msgs
## 配置 msg 源文件
add_message_files(
  FILES
  Person.msg
)


# 生成消息时依赖于 std_msgs
generate_messages(
  DEPENDENCIES
  std_msgs
)


#执行时依赖
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES demo02_talker_listener
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)


4.1.5编译

编译后的中间文件查看:
C++ 需要调用的中间文件(…/工作空间/devel/include/包名/xxx.h)
ROS:话题通信机制详解
Python 需要调用的中间文件(…/工作空间/devel/lib/python3/dist-packages/包名/msg)
ROS:话题通信机制详解

4.2将自定义msg信息发布和订阅(C++)

4.2.1需求

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

4.2.2流程

分析:

在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
发布方
接收方
数据(此处为自定义消息)

流程:
编写发布方实现;
编写订阅方实现;
编辑配置文件;
编译并执行。

4.2.3vscode 配置

为了方便代码提示以及避免误抛异常,需要先配置 vscode,将前面生成的 head 文件路径配置进 c_cpp_properties.json 的 includepath属性:

{
    "configurations": [
        {
            "browse": {
                "databaseFilename": "",
                "limitSymbolsToIncludedHeaders": true
            },
            "includePath": [
                "/opt/ros/noetic/include/**",
                "/usr/include/**",
                "/xxx/yyy工作空间/devel/include/**" //配置 head 文件的路径 
            ],
            "name": "ROS",
            "intelliSenseMode": "gcc-x64",
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++17"
        }
    ],
    "version": 4
}

4.2.4发布方

#include "ros/ros.h"
#include "plumbing_pub_sub/Person.h"

/*
发布方:发布人的消息
1.包含头文件;
2.初始化ROS节点;
3.创建节点句柄
4.创建发布者对象
5.编写发布逻辑,发布数据

*/

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    ROS_INFO("这是消息的发布方");
// 2.初始化ROS节点;
    ros::init(argc,argv,"banZhuRrn");
// 3.创建节点句柄
    ros::NodeHandle nh;
// 4.创建发布者对象
    ros::Publisher pub = nh.advertise<plumbing_pub_sub::Person>("LiaoTian",10);
// 5.编写发布逻辑,发布数据
//5.1创建发布数据
    plumbing_pub_sub::Person person;
    person.name = "张三";
    person.age = 0;
    person.height = 1.73;

//5.2发布频率
    ros::Rate rate(1);

//5.3循环发布数据
    while(ros::ok())
    {
        person.age +=1;
        //核心:发布数据
        pub.publish(person);
        ROS_INFO("发布的消息:%s,%d,%.2f",person.name.c_str(),person.age,person.height);
        //休眠
        rate.sleep();
        //调用回头函数
        ros::spinOnce();
    
    }

    return 0;
}

4.2.5订阅方

#include "ros/ros.h"
#include "plumbing_pub_sub/Person.h"


/*
订阅方实现:
1.包含头文件
2.初始化ros节点
3.创建节点句柄
4.创建订阅者对象
5.处理订阅数据
6.spin()函数
*/

void doPerson(const plumbing_pub_sub::Person::ConstPtr & person)
{
    //通过msg获取并操作订阅到的数据
    ROS_INFO("订阅的的数据:%s,%d,%.2f",person->name.c_str(),person->age,person->height);

}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    ROS_INFO("这是消息的订阅方");
    //2.初始化ros节点
    ros::init(argc,argv,"jiaZhang");
    //3.创建节点句柄
    ros::NodeHandle nh;
    //4.创建订阅者对象
    ros::Subscriber sub = nh.subscribe("LiaoTian",10,doPerson);
    //5.处理订阅数据

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




    return 0;
}

4.2.6配置 CMakeLists.txt

需要添加 add_dependencies 用以设置所依赖的消息相关的中间文件。

add_executable(demo03_pub_person src/demo03_pub_person.cpp)
add_executable(demo04_sub_person src/demo04_sub_person.cpp)

add_dependencies(demo03_pub_person ${PROJECT_NAME}_generate_messages_cpp)
add_dependencies(demo04_sub_person ${PROJECT_NAME}_generate_messages_cpp)

target_link_libraries(demo03_pub_person
  ${catkin_LIBRARIES}
)
target_link_libraries(demo04_sub_person
  ${catkin_LIBRARIES}
)

4.2.7执行

1.启动 roscore;

2.启动发布节点;

3.启动订阅节点。
ROS:话题通信机制详解

4.3将自定义msg信息发布和订阅(python)

4.3.1需求

编写发布订阅实现,要求发布方以1HZ(每秒1次)的频率发布自定义消息,订阅方订阅自定义消息并将消息内容打印输出。

4.3.2流程

分析:
在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
发布方
接收方
数据(此处为自定义消息)

流程:
编写发布方实现;
编写订阅方实现;
为python文件添加可执行权限;
编辑配置文件;
编译并执行。

4.3.3vscode配置

为了方便代码提示以及误抛异常,需要先配置 vscode,将前面生成的 python 文件路径配置进 settings.json

{
    "python.autoComplete.extraPaths": [
        "/opt/ros/noetic/lib/python3/dist-packages",
        "/xxx/yyy工作空间/devel/lib/python3/dist-packages"
    ]
}


4.3.4发布方

#! /usr/bin/env python

import rospy
from plumbing_pub_sub.msg import Person #发布消息的类型

"""
使用py 实现人的消息发布
1.导包
2.初始化ROS节点
3.创建发布者对象
4.编写发布逻辑并发布数据

"""

if __name__ == "__main__":

#2.初始化ROS节点
    rospy.init_node("dama")#传入节点名称
# 3.创建发布者对象
    pub = rospy.Publisher("jiaoshetou",Person,queue_size=10)
# 4.编写发布逻辑并发布数据
    #创建数据
    p =Person()
    p.name = "奥特曼"
    p.age = 8
    p.height = 1.85
    #指定发布频率
    rate = rospy.Rate(1)
    #设置计数器
    count = 0
    #使用循环发布数据
    while not rospy.is_shutdown():
    #发布数据
        pub.publish(p)
        rospy.loginfo("发布的数据是:%s,%d,%.2f",p.name,p.age,p.height)
        rate.sleep()

4.3.5订阅方

#! /usr/bin/env python

import rospy
from plumbing_pub_sub.msg import Person #发布消息的类型

"""
使用py 实现消息订阅
1.导包
2.初始化ROS节点
3.创建订阅者对象
4.回调函数处理数据
spin

"""
def doPerson(p):
    rospy.loginfo("订阅的数据是:%s,%d,%.2f",p.name,p.age,p.height)


if __name__ == "__main__":
    # 2.初始化ROS节点
    rospy.init_node("daye")#传入节点名称
    # 3.创建订阅者对象
    sub = rospy.Subscriber("jiaoshetou",Person,doPerson,queue_size=10)
    # 4.回调函数处理数据
    #5.spin
    rospy.spin()

4.3.6权限设置

终端下进入 scripts 执行:chmod +x *.py

4.3.7配置 CMakeLists.txt

catkin_install_python(PROGRAMS
  scripts/demo03_pub_person_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
catkin_install_python(PROGRAMS
  scripts/demo04_sub_person_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

4.3.8执行

启动 roscore;

启动发布节点;

启动订阅节点。
ROS:话题通信机制详解
ROS:话题通信机制详解文章来源地址https://www.toymoban.com/news/detail-515193.html

到了这里,关于ROS:话题通信机制详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ROS】如何让ROS中节点实现数据交换Ⅰ--ROS话题通信

    Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。 roscore 启动ros核心节点 roscd 将工作空间切换到指定ros功能包 catkin_create_pkg 将工作空间切换到指定ros功能包 ** rqt_graph 启动节点间的关系图 rosrun 包名 节点名称 启动节点 ( rosrun

    2024年02月02日
    浏览(47)
  • ROS2从入门到精通1-2:详解ROS2服务通信机制与自定义服务

    本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 🚀详情:《ROS2从入门到精通》 服务 是 ROS 图中节点之间的另一种通信方法。服务基于 服务器-客户端 模型,不同于话题的 发布者-订阅者

    2024年04月09日
    浏览(37)
  • ROS学习——通信机制(服务通信)

     2.2.3 服务通信自定义srv调用A(C++) · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程    068服务通信(C++)3_客户端优化_Chapter2-ROS通信机制_哔哩哔哩_bilibili 服务通信也是ROS中一种极其常用的通信模式,服务通信是基于 请求响应 模式的,是一种应答机制。也即: 一个节点

    2024年02月08日
    浏览(77)
  • ROS学习2:ROS通信机制

    【Autolabor初级教程】ROS机器人入门 机器人操作系统 ROS 快速入门教程 1. 引言 机器人上可能集成各种传感器(雷达、摄像头、GPS等)以及运动控制实现, 为了解耦合 ,在 ROS 中 每一个功能点都是一个单独的进程 , 每一个进程都是独立运行的 。更确切的讲, ROS 是进程(也称为

    2024年02月08日
    浏览(44)
  • ROS学习笔记(六)---服务通信机制

    在ROS中,服务通信机制是一种点对点的通信方式,用于节点之间的请求和响应。它允许一个节点(服务请求方)向另一个节点(服务提供方)发送请求,并等待响应。 服务通信机制在ROS中使用以下两个概念: 服务(Service):服务是一种在ROS中定义的一对相关消息类型,包括

    2024年02月07日
    浏览(45)
  • 理解ROS Topic 通信频率背后的机制

    Topic是ROS的三种通信方式中最为基本、也是常用的一种。本文对于ROS的Topic通信背后的数据吞吐机制做一个较为详细、深入的介绍。 ROS中发布一个topic的函数是这样的 有三个参数: topic 就是我们要发布的话题, queue_size 是publisher队列中可以存储的消息数量, latch 是锁存,比如

    2024年02月08日
    浏览(48)
  • 随手笔记——将ROS图像话题转为OpenCV图像格式处理后再转为ROS图像话题发布(C++版)

    将ROS图像话题转为OpenCV图像格式处理后再转为ROS图像话题发布,主要通过cv_bridge的toImageMsg()和toCvCopy()函数(C++版)。 ​ 代码来自wiki

    2024年02月12日
    浏览(44)
  • 【ROS2入门】理解 ROS 2 Topics 话题

            大家好,我是虎哥,从今天开始,我将花一段时间,开始将自己从ROS1切换到ROS2,在上一篇中,我们一起了解ROS 2中节点的功能以及与之交互的工具, 这一篇,我们主要会围绕ROS中另外一个重要的概念“Topic ”,详细其具体的操作指令。 目录 一、ROS2中话题(Top

    2023年04月08日
    浏览(44)
  • 【ROS2指南-4】理解ROS2话题

    目标: 使用 rqt_graph 和命令行工具来反思 ROS 2 主题。 教程级别: 初学者 时间: 20分钟 内容 背景 先决条件 任务 1 设置 2 rqt_graph 3 ros2主题列表 4 ros2主题回显 5 ros2 主题信息 6 ros2界面展示 7 ros2主题发布 8 ros2 主题赫兹 9 清理 概括 下一步 ROS 2 将复杂的系统分解为许多模块化节

    2023年04月19日
    浏览(47)
  • ROS学习笔记(二):ROS话题的发布与订阅

    第十讲  发布者Publisher的编程 1. 创建功能包 learning_topic  $ cd ~/test1/src  $ catkin_create_pkg learning_topic std_msgs rospy roscpp geometry_msgs turtlesim 2.执行C++文件程序如下:放在创建的功能包的/learning_topic/src里 程序名为velocity_publisher.cpp 2.如何实现一个发布者(发布到ros自带节点 ) (1)初

    2024年02月04日
    浏览(79)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包