【轻量级开源ROS 的机器人设备(5)】--(1)拟议的框架——µROS节点

news2025/1/19 22:28:04

前文链接:

【轻量级开源ROS 的机器人设备(4)】--(3)通信实现

【轻量级开源ROS 的机器人设备(4)】--(2)通信实现

【轻量级开源ROS 的机器人设备(4)】--(1)通信模块 

一、说明

        根据第 4 章中解释的研究目标,我们设计了并实现了一个通信框架,µROSnode(uros inside the代码,图 5.1 中的标识),它与 ROS 具有原生兼容性,并且是针对嵌入式系统软件。其软件架构和实施细节突出了其模块化方法,以及设计针对简单性和便携性进行了优化。此外,我们开发了一些工具帮助用户将应用软件与框架集成,通过生成(取消)编组过程,并估计堆栈使用情况适用于内存受限的目标平台。一个开发过程终于来了提议,展示了使用我们的框架开发应用程序的理想方式从头开始,或通过整合。

二、实施选择

        下面说明了主要特性和实现选择,以便更好地了解在嵌入式系统领域所做的工作。针对资源受限的设备进行开发,我们必须找到合适的语言可移植性和特性之间以及占用空间之间的折衷大小和代码优雅。

2.1 语言观察

        该框架是用几乎纯 ANSI C89 [1] 编写的,也称为 ISOC90 [26],在 GCC [10] 支持的更正版本中。这确保了跨多个平台的最大可移植性,如广泛说明3.2节的研究策略。框架广泛使用C99标准
整数类型(例如 uint32_t),大部分可以在 C89 中手动定义;
        实际上,任何最近的编译器都支持它们,包括 stdint.h。遵守如果使用 gcc -ansi -pedantic 编译,则符合 C89 标准。
        选择这种语言,尽管它具有可移植性,但使我们接受了一些其他类似语言中没有的强烈限制,特别是它的广泛使用进化 C++。缺乏通用编程特性、命名空间和类,它可以使代码严格类型化并更具可读性,迫使我们做出一些共同的妥协。
        例如,列表中的对象由指向 void 的指针弱寻址,其中C++ 模板会为它们分配正确的类型;键入宏的使用在这种情况下会降低可读性。命名空间缺失问题解决通过在函数名称前加上 uros 前缀,通常后跟模块名称(_lld_+低级驱动模块);主要类型名称以 Uros 为前缀,uros_未成年人。我们试图编写一个干净的代码库,具有用户友好的编码风格,以应对 ANSI C 的局限性。

        如第 3 章所述,并非所有 C++ 特性都适用于所有嵌入式系统,或者是矫枉过正。例如,仅启用 RTTI编译器生成一个更大的目标代码,无法放入微控制器的小代码存储器。此外,某些人根本不支持有用的异常处理编译器、目标架构或操作系统。此外,C++语言对普通的旧 ANSI C 没有同样成熟的支持。

2.2 指纹优化

        在可能的情况下,编写代码以尽量减少内存使用。这可能会使代码有点混乱,但我们尝试尽量减少别名结构的使用(通过联合),只有在堆栈分析工具显示有很大机会减少堆栈使用的情况下。无论如何,此类优化通常供内部使用,而用户 API 是干净的。

        得益于堆栈分析工具,我们减少了函数调用的次数,并最小化函数参数或局部变量。虽然声明更多具有有意义的名称和单一赋值的变量使代码更具可读性,编译器并不总是能够优化堆栈用法。所以,一些函数重用局部变量或参数来减少堆栈使用,没有积极的重用,不会混淆代码。

        具有可预测寿命的对象通常被放置在堆栈上,即使相当大的。这样,堆栈分析工具可以跟踪此类 对象,并且程序员知道后果。此外,堆栈分配速度更快并且自动管理。

         相比之下,堆分配速度较慢(甚至不是恒定时间)并且容易出错;此外,疏忽地分配到堆中可能会使它饱和(因此失败)出乎意料。这就是为什么我们鼓励整个过程中的堆栈分配代码库。

        为了减少堆栈使用,我们避免在任何地方进行激进的函数嵌套可能,同时保持合理程度的因式分解。
        在我们看来,目标代码大小是一个次要问题,因为最新的微控制器有足够的空间,如第 3.2 节所示。尽管如此,正如常识所暗示的那样,特征分解以及一组忽略未使用代码的预处理器开关可以减少目标代码的大小。
        例如,TCPROS 连接头发送和接收功能,相当冗长,在客户端和服务器之间共享;同样地,XML-RPC 客户端调用依赖于通用语法。做了一些优化编译器也可以帮助减少目标代码占用空间,即使是那些哪个目标速度。

三、框架说明

        该框架由反映其领域的软件模块组成专业知识。大多数模块都是平台无关的,而有些模块有
依赖于平台的对应物,以绑定的 lld(低级驱动程序)为前缀到为特定平台提供的低级库。还有
一些应用相关的模块,应该由用户提供,定义回调函数。可选地,一些用户模块包含序列化
ROS 主题和服务的函数和处理程序。主要优化强调了资源受限的平台(嵌入式系统)。

                                 图 5.2 显示了框架软件模块的逻辑视图。

3.1 基础模块

        urosBase 模块提供了整个过程中使用的软件功能框架,例如基本类型和内存管理功能。低级对应物 uros_lld_base 为内存管理提供绑定功能。
1)基本类型

        框架提供的基本类型是那些由C99标准,加上一些常用的类型。此外,一些有用的定义函数类型(签名),如谓词、比较和线程入口点签名。

2)字符串Strings

        字符串类型,UrosString,用于字符串管理,取而代之C 语言使用的以 null 结尾的字符串。它们由 size_t 组成包含字符串长度的字段,后跟指向字符串内容的指针。这种表示优化了字符串管理,例如通过解析和序列化功能,得益于嵌入式长度计数器;这允许在不同的字符串描述符之间共享相同的文本块,这可能只使用它的一部分。

        该模块提供了从 C 字符串(分配的或克隆的)进行转换的函数、检查函数和字符串比较函数。

3)列表

        列表类型 UrosList 是一个单向串联的元素列表 任何类型(用户知道)。列表对象本身包含的计数 条目,以及指向第一个条目的指针。列表节点 UrosListNode 由一个 指向节点数据的指针,以及指向下一个节点的指针。 该库提供了常见列表操作(添加、删除、 节点的存在),以及一些谓词函数类型,用于查找 条目。

        消息类型 消息类型记录 UrosMsgType 包含名称、可选的文本描述,以及主题/服务消息类型的 MD5 和 以及 topic/service message 类的总和,通常在应用程序领域内众所周知。因此,一个全局列表,建立在启动时,保留应用程序中使用的所有消息类型;一套函数在此列表上运行。服务消息类型的处理方式相同,但在单独的全局列表中。

4)主题/服务描述符

        主题和服务共享相同的描述符输入 UrosTopic。它包含主题/服务名称,指向其消息类型的指针,指向处理程序函数的指针、一组标志和一个引用计数器。这消息类型通常包含在全局静态寄存器中(见上文)。
        标志指定一些连接设置,以及主题和主题之间的切换服务。使用引用计数器,以便可以共享描述符引用它的多个处理程序实例(共享指针机制)。

5)堆分配器框
        架管理的大多数操作都需要动态分配;考虑解析传入的 XML-RPC 请求持有 URI 列表。框架使用堆分配器技术。
        一组函数允许动态分配和删除内存任何可能大小的块。该库支持多个堆,对于那些具有脱节内存空间的平台,常见于嵌入式系统架构。

6)内存池

        管理内存块的常用方法同样大小的,比如线程池栈,就是内存池。块作为一个单向列表,其中每个节点都是一个内存块,另外还有一个最开始的保留指针,用于寻址链表中的下一个节点列表。

        内存池由 UrosMemPool 类型定义。它保存块大小(保留指针的综合),指向第一个块的指针 列表,以及剩余的空闲块数,分配器函数和锁 word(用于多线程访问)。

         如果提供了分配器功能,当池已满并且一个新块被提供时 请求,然后分配器函数将创建一个新块。否则, 内存池大小固定,申请线程挂起。

        该库提供了用于创建内存池的函数,既可以通过分配器函数动态创建,也可以从固定大小的内存块(数组)创建,并且 请求或释放块的功能。 上面说明的内存池机制是独立于平台的,但是 如果可用,可以为本机内存池覆盖。

3.2 连接模块

        urosConn 模块提供了 TCP 和 UDP 连接特性框架。低级对应物 uros_lld_conn 连接到用户选择的网络堆栈。
1)连接地址Addresses

        该库提供用于保存 IP 号 (UrosIp) 的数据类型,和 TCP 或 UDP 地址(UrosAddr)。一些辅助函数可以解决地址的主机名或 ROS URI。

2)连接记录

        连接记录,UrosConn,保存着本地和远程地址,协议标识符,以及接收和传输的字节。某些字段可能由所选的低级驱动程序添加。

3)与 BSD 套接字的比较
        连接生命周期和使用等同于广泛使用的POSIX套接字 [11],只有少数有意义的例外,所以读者知道查阅 POSIX 套接字手册。下面解释的差异是仅在发送和接收调用行为中。他们被介绍为了在不同网络堆栈之间实现更高程度的可移植性;例如,没有其他聪明的方法来为 LWIP 堆栈提供绑定,而保持 POSIX 套接字的合理实现。连线还可以支持超时,如果在目标体系结构上可用。

4)传输

        对 urosConnSend()(或相关)的调用发送指定的数据块数据的整体,而 POSIX 套接字可以部分发送(即使不是在全部)。

5)接待调用

        urosConnRecv() (或相关)填充由提供的缓冲区低级驱动程序,而不是像 POSIX 那样由用户提供的缓冲区插座。

3.3 XML-RPC 模块

1)urosRpc 模块

        urosRpc 模块提供了所有需要的 XML-RPC 特性。符合 ROS 的节点,如解析和流功能,以及客户端调用和 Slave API 服务器。

2)参数

        XML-RPC 参数由 UrosRpcParam 描述。它指定值类(参数类型开关)和多态值本身。有关 XML-RPC 参数类型的更多信息,请参阅第 4.3 节。

3)参数列表
        一个参数列表,UrosRpcParamList,是一个双端的,UrosRpcParamNode 条目的单向列表。列表描述符包含条目数和指向头节点和尾节点的指针。一个节点嵌入一个UrosRpcParam 值,以及指向下一个节点的指针。

        这样的结构使得在解析或处理 XML-RPC 流时参数管理更容易。实际上,节点附加在末尾(尾部),并且列表仍然可以从最旧的节点(头)遍历到最新的节点(尾巴);相比之下,UrosList 可以在恒定时间内进行管理和遍历仅以相反的顺序。将值嵌入节点内避免了UrosListNode 不需要的间接寻址和堆碎片。

4)解析器

        作为一种基于 XML 的语言,提供的众多 XML 解析器之一外部库可以用于 XML-RPC 解析。无论如何,大多数(如果不是全部)不是专门为资源受限的平台设计的,因为嵌入式系统是。因此,这个模块提供了一个优化的解析器,它可以通过 HTTP 对传入的 XML-RPC 请求执行一次解析,代码和堆栈占用空间小。

        UrosRpcParser 记录保存了最后的错误代码(便于避免堆栈上的局部变量)、指向连接的指针和用于解析的字段;其中,指向接收到的 HTTP 缓冲区的指针及其长度,以及当前游标状态。此外,缓冲区保存可能的传入字符串实体;实际上,LL(k) 假设 [24] 唯一不成立的情况是当值是没有字符串标记的字符串类型时,因此解决方法是预取可能的最大长度的字符串。

5)Streamer

        该库还能够流式传输 XML-RPC 消息通过 HTTP。 streamer对象类型为UrosRpcStreamer,结构化类似于解析器;这使得在任何需要的地方都可以使用别名,通过重用解析器和流媒体的内存块(互斥),从而优化内存使用。

6)Calls

        一组所有可能的 ROS 客户端对 Master、Slave 和参数服务器 API 可用。它们在代码和内存中的足迹通过利用通用语法和 XML-RPC,使用量保持在最低限度参数。

7)Slave

        框架用于创建一个Slave ROS Node,所以暴露了它的 Slave API 服务器,由 Slave 服务器线程执行。它听任何传入的 XML-RPC 请求消息,并将它们分派到适当的从 API 方法处理程序,处理它们并生成预期的响应消息。

3.4 TCPROS模块

urosTcpRos 模块提供了通过TCPROS 协议。

1)连接状态

        TCPROS 连接状态由描述符 UrosTpcRosStatus 保存,它指定调用者姓名、引用的主题或
服务描述符和标志、退出请求标志和其他选项。

2)函数

        由于 TCPROS 协议非常接近内存中的二进制表示,其函数只是原始数据传输的简写和接待处。相反,(取消)编组例程应该由特定于应用程序的代码,在 urosMsgTypes 模块内(参见第 5.2.8 节)。
        一对函数可以发送和接收 TCPROS 连接头,对于两者发布者和订阅者。

3)宏

        此外,为了简化主题/服务处理函数的主体,提供了一组有用的宏。它们被扩展到(未)编组
语句,以及有意义的错误检查、(未)初始化和(取消)分配声明。这些宏被那些处理程序广泛使用由代码生成器创建(参见第 5.3.1 节)。

4)数组

        为了管理 TCPROS 可变长度数组,记录类型UrosTcpRosArray 可以被(un)编组过程使用。数组类型保存条目的数量,以及指向条目内存块的指针(任何类型,用户知道类型检查)。

3.5 节点模块

        urosNode 模块管理配置、状态和生命周期节点单例。

1)配置

        ​​​​​​​配置记录,UrosNodeConfig,持有节点配置,在启动时加载。它由节点名称、URI以及远程 Master XML-RPC 服务器的 TCP/IP 地址,本地XML-RPC 从属服务器和本地 TCPROS 服务器。

2)Status

状态记录,UrosNodeStatus,保存了节点的运行时状态节点。它包含发布者和订阅者列表,活动的 TCPROS连接列表,用于 XML-RPC 和 TCPROS 的线程(和内存)池处理程序,以及用于对所有这些进行多线程访问的函数。

3)注册函数

一组例程用于管理主题发布/订阅、服务发布/调用和参数订阅。这些例程还对节点状态列表执行检查和操作作为要建立或关闭的 TCPROS 通道的自动管理。

4)节点线程

        节点线程负责节点的生命周期。它填充线程池,将主题/服务/参数注册到主节点,保持检查后者是否始终可达,并在相反的顺序。

3.6 线程模块

        urosThreading 模块根据需要提供多线程环境由框架,如线程、同步原语和线程池。低级驱动程序 uros_lld_threading 绑定到多线程 API目标操作系统。


1)原语Primitives

         框架提供的同步原语是规范的,例如信号量、互斥量和条件变量。它们的用法应该很简单。


2)线程

至于同步原语,线程遵循规范的方法。可以使用来自堆或来自内存池;线程最终可以加入。


3)线程池

        线程库包括线程池机制,其中线程池具有 UrosThreadPool 类型,并且它们使用内存池 (UrosMemPool) 作为他们的堆栈供应商。线程池可以启动(线程创建)和停止(线程加入)优雅。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/93119.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker+Jenkins+Gitee+Harbor+WebHooks实现CI/CD!

🎶 文章简介:DockerJenkinsGiteeHarborWebHooks实现CI/CD! 💡 创作目的:DockerJenkinsGiteeHarborWebHooks实现CI/CD! ☀️ 今日天气:天气有些阴沉 📝 每日一言:如果你执…

【设计模式】策略模式

【设计模式】策略模式 文章目录【设计模式】策略模式一:策略模式简介二:策略模式使用场景三:策略模式总结四:策略模式实战一:策略模式简介 在策略模式(Strategy Pattern)中,一个类的…

[附源码]Node.js计算机毕业设计房地产销售系统Express

项目运行 环境配置: Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境:最好是Nodejs最新版,我…

怎么把图片转换成excel文件?

作为一个办公人员,难免会遇到图片里面有一些内容数据,需要编辑成Excel表格。如果我们按照上面图片表格,创建一个新的文件,这样就非常费时费力,还容易出错。其实小伙伴们如果需要,可以借助软件直接把图片变成…

聚观早报 | 百度 APP 上线疫情指数;辣条第一股卫龙在港上市

今日要闻:百度 APP 上线疫情指数;辣条第一股卫龙在港上市;特斯拉股价大跌引投资者不满;苹果将允许下载第三方商店;京东调集快递小哥驰援北京百度 APP 上线疫情指数 近日,百度 APP 正式上线「疫情指数」&…

CRM客户管理系统源码带手机端+Uniapp小程序源码+调试部署视频

一套Java大型CRM客户关系管理源码带手机端和小程序源码(带调试部署视频) 了解CRM源码更多信息可私信我。 相关技术: 1. 前端:Vue 2. 后端:Spring boot 3. 数据库:MySQL 4.小程序端:UNIAPP …

C++画图之GOC编程 第6课 通天云梯

Goc编程第一课 Goc编程第一课_哔哩哔哩_bilibili Goc编程第一课扩展加复习 Goc编程第一课扩展加复习_哔哩哔哩_bilibili Goc编程第二课 Goc编程第二课_哔哩哔哩_bilibili Goc编程第三课 Goc编程第三课_哔哩哔哩_bilibili Goc编程第四课 Goc编程第四课_哔哩哔哩_bilibili G…

程序员开发10年无法突破架构师?那是因为这个环节没做对

“架构师”对于程序员来讲,一定是大部分程序员所追求以及渴望达到的一个高度。那么,到底需要达到什么要求才能算是架构师呢?下面为大家分享一张Java架构师的岗位职责图,大家可以先看看参考参考。 从图中可以看出,架构师…

机器学习~从入门到精通(一)knn算法数据集处理训练模型

一、机器学习的概念 机器学习的概念: 重点在于学习 ,区别于让机器去执行我们定义好的规则 我们让机器去学习,也就是具备一定的预测能力,需要我们给机器大量的数据,以及给定对于这些数据 机器如何去看待的规则&#x…

小程序框架与生命周期

目录 框架 响应的数据绑定 页面管理 基础组件 丰富的 API 逻辑层 App Service 小程序的生命周期 注册页面 使用 Page 构造器注册页面 在页面中使用 behaviors 使用 Component 构造器构造页面 页面的生命周期 页面路由 页面栈 路由方式 注意事项 模块化 模块化…

P2P之ICE协议(二)

名词解释 Transport Address:包含IP、port和传输协议。 Candidate:除了Transport Address 外还包括类型、优先级、foundation还有Base。 Base:Host candidate 关联一个 Server reflexive candidate 。 ICE的建连过程 ICE实现NAT穿透的所要…

影像组学——一个入门级汇报

影像组学1 相关综述2 发展历程3 研究背景4 影像组学工作流程5 临床应用6 影像组学的问题及挑战7 发展趋势1 相关综述 1. Radiomics the process and the challenges 2. Radiomics Extracting more information from medicalimages 3. Integrating pathomics with radiomics an…

Qt新手入门指南——创建一个基于Qt Widget的文本查找器(二)

Qt是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。 本教程将介绍如何使用…

原生JS之sort排序方法详解

在JavaScript中排序主要用到的api就是sort了,但是使用sort有几个坑需要注意,让我们一起来看看 排序原理-不使用参数时 sort() 方法用于对数组的元素进行排序。排序顺序可以是字母或数字,并按升序或降序。 默认排序顺序为按字典升序。 在不…

CSS 如何实现羽化效果?

最近碰到这样一个问题,在一张封面上直接显示书名,可能会存在书名看不太清楚的情况(容易受到背景干扰),如下 为了解决这个问题,设计师提了一个“究极”方案,将书名背后的图片模糊一下&#xff0c…

【OpenCV-Python】教程:6-1 相机标定

OpenCV Python 相机标定 【目标】 摄像机引起的失真类型如何找到相机的内参和外参如何基于这些特性校正这些图像 【理论】 一些针孔相机会导致图像发生严重失真,主要有两种,一是径向畸变,一是切向畸变。 径向畸变使直线看起来弯曲。距离…

Spring MVC学习 | 报文信息转换

文章目录一、HttpMessageConverter二、获取请求报文信息2.1 使用原生servletAPI2.2 使用RequestBody注解获取请求体信息2.3 使用RequestEntity对象获取请求报文信息三、设置响应报文信息3.1 使用原生的servletAPI3.2 使用ResponseBody注解设置响应体信息3.3 ResponseEntity类的…

Docker 镜像构建可以分享的快乐

通过上一篇 Dockerfile 语法与指令的学习,本节就开始使用Dockerfile 来制作自己的 Docker 镜像啦。 Docker 镜像构建 新建 app.py 文件 from flask import Flaskapp Flask(__name__)app.route(/) def hello():return Hello World! Hogwarts.本代码主要功能是当我…

二十八—— 四十三

二十八、JavaScript——if-else语句 if-else语句- 语法: if(条件表达式) { 语句 }else{ 语句。。。 } - 执行流程 if-else执行时,先对条件表达式进行判断 如果结果为true,则执行if后得而语句 如果结果为false,则执行else后的语句 if-else if-…

公众号名称排名优化

HTML 实例解释 <p> 元素&#xff1a; <p>This is my first paragraph.</p> 这个 <p> 元素定义了 HTML 文档中的一个段落。 这个元素拥有一个开始标签 <p>&#xff0c;以及一个结束标签 </p>。 元素内容是&#xff1a;This is my firs…