当前位置: 首页 > news >正文

micro-ROS中对消息的内存管理

文章目录

  • 1.背景
  • 2.答案
    • 2.1.基本类型及其数组,不需要
    • 2.1.序列类型(复合类型、复合序列类型),需要
  • 3.内存申请方法
    • 3.1.手动申请(Manual allocation)
    • 3.1.工具辅助(micro-ROS utilities)
      • 3.1.1.规则的定义
      • 3.1.2.规则的使用

1.背景

我在之前的一篇文章【在VSCode下利用PlateFormIO开发Arduino的MicroROS遇到的一些问题】中的第10点中,提到一个问题:为啥在使用自定义消息类型时,有时候需要调用 micro_ros_utilities_create_message_memory 函数来对消息对象进行内存申请,而有时候不用呢?

2.答案

其实答案就在这篇官方的指导/说明文章中:【Handling messages memory in micro-ROS】

是否需要对消息类型进行内存申请,取决于消息的成员类型。

2.1.基本类型及其数组,不需要

假如你的消息的成员类型是基本类型(Basic type)及其数组类型(Array type),比如bool、byte、char、float32,bool[n]、byte[n]、char[n]、float32[n]等等,那就不用额外进行内存申请的操作,因为这些基本类型在实例化时就已经明确了空间大小,系统直接帮忙分配好了内存。

bool bool_test
byte byte_test
char char_test
float32 float32_test
float64 double_test
int8 int8_test
uint8 uint8_test
int16 int16_test
uint16 uint16_test
int32 int32_test
uint32 uint32_test
int64 int64_test
uint64 uint64_test

2.1.序列类型(复合类型、复合序列类型),需要

但是,假如消息的成员类型为:序列类型(Sequence type)、包含序列的复合类型(Compound type)、复合序列类型(Sequences of compound types),那就需要手动申请内存空间了。当然,假如复合类型中的成员全是基本类型,那也不用手动申请。
上面提到的这些类型,之所以需要人为去申请内存,原因很简单:系统不知道你要多大的空间。
就拿int32的序列int32[](注意,这个不是数组类型,中括号中间没有具体的数值)来说,在micro-ROS中,该类型经过解析后,得到的是这样一个结构体:

typedef struct rosidl_runtime_c__int32__Sequence
{int32_t* data;    /* The pointer to an array of int32 */size_t size;      /* The number of valid items in data */size_t capacity;  /* The number of allocated items in data */
} rosidl_runtime_c__int32__Sequence;

由于size、capacity都是未知的,那么系统如何知道要申请多大的内存空间并把指针值赋予data呢?
因此需要程序员自己手动申请并赋值一下。(这里解释一下上述结构体中的size、capacity的区别,类比电池的话,size表示剩余电量/可用电量,capacity表示电池总容量。这样设计,估计是为了在实例化一次这个对象后,能够对这个对象反复利用)

3.内存申请方法

在这个【Handling messages memory in micro-ROS】文章中提到,在micro-ROS中处理消息的内存有两种方式:手动申请(Manual allocation)、辅助申请(micro-ROS utilities)。

3.1.手动申请(Manual allocation)

这个就是要求对数据结构的各个成员进行数据填充、内存分配。比如对上面的rosidl_runtime_c__int32__Sequence类型,可以这样子初始化:

rosidl_runtime_c__int32__Sequence values;values.capacity = 100;
values.data = (int32_t*) malloc(mymsg.values.capacity * sizeof(int32_t));
values.size = 0;

这样子操作比较繁琐,更好的是下面的方法。

3.1.工具辅助(micro-ROS utilities)

在micro-ROS中,官方提供了一些函数及结构,可以让我们相对便捷地对消息类型进行内存管理。
这里看一下例子:

mypackage__msg__MyComplexType mymsg;static micro_ros_utilities_memory_conf_t conf = {0};micro_ros_utilities_memory_rule_t rules[] = {{"multiheaders", 4},{"multiheaders.frame_id", 60},{"name", 10}
};
conf.rules = rules;
conf.n_rules = sizeof(rules) / sizeof(rules[0]);// member named "values" of MyComplexType will have the default max_basic_type_sequence_capacitybool success = micro_ros_utilities_create_message_memory(ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),&mymsg,conf
);

其中,mypackage__msg__MyComplexType类型是这样子的:

typedef struct mypackage__msg__MyComplexType
{std_msgs__msg__Header__Sequence multiheaders;rosidl_runtime_c__int32__Sequence values;double duration;int8 coefficients[10];rosidl_runtime_c__String name;  // equal to rosidl_runtime_c__char__Sequence
} mypackage__msg__MyComplexType;

header的类型是这样的:

typedef struct std_msgs__msg__Header
{builtin_interfaces__msg__Time stamp;rosidl_runtime_c__String frame_id;
} std_msgs__msg__Header;

3.1.1.规则的定义

可以看到,针对mypackage__msg__MyComplexType的成员multiheaders,指定下面的内存申请规则:

...
micro_ros_utilities_memory_rule_t rules[] = {{"multiheaders", 4}, // 对序列进行长度(capacity)的申请{"multiheaders.frame_id", 60}, // frame_id是字符串,进行60字节的申请...
};
...

rule的具体的写法应该是

 {"对象成员名称",  Sequence的capacity大小}

在这里插入图片描述

需要注意的是,序列成员的成员可以直接写,而不用序列号,比如上面的"multiheaders.frame_id"就不用写成"multiheaders.data[0].frame_id"之类的。

另外,对于未在rules中指定的序列类型成员,会按照micro_ros_utilities_memory_conf_t的max_string_capacity、max_ros2_type_sequence_capacity、max_basic_type_sequence_capacity来进行申请,假如需要覆盖默认值micro_ros_utilities_memory_conf_default,可以这样操作:

static micro_ros_utilities_memory_conf_t conf = {0};conf.max_string_capacity = 50;
conf.max_ros2_type_sequence_capacity = 5;
conf.max_basic_type_sequence_capacity = 5;

3.1.2.规则的使用

定义好规则之后,当调用 micro_ros_utilities_create_message_memory 函数时,应该是对Sequence类型的capacity进行赋值,然后再根据此capacity进行实际内存的计算+申请。(可能会涉及递归过程?)
大概看一下源码,应该是的。具体实现过程有空再分析分析。
在这里插入图片描述


参考:
【Handling messages memory in micro-ROS】

相关文章:

micro-ROS中对消息的内存管理

文章目录 1.背景2.答案2.1.基本类型及其数组,不需要2.1.序列类型(复合类型、复合序列类型),需要 3.内存申请方法3.1.手动申请(Manual allocation)3.1.工具辅助(micro-ROS utilities)…...

Springboot中使用拦截器、过滤器、监听器

一、Servlet、Filter(过滤器)、 Listener(监听器)、Interceptor(拦截器) Javaweb三大组件:servlet、Filter(过滤器)、 Listener(监听器) Spring…...

代码随想录二刷day45

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、力扣70. 爬楼梯二、力扣322. 零钱兑换三、力扣279. 完全平方数 前言 一、力扣70. 爬楼梯 class Solution {public int climbStairs(int n) {int[] dp new…...

泊车功能专题介绍 ———— AVP系统基础数据交互内容

文章目录 系统架构系统功能描述云端子系统车辆子系统场端子系统用户APP 工作流程基础数据交互内容AVP 系统基础数据交互服务车/用户 - 云基础数据交互内容车位查询工作流程技术要求数据交互要求 车位预约工作流程技术要求数据交互要求 取消预约工作流程技术要求数据交互要求 泊…...

蓝桥杯每日一题2023.10.6

题目描述 门牌制作 - 蓝桥云课 (lanqiao.cn) 题目分析 #include<bits/stdc.h> using namespace std; int ans; int main() {for(int i 1; i < 2020; i ){int x i;while(x){int a x % 10;if(a 2)ans ;x / 10;}}cout << ans;return 0; } 题目描述 既约分数…...

7、【Qlib】【主要组件】Data Layer:数据框架与使用

7、【主要组件】Data Layer&#xff1a;数据框架与使用 简介数据准备Qlib 格式数据Qlib 格式数据集自动更新日频率数据将 CSV 格式转换为 Qlib 格式股票池&#xff08;市场&#xff09;多股票模式 数据API数据检索特征过滤器 数据加载器QlibDataLoaderStaticDataLoaderInterfac…...

Kubernetes安装部署 1

本文主要描述kubernetes的安装部署&#xff0c;kubernetes的安装部署主要包括三个关键组件&#xff0c;其中&#xff0c;包括kubeadm、kubelet、kubectl&#xff0c;这三个组件的功能描述如下所示&#xff1a; Kubeadm 用于启动与管理kubernetes集群 Kubelet 运行在所有集群的…...

在VS Code中优雅地编辑csv文件

文章目录 Rainbow csv转表格CSV to Tablecsv2tableCSV to Markdown Table Edit csv 下面这些插件对csv/tsv/psv都有着不错的支持&#xff0c;这几种格式的主要区别是分隔符不同。 功能入口/使用方法Rainbow csv按列赋色右键菜单CSV to Table转为ASCII表格指令CSV to Markdown …...

LCR 128.库存管理 I

​题目来源&#xff1a; leetcode题目&#xff0c;网址&#xff1a;LCR 128. 库存管理 I - 力扣&#xff08;LeetCode&#xff09; 解题思路&#xff1a; 数组可以分割成两段的升序连续子数组&#xff0c;找到两个子数组的开始元素并返回较小者即可。 解题代码&#xff1a; …...

eigen::Affine3d 转换

平移eigen::vector3d和四元数Eigen::Quaterniond 转 eigen::Affine3d Eigen::Vector3d t Eigen::Vector3d::Zero(); Eigen::Quaterniond q Eigen::Quaterniond ::Identity();Eigen::Affine3d affine3d t * q.toRotationMatrix(); Eigen::Matrix4d 转 eigen::Affine3d Eige…...

【Python从入门到进阶】38、selenium关于Chrome handless的基本使用

接上篇《37、selenium关于phantomjs的基本使用》 上一篇我们介绍了有关phantomjs的相关知识&#xff0c;但由于selenium已经放弃PhantomJS&#xff0c;本篇我们来学习Chrome的无头版浏览器Chrome Handless的使用。 一、Chrome Headless简介 Chrome Headless是一个无界面的浏览…...

给Python项目创建一个虚拟环境(enev)

给Python项目创建一个虚拟环境&#xff08;enev&#xff09; 为您的Python项目创建一个虚拟环境是一种良好的实践&#xff0c;可以隔离项目的依赖项&#xff0c;以确保它们不会干扰全局Python环境或其他项目。您可以使用venv模块来创建虚拟环境。以下是在Linux上创建虚拟环境的…...

【RK3588】YOLO V5在瑞芯微板子上部署问题记录汇总

YOLO V5训练模型部署到瑞芯微的板子上面&#xff0c;官方是有给出案例和转过详情的。并且也提供了Python版本的推理代码&#xff0c;以及C语言的代码。 但是&#xff0c;对于转换过程中的细节&#xff0c;哪些需要改&#xff1f;怎么改&#xff1f;如何改&#xff0c;和为什么…...

别人做的百度百科词条信息不全,如何更正自己的百度百科词条

很多人自己的百度百科词条是别人上传上去的&#xff0c;自己压根不知道&#xff0c;而且里面的信息内容要么不全&#xff0c;要么是有错漏的&#xff0c;但自己想要更正自己的百度百科词条又不知道如何更正&#xff0c;下面洛希爱做百科网和大家介绍一些百科经验知识。 首先百…...

[论文精读]U-Net: Convolutional Networks for BiomedicalImage Segmentation

论文原文&#xff1a;U-Net: Convolutional Networks for Biomedical Image Segmentation (arxiv.org) 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔…...

Godot Identifier “File“ not declared in the current scope.

解决方案&#xff1a; f FileAccess.open(savedir, FileAccess.READ)...

Java ORM Bee,多表关联更新

Bee V2.1.8 增加支持多表的update, insert, delete; 使用FK注解进行关联. 如果子实体没有用上FK声明的字段(即FK的字段没有值),则不执行,防止更新到多余记录 外键有一个没有设置时&#xff0c;跳过。 更多实例,请查看样例工程:https://gitee.com/automvc/bee-exam 或:h…...

Java 读取excel文件

导入&#xff1a; 先导入依赖&#xff1a; <!-- 文件上传 --> <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>4.5.7</version> </dependency> <!-- JSON -…...

PageRank(上):数据分析 | 数据挖掘 | 十大算法之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…...

吃鸡达人专享!提高战斗力,分享干货,查询装备皮肤,保护账号安全!

大家好&#xff01;作为专业吃鸡行家&#xff0c;我将为您带来一些热门话题和实用内容&#xff0c;帮助您提升游戏战斗力&#xff0c;分享顶级游戏作战干货&#xff0c;并提供便捷的作图工具和查询服务。让我们一起享受吃鸡的乐趣&#xff01; 首先&#xff0c;我要推荐一款绝地…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...