栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

ROS入门保姆级教程:6-ROS话题通信实现

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ROS入门保姆级教程:6-ROS话题通信实现

ROS入门往期:
ROS入门保姆级教程:1-hello world初体验
ROS入门保姆级教程:2-VScode中使用ROS
ROS入门保姆级教程:3-ROS文件系统
ROS入门保姆级教程:4-ROS文件系统操作指令
ROS入门保姆级教程:5-ROS计算图

文章目录
  • 0 前言
  • 1 理论模型
    • 1.1 话题发布与订阅实现流程
  • 2 话题通信的C++实现
    • 2.1 发布方实现(C++)
    • 2.2 订阅方实现(C++)
    • 2.3 测试结果
  • 3 话题通信的Python实现
    • 3.1 发布方实现(Python)
    • 3.2 订阅方实现(Python)
    • 3.3 测试结果

0 前言

ROS 中的基本通信机制主要有如下三种实现策略:

  • 话题通信(发布订阅模式)
  • 服务通信(请求响应模式)
  • 参数服务器(参数共享模式)

本文主要介绍话题通信部分

话题通信是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。

话题通信的应用场景也极其广泛,主要用于不断更新的、少逻辑处理的数据传输场景。

1 理论模型

话题通信实现模型是比较复杂的,该模型如下图所示,该模型中涉及到三个角色:

  • ROS Master (管理者)
  • Talker (发布者)
  • Listener (订阅者)

ROS Master 负责保管 Talker 和 Listener 注册的信息,并匹配话题相同的 Talker 与 Listener,帮助 Talker 与 Listener 建立连接,连接建立后,Talker 可以发布消息,且发布的消息会被 Listener 订阅。

1.1 话题发布与订阅实现流程

整个流程由以下步骤实现

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 Master,Talker 与 Listern 照常通信。

2 话题通信的C++实现

分析:
在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:

  • 发布方
  • 接收方
  • 数据(此处为普通文本)

实现流程:

  1. 编写发布方实现;
  2. 编写订阅方实现;
  3. 编辑配置文件;
  4. 编译并执行
2.1 发布方实现(C++)

C++源文件放置路径于:【/workspace_name / src / pkg_name / src / file_name.cpp】

  1. 源文件:
#include "ros/ros.h"
#include "std_msgs/String.h"//ROS文本类型
#include //字符串拼接

using namespace ros;



int	main(int argc, char **argv)
{
    //2.初始化ros节点
    init(argc, argv, "demo1_pub");
    
    //3.创建句柄
    NodeHandle nh_pub;
    
    //4.创建发布对象
    
    Publisher pub_obj = nh_pub.advertise("topic_name_pubsub", 10);
    
    //5.发布
    //5.1创建发布的消息
    std_msgs::String message;
    //5.2循环发布
    Rate rate(5);//5Hz
    int counter = 0;//计数器
    while(ok()) //节点存活判断
    {
        //字符串拼接
        std::stringstream ss;
        ss << "Pub Data by C++ ============= " << counter;
        counter ++;

        //数据发布
        message.data = ss.str();
        pub_obj.publish(message);

        //打印日志
        ROS_INFO("INFO:%s", ss.str().c_str());

        rate.sleep();
    }

    return 0;
}
  1. CMakeLists.txt 文件配置
#添加可执行文件
#add_executable(节点名,一般同文件名  src/文件名.cpp)
add_executable(demo1_pub src/demo1_pub_c.cpp)

#修改目标链接库
#target_link_libraries(节点名
#  ${catkin_LIBRARIES}
#)
target_link_libraries(demo1_pub
  ${catkin_LIBRARIES}
)
2.2 订阅方实现(C++)
  1. 源文件

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

using namespace ros;

void callback_sub(const std_msgs::String::ConstPtr &msg)
{
    //传入的是std_msgs::String类型的字符串
    //msg为一个常量指针的引用
    //通过msg获取并操作数据
    ROS_INFO("GET MSG: %s", msg->data.c_str());
}

