网站后台关键词设置,apache搭建多个网站,山东建设主管部门网站,网站登录不上去怎么回事文章目录 1.背景2.答案2.1.基本类型及其数组#xff0c;不需要2.1.序列类型#xff08;复合类型、复合序列类型#xff09;#xff0c;需要 3.内存申请方法3.1.手动申请#xff08;Manual allocation#xff09;3.1.工具辅助#xff08;micro-ROS utilities#xff09;… 文章目录 1.背景2.答案2.1.基本类型及其数组不需要2.1.序列类型复合类型、复合序列类型需要 3.内存申请方法3.1.手动申请Manual allocation3.1.工具辅助micro-ROS utilities3.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、float32bool[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_test2.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】