roscpp 底层通讯协议更改

2023-05-16

        ROS为机器人开发者们提供了不同语言的编程接口,其中C++接口叫做roscpp,用来创建topic、service、param,实现ROS的通信功能。

roscpp is a C++ implementation of ROS. It provides a client library that enables C++ programmers to quickly interface with ROS TopicsServices, and Parameters. roscpp is the most widely used ROS client library and is designed to be the high-performance library for ROS.

        roscpp 底层采用的通讯协议为TCP/UDP,即无论使用ros的topic还是service,都是通过tcp或udp进行传输。

ros-melodic topic 传输机制

        ros topic 的pub sub 过程如下图,talker通过rpc向ros master 注册pub topic,listener通过rpc向ros master 注册sub topic。当ros master 发现listenser注册的sub topic 有人pub时,会把pub此topic的talker信息发送给listener,然后listener和talker通过rpc建立 tcp/udp连接。后续二者通过tcp/udp连接进行通讯,ros master不再参与。

        ros 底层通过 transport 实现talker和listener的通信。transport成对建立,为点对点通讯形式。当talker发布的一个topic被多个listener订阅时,ros会为每个listener都建立一个transport用于与其通信,当talker publish一个message时,ros通过遍历所有transport为每个listener发送message。

 roscpp_jbus 通信原理

        roscpp 是点对点通讯形式,talker 会为每一个listener创建一个transport。而jbus是点对面通讯,所以我们要改变pub的行为,即无论有几个listener,talker只创建一个transport,由jbus通过tipc广播给每一个listener。

 

        Class Transport 是ros抽象底层通信行为的基类。我们通过继承它来实现对roscpp底层通讯协议的更改,通过仿照Class TransportUDP编写Class TransportJBUS。

#ifndef ROSCPP_TRANSPORT_JBUS_H
#define ROSCPP_TRANSPORT_JBUS_H

#include <ros/types.h>
#include <ros/transport/transport.h>

#include <boost/thread/mutex.hpp>
#include "ros/io.h"
#include <ros/common.h>
#include <queue.h>
#include <jbus.h>
#include <vector>
namespace ros {
#define ROSJBUS_ID_FMT_     "ROSJBUS_%d"
#define MAX_RECV_QUEUE_     32

class TransportJBUS;
typedef boost::shared_ptr<TransportJBUS> TransportJBUSPtr;

class PollSet;

class ROSCPP_DECL TransportJBUS : public Transport {
  public:
	TransportJBUS(PollSet* poll_set, int max_datagram_size = 0);
	~TransportJBUS();

	/**
	 * @brief 用于链接jbus,只在 ConnectionManager::start 调用一次
	 *
	 * @return true
	 * @return false
	 */
	bool connect_jbus();

	virtual void close();

	/**
	 * @brief Create a Incoming object
	 *
	 * @param topic_name
	 * @param user 实质为jbus_handle_t *
	 * @return true
	 * @return false
	 */
	bool createIncoming(const char *topic_name, void *user);

	/**
	 * @brief Create a Outgoing object
	 *
	 * @param max_datagram_size 取决于发送端的设置
	 * @param topic_name
	 * @return TransportJBUSPtr
	 */
	TransportJBUSPtr createOutgoing(int max_datagram_size, const char *topic_name);
	// overrides from Transport
	virtual int32_t read(uint8_t* buffer, uint32_t size);
	virtual int32_t write(uint8_t* buffer, uint32_t size);

	virtual void enableWrite();
	virtual void disableWrite();
	virtual void enableRead();
	virtual void disableRead();

	virtual std::string getTransportInfo();

	virtual bool requiresHeader() {
		return false;
	}

	virtual const char* getType() {
		return "JBUSROS";
	}

	int getMaxDatagramSize() const {
		return max_datagram_size_;
	}

	void setJbusHandleIndex(int index) {
		jbus_handle_index_ = index;
	}

	int getJbusHandleIndex() const {
		return jbus_handle_index_;
	}

	const char *getTopicName() {
		return (const char *)topic_name_;
	}
  private:
	/**
	 * @brief 初始化epoll,设置topic name
	 *
	 * @param topic_name
	 * @return true
	 * @return false
	 */
	bool initializeSocket(const char *topic_name);

	/**
	 * @brief epoll 处理函数
	 *
	 * @param events
	 */
	void socketUpdate(int events);

	/**
	 * @brief jbus 回调函数,我们通过他接收数据然后触发POLLIN
	 *
	 * @param arg jbus收到的数据
	 * @param user jbus_handle_t *,传他是因为若传this指针,当对象析构后,无法通过this指针判断
	 * @return enum jbus_cb_status
	 */
	static enum jbus_cb_status callback_raw(nmpk_msg_t * arg, void *user);

	/** data **/
	PollSet* poll_set_;
	uint32_t max_datagram_size_;		// 因为jbus层有切片,所以我们默认其为MSGSIZE_NMPK_MAX (64*1024*1024)
	bool closed_;
	boost::mutex close_mutex_;

	bool expecting_read_;				//
	bool expecting_write_;				//
	int notify_pipe[2];					// 实际用于epoll的句柄
	char *topic_name_;					// 我们用topic name来操作jbus的收发
	queue_t *recv_queue_;				// 这个队列用于暂存接收数据
	bytes_t *recv_buffer_;				// 数据读取,第一次先读头,第二次才真正的读数据,所以需要一个缓存
	int reorder_bytes_;					// recv_buffer_已读数据长度
	int jbus_handle_index_;				// 当用于sub时,记住其in_transport_vec_的索引号
};

/**
 * @brief in 类型的对象管理结构体
 *
 */
struct jbus_handle_t {
	jbus_handle_t():handle_(nullptr), is_alive_(false) {};
	TransportJBUS *handle_;			// 对象的this指针
	boost::mutex handle_mutex_;
	bool is_alive_;					// 记录对象是否存活,构造:is_alive_ = true 析构:is_alive_ = false
};

}
#endif

具体实现细节及使用方式见README

# ROSCPP with libjbus

## 依赖

* libcjson

* support_libs

* libjbus

* ros [and it`s dependencies]

## 编译安装

* mkdir build

* cd build

* cmake ..

* make

* sudo cp devel/lib/libroscpp.so /opt/ros/melodic/lib/libroscpp.so

*or catkin_make ??*

## 说明

在 topic 中强制使用 jbus 代替 ros 原本使用的 TCP/UDP 底层通讯协议,使用时只需将编译出来的 libroscpp.so 代替 ros 中原本的libroscpp.so 即可,无需更改任何代码。

### transport_jbus

class TransportJBUS 由基类 Transport 派生,仿照 TransportUDP 编写,用于实现 topic 通讯。

由于原本的ros通讯机制为点对点,而jbus则为点对面,故我们在 pub topic 时,不再为每个 sub 链接都创建一个 transport,而是只创建一个 pub 用的 TransportJBUS 对象,并由 JbusTransportManager 中的 out_transport_map_ 进行管理。

在 sub topic 时,会创建一个 TransportJBUS,并创建一个 jbus_handle_t 对象对其进行管理。因为在 jbus 接收数据时,是通过void *指针将对象传入 jbus 的回调函数中,若我们直接将 TransportJBUS 对象的 this 指针传入,会导致对象析构后无法通过 this 指针判断,从而发生不可预料的问题。而 jbus_handle_t 通过标记 TransportJBUS 对象的状态,避免了这类问题。jbus_handle_t 由JbusTransportManager 中的 in_transport_vec_ 进行管理,并在程序退出时统一释放。

### jbus_transport_manager

class JbusTransportManager 用于管理 TransportUDP 对象。JbusTransportManager 是一个单例对象,在程序启动时会打印JBUSROS: start!

Hello world

表示现在使用的是 roscpp_jbus

### 其他修改

在其他源文件中的修改都由注释

```

/*** jbusros ***/

xxxxx;

/***************/

```

进行包裹,可通过搜索此注释快速定位各处修改

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

roscpp 底层通讯协议更改 的相关文章

  • python中sort函数的使用

    转自https blog csdn net lyy14011305 article details 76148512 我们需要对List进行排序 xff0c Python提供了两个方法 对给定的List L进行排序 xff0c 方法1 用L
  • Python序列与文件编程练习

    练习一 xff1a 使用以下语句存储一个字符串 xff1a string 61 My moral standing is 0 98765 将其中的数字字符串转换成浮点数并输出 代码 xff1a span class token commen
  • 简单平台用户信息管理系统

    要求 xff1a 用字典创建一个平台的用户信息 xff08 包含用户名和密码 xff09 管理系统 xff0c 新用户可以用与现有系统帐号不冲突的用户名创建帐号 xff0c 已存在的老用户则可以用用户名和密码登陆重返系统 实现代码 xff1
  • DataFrame小练习

    练习要求 xff1a 已知有一个列表中存放了一组音乐数据 xff1a music data 61 the rolling stones Satisfaction Beatles Let It Be Guns N Roses Don t Cr
  • nenuacm 2019 新生训练#10 字符串处理 题解

    题目链接 Ultra Fast Mathematician 解题思路 xff1a 题目说辣么多 xff0c 其实就是将两个二进制进行异或运算 xff1a 相同位上的数字相同 xff0c 异或结果为0 xff0c 否则为1 AC代码 span
  • 比较两个字符串大小(C语言)

    比较两个字符串的大小 比较两个字符串的大小 xff0c 不许使用strcmp函数 输入格式 在两行分别输入两个长度小于20的字符串 在字符串中不要出现换行符 xff0c 空格 xff0c 制表符 输出格式 直接输出 gt 或 lt 或 61
  • 海康web3.0使用记录

    项目中集成海康web3 0控制摄像头 近期项目中的业务需求涉及播放控制实时监控 xff0c 采用了海康web3 0的开发包 xff0c 开发包规范是32位IE11浏览器 xff0c 业务前期本来只是播放rtsp流的监控 xff0c 所以采取
  • 字符串与数字范围

    当字符串由数字组成时 xff0c 告诉你字符串的长度是length xff0c 意味着变成数字时最大会达到10length 1 比如告诉字符串长度最长为105 xff0c 那要注意数字可以达到10的105 1次方 xff0c 大约是1010
  • 如何在VS2019上配置OpenCV

    目录 前言正文1 安装Visual Studio2017 20192 配置 OpenCV https so csdn net so search q 61 OpenCV amp spm 61 1001 2101 3001 7020 2 1
  • GCC编译与Makefile基本语法

    写在最前面 xff1a 所有的博文都是为了若干年月以后当我再次翻看可以快速回想起之前的零星知识 学海无涯 xff0c 在看这篇文章的未来的你 xff0c 加油吧 xff01 目录 一 Makefile简介 二 Linux环境下的C语言编译过
  • CMake与CMakeLists是干什么的?

    写在最前面 xff1a 所有的博文都是为了若干年月以后当我再次翻看可以快速回想起之前的零星知识 学海无涯 xff0c 在看这篇文章的未来的你 xff0c 加油吧 xff01 因为之前看到有些软件中使用了CMake xff0c 不太理解为什么
  • 解决vscode智能代码提示快捷键 Ctrl+Space 无效的问题

    背景 vscode 智能代码提示除了输入时通过字符触发 xff0c 还能使用快捷键ctrl 43 space触发 xff0c 但是在 Windows 下会发现没有效果 因为这个快捷键在Windows下是系统的中文 简体 输入法 输入法 非输
  • Ubuntu系统安装、并解决Ubuntu系统网络连接激活失败问题

    Ubuntu系统安装 并解决Ubuntu系统网络连接激活失败问题 前言 1 Ubuntu安装过程中要保证网络连接稳定 2 Ubuntu安装过程要保证U盘不离开插槽 3 第一次安装请先浏览整个过程 xff0c 再进行操作 4 卸载Ubuntu
  • 激光雷达运动畸变去除方法

    文章目录 一 激光雷达运动畸变产生的原因二 为什么需要解决这个问题 xff1f 三 去除运动畸变的原理四 运动去畸变的方法1 纯估计方法 xff08 ICP VICP xff09 2 传感器辅助的方法 xff08 odom xff0c IM
  • curl下载文件的命令

    curl文件下载 curl将下载文件输出到stdout xff0c 将进度信息输出到stderr xff0c 不显示进度信息使用 silent 选项 1 curl URL silent 这条命令是将下载文件输出到终端 xff0c 所有下载的
  • 倍福ADS通讯(一)——ADS通讯简介

    ADS通讯简介 xff08 一 xff09 简介 xff08 二 xff09 ADS通讯协议概述 xff08 三 xff09 ADS通讯协议的设备标识 xff08 四 xff09 使用TwinCAT Ads中间件 xff08 一 xff09
  • 使用select的TCP服务器

    select函数详解 span class token macro property span class token directive hash span span class token directive keyword inclu
  • undefined symbol问题的查找、定位与解决方法

    今天被客户测出来一个问题 xff1a 程序执行中报错 xff0c 报错内容如下 XXXX xff1a symbol lookup error xff1a home libpdfium so xff1a undefined symbol xf
  • PRD-审批流BPM(结合企微审批引擎和结合flowable方案选择)

    前言 流程设计历来都是比较繁琐之事 xff0c 由于公司急需上线流程化的平台 xff0c 内部系统迫切需要升级 xff0c 在无产品经理的情况下 xff0c 我迎难而上 xff0c 正如 人人都是产品经理 所言 不是每个人都能以产品经理为业
  • VS Code用久了后,启动速度变慢

    目录 前提发现过程解决方法方法一方法二方法三 前提 不是因为电脑性能或者插件装太多导致的 是在使用一段时间后 xff0c 逐渐变慢 看结论直接跳转到解决方法 发现过程 困扰了很久 xff0c 这次一鼓作气找出问题 xff0c 太激动了 xf

随机推荐

  • ROS基础——话题、服务、动作编程

    文章目录 工作空间功能包ROS通信编程1 话题编程2 服务编程3 动作编程 参考资料 工作空间 存放工程开发相关文件的文件夹 xff0c 其中主要包括src xff0c build xff0c devel xff0c install文件夹
  • 一、ROS的五个特点

    一 ROS的五个特点 xff1a 1 点对点设计 点对点的设计通俗的讲就是一个大的工程项目 xff0c 每个动能相互是独立的 xff0c 或者耦合比较低 有一个大脑负责总的任务调度 xff0c 为服务和客户建立连接充当媒介 各个功能之间可以
  • LINK1104 无法打开文件“libboost_atomic-vc142-mt-gd-x64-1_76.lib”

    问题描述 LNK1104 无法打开文件 libboost atomic vc142 mt gd x64 1 76 lib 可能原因 xff1a 相应的包没有安装 xff0c 可以再电脑上搜一下 xff0c 是否搜索到 xff0c 如果搜索到
  • 2021-08-10

    LEGO loam第一次测试运行数据包nsh indoor outdoor成功 xff1a 记录以下 xff0c 以免自己忘记步骤 在第一个终端里 xff1a 1 source catkin ws devel setup bash xff0
  • 趣味GPS

    简介 GPS的全称是全球定位系统 the Global Positioning System 它属于美国政府 xff0c 并由洛杉矶的联合项目办公室 JPO Joint Program Office 管理 1957年 xff0c 苏联发射第
  • 如何访问西门子S1500PLC的IO系统

    提示 xff1a 本文仅代表个人在项目中的使用看法 xff0c 不参与任何真理的辩驳 文章目录 前言一 硬件配置二 访问方式1 S1500与ET200MP1 ET200MP的组态2 ET200MP的IO调用 2 S1500与ET200AL1
  • CubeMX配合PlatformIO开发STM32(STorM32),配置双MPU6050(板载与外置),并使用gui显示数据

    本人使用的设备 驱动 xff1a Windows10串口助手 4 3 25 其实啥都行 桃饱随处可买的usb ttl xff08 ch340G xff09 桃饱随处可买的stlinkmpu6050 xff08 一个板载 xff0c 一个通过
  • ros学习心得(九)ros之Topic通讯机制及发送与接收节点的编码与调试

    节点间需要有数据交互 xff0c 而ros所要解决的问题就是数据该如何交互 一 通讯原理图 ros在设计Node间通讯机制的时候 xff0c 考虑的是很周全的 Publisher 发送消息的 xff0c Subscriber 接收消息的 T
  • 硬石开发板STM32F407IGT6 (HAL库)学习笔记

    硬石开发板STM32F407IGT6 xff08 HAL库 xff09 学习笔记 2020 06 21 2020 06 22 2020 06 23 2020 06 24 该笔记为学习时遇到的问题与解决方法等内容的记录 xff0c 可能有错
  • Ubuntu20/视觉SLAM十四讲踩坑记录

    Ubuntu 视觉SLAM十四讲踩坑记录 Ubuntu xff08 20 xff09 视觉SLAM十四讲踩坑记录 xff1a 共性问题 xff1a 1 安装OpenCV后 xff0c 例程仍无法找到OpenCV文件 ch3 visualiz
  • AMESim2020.1仿真编译失败解决方法之一

    AMESim2020 1仿真编译失败解决方法之一 问题描述 xff1a 软件安装正确 xff0c 在准备和matlab联合仿真时 xff0c 换用VC2015以上版本编译器编译失败 解决方法 xff1a 到AMESim安装路径下 xff0c
  • Linux/Ubuntu20.04下载安装Geant4及B1示例测试

    Linux Ubuntu20 04下载安装Geant4及B1示例测试 0 参考内容1 下载geant4软件包2 geant4安装准备内容3 geant4文件编译4 安装数据包4 1 安装方式14 2安装方式2 5 添加文件路径6 B1示例测
  • Ubuntu20.04进行CUDA11.0及对应CUDNN安装

    Ubuntu20 04进行CUDA11 0及对应CUDNN安装 xff1a 基本步骤 xff1a 1 安装nvidia显卡驱动 可直接通过 xff1a 软件和更新 gt 附加驱动 选择满足CUDA版本的nvidia专有驱动 gt 应用更改
  • git分离头指针处理

    文章目录 1 什么是git分离头指针2 将git 分离头指针所指向的代码 xff08 commit id xff09 保存下来总结 本文将主要介绍一下git分离头指针状态 xff0c 并记录如何将分离头指针状态的代码合并到分支中 1 什么是
  • Docker使用系列——Docker安装(Ubuntu20.04)

    Docker使用系列 Docker安装 xff08 Ubuntu20 04 xff09 卸载安装测试问题 直接按官方安装教程即可 xff1a Install Docker Engine on Ubuntu 卸载 安装过老版本的Docker则
  • Docker使用系列——生成一个Ubuntu20.04+Pyqt5的容器

    由于在自己的电脑中安装Pyqt5不成功 xff0c 原因是与其他环境中的qt版本不兼容 因此 xff0c 了解到了docker xff0c 这里记录一下在docker中安装pyqt5过程 1 安装Docker并从官方仓库拉取Ubuntu 2
  • C语言实现链表(链式存储结构)

    链表 xff08 链式存储结构 xff09 及创建 链表 xff0c 别名链式存储结构或单链表 xff0c 用于存储逻辑关系为 一对一 的数据 与顺序表不同 xff0c 链表不限制数据的物理存储状态 xff0c 换句话说 xff0c 使用链
  • cmake与make的区别及CMakeLists.txt文件编写

    一 cmake与make的区别 make工具是一个自动化编译工具 xff0c 它会根据Makefile中的规则进行批处理编译 当需要编译的文件较多时 xff0c 使用make工具会大大提高效率 但是 xff0c 当项目较大时 xff0c 编
  • 接口测试学习必看 - 实现简易接口测试

    前言 终于整理到了接口测试部分的内容 xff0c 接口测试可以说是软件测试入门到初级软件测试的一个必备进阶技巧 很多挂着 灰盒测试 的标识 xff0c 其实就是对接口测试的另外一层理解 何为 灰盒 xff0c 能够看到一部分本质的东西 xf
  • roscpp 底层通讯协议更改

    ROS为机器人开发者们提供了不同语言的编程接口 xff0c 其中C 43 43 接口叫做roscpp xff0c 用来创建topic service param xff0c 实现ROS的通信功能 roscpp is a C 43 43 im