int	main(int argc, char **argv)
{
    //2.初始化ros节点
    init(argc, argv, "demo2_sub");

    //3.创建句柄
    NodeHandle nh_sub;

    //4.创建订阅对象
    
    Subscriber sub_obj = nh_sub.subscribe("topic_name_pubsub", 10, callback_sub); //话题名称需要与发布方一致

    spin();//回头处理上一步的回调函数

    return 0;
}
  1. CMakeLists.txt 文件配置
#添加可执行文件
#add_executable(节点名,一般同文件名  src/文件名.cpp)
add_executable(demo2_sub src/demo2_sub_c.cpp)

#修改目标链接库
#target_link_libraries(节点名
#  ${catkin_LIBRARIES}
#)
target_link_libraries(demo2_sub
  ${catkin_LIBRARIES}
)
2.3 测试结果
  1. 发布订阅

  2. 计算图

3 话题通信的Python实现

Python源文件放置路径于:【/workspace_name / src / pkg_name / scripts / file_name.py】

3.1 发布方实现(Python)
  1. 源文件
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
#解决Python文件中中文编码编译报错

"""
发布方实现:
    1.导包
    2.初始化ros节点
    3.创建发布对象
    4.发布
"""

# 1. import bag
# 1.导包
import rospy
from std_msgs.msg import String

if __name__ == "__main__":
    # 2. initialization ROS node
    # 2. 初始化ros节点
    rospy.init_node("demo3_pub")

    # 3. Create a publish object
    # 3. 创建发布对象
    # def __init__(self, name, data_class, subscriber_listener=None, tcp_nodelay=False, latch=False, headers=None, queue_size=None):
    pub_obj = rospy.Publisher("topic_name_pubsub", String, queue_size=10)
    # pub_obj = rospy.Publisher("topic_name_pubsub", String, 10)  #Works, maybe report errors

    # 4. Publish
    # 4. 发布
    
    # 创建数据
    message_py = String()
    #设置频率
    rate = rospy.Rate(5)

    counter = 0
    while not rospy.is_shutdown(): #python判断节点
        message_py.data = "Pub Data by Python ============= " + str(counter)
        pub_obj.publish(message_py)

        #打印日志
        rospy.loginfo(message_py.data)

        counter += 1

        rate.sleep()

  1. 添加可执行权限
$ chmod +x *.py
#【*.py】可实现对目录下所有Python文件添加可执行权限

#或
$ chmod +x 【python_file_name.py】

#ll指令可查看权限
  1. CMakeLists.txt 文件配置
#指定Python解释器

catkin_install_python(PROGRAMS 
scripts/【python_file_name.py】
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

#该操作为Python文件选择恰当的解释器
#该操作在ROS的melodic及之前版本上不需要
3.2 订阅方实现(Python)
  1. 源文件
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
#解决Python文件中中文编码编译报错

"""
发布方实现:
    1.导包
    2.初始化ros节点
    3.创建订阅对象
    4.接收数据
"""

# 1. import bag
# 1. 导包
import string
import rospy
from std_msgs.msg import String

# 4. data processing
# 4. 回调函数接收数据
def callback_sub_py(msg_get):
    rospy.loginfo("GET MSG : " + msg_get.data)


if __name__ == "__main__":
    # 2. initialization ROS node
    # 2. 初始化ros节点
    rospy.init_node("demo4_sub")

    # 3. Create a Subscriber object
    # 3. 创建订阅对象
    # def __init__(self, name, data_class, callback=None, callback_args=None,
    #              queue_size=None, buff_size=DEFAULT_BUFF_SIZE, tcp_nodelay=False):
    sub_obj = rospy.Subscriber("topic_name_pubsub", String, callback_sub_py, queue_size=10)

    # 5. 回旋
    rospy.spin()
  1. 添加可执行权限
$ chmod +x *.py
#【*.py】可实现对目录下所有Python文件添加可执行权限

#或
$ chmod +x 【python_file_name.py】

#ll指令可查看权限
  1. CMakeLists.txt 文件配置
#指定Python解释器

catkin_install_python(PROGRAMS 
scripts/【python_file_name.py】
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

#该操作为Python文件选择恰当的解释器
#该操作在ROS的melodic及之前版本上不需要
3.3 测试结果
  1. 发布订阅
  2. 计算图
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1021894.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号