Skip to content

Commit cfd073b

Browse files
committed
Update galactic memory handling tutorial
1 parent ca2f2b3 commit cfd073b

1 file changed

Lines changed: 126 additions & 3 deletions

File tree

  • _docs/tutorials/advanced/handling_type_memory

_docs/tutorials/advanced/handling_type_memory/index.md

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ This page aims to explain how to handle messages and types memory in micro-ROS.
77

88
First of all, since the micro-ROS user is in an embedded C99 environment, it is important to be aware of what messages and ROS 2 types are being used in order to handle memory correctly.
99

10+
The micro-ROS type memory handling has changed in the latest micro-ROS Galactic distribution, two approaches are presented in this tutorial: micro-ROS Foxy and micro-ROS Galactic and beyond.
11+
12+
# micro-ROS Foxy
13+
1014
By watching the `.msg` or `.srv` of the types used in a micro-ROS application, you can determine the type of each member. Currently, the following types are supported:
1115
- Basic type
1216
- Array type
@@ -58,7 +62,7 @@ In the case of `MyType.msg`, the `values` sequence member is represented in C99
5862

5963
```c
6064
typedef struct rosidl_runtime_c__int32__Sequence
61-
{
65+
{
6266
int32_t* data; /* The pointer to an array of int32 */
6367
size_t size; /* The number of valid items in data */
6468
size_t capacity; /* The number of allocated items in data */
@@ -94,7 +98,7 @@ for(int32_t i = 0; i < 3; i++){
9498

9599
## Compound types in micro-ROS
96100

97-
When dealing with a compound type, the user should recursively inspect the types in order to determine how to handle each internal member.
101+
When dealing with a compound type, the user should recursively inspect the types in order to determine how to handle each internal member.
98102

99103
For example in the `MyType.msg` example, the `header` member has the following structure:
100104

@@ -148,7 +152,7 @@ int8[10] coefficients
148152
string name
149153
```
150154
151-
In this case, the generated typesupport will be:
155+
In this case, the generated typesupport will be:
152156
153157
```c
154158
typedef struct mypackage__msg__MyComplexType
@@ -191,3 +195,122 @@ for(int32_t i = 0; i < 3; i++){
191195
mymsg.multiheaders.size++;
192196
}
193197
```
198+
199+
# micro-ROS Galactic
200+
201+
Due to the inclusion of [`rosidl_typesupport_introspection_c`](https://github.com/ros2/rosidl/tree/master/rosidl_typesupport_introspection_c) in micro-ROS Galactic distribution, an automated memory handling for micro-ROS types is available. The tools related to this feature are available in the package [`micro_ros_utilities`](https://github.com/micro-ROS/micro_ros_utilities).
202+
203+
The documentation of the package [`micro_ros_utilities`](https://github.com/micro-ROS/micro_ros_utilities) are available [here](https://micro.ros.org/docs/api/utils/).
204+
205+
This package is able to auto-assign memory to a certain message struct using default dynamic memory allocators, for example, using the previouly declated type:
206+
207+
```c
208+
mypackage__msg__MyType mymsg;
209+
210+
static micro_ros_utilities_memory_conf_t conf = {0};
211+
212+
bool success = micro_ros_utilities_create_message_memory(
213+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyType),
214+
&mymsg,
215+
conf
216+
);
217+
```
218+
219+
This code will init all the string and sequences recursively in `MyType` type. The size of this memory slots will be by default the ones in [`micro_ros_utilities_memory_conf_default`](https://github.com/micro-ROS/micro_ros_utilities/blob/c829971bd33ac1f14a94aa722476110b4b59eaf9/include/micro_ros_utilities/type_utilities.h#L51), that is:
220+
- String will have 20 characters
221+
- ROS 2 types sequences will have a length of 5
222+
- Basic types sequences will have a length of 5
223+
224+
This defaults can be overriden using:
225+
226+
```c
227+
mypackage__msg__MyType mymsg;
228+
229+
static micro_ros_utilities_memory_conf_t conf = {0};
230+
231+
conf.max_string_capacity = 50;
232+
conf.max_ros2_type_sequence_capacity = 5;
233+
conf.max_basic_type_sequence_capacity = 5;
234+
235+
bool success = micro_ros_utilities_create_message_memory(
236+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyType),
237+
&mymsg,
238+
conf
239+
);
240+
```
241+
242+
A complex rules approach can be used as in the following example:
243+
244+
```c
245+
mypackage__msg__MyComplexType mymsg;
246+
247+
static micro_ros_utilities_memory_conf_t conf = {0};
248+
249+
micro_ros_utilities_memory_rule_t rules[] = {
250+
{"multiheaders", 4},
251+
{"multiheaders.frame_id", 60},
252+
{"name", 10}
253+
};
254+
conf.rules = rules;
255+
conf.n_rules = sizeof(rules) / sizeof(rules[0]);
256+
257+
// member values of MyComplexType will have the default max_basic_type_sequence_capacity
258+
259+
bool success = micro_ros_utilities_create_message_memory(
260+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
261+
&mymsg,
262+
conf
263+
);
264+
```
265+
266+
Is also possible to use a user-provided buffer to allocate memory:
267+
268+
```c
269+
mypackage__msg__MyComplexType mymsg;
270+
271+
static micro_ros_utilities_memory_conf_t conf = {0};
272+
273+
static uint8_t my_buffer[1000];
274+
275+
bool success = micro_ros_utilities_create_static_message_memory(
276+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
277+
&mymsg,
278+
conf,
279+
my_buffer,
280+
sizeof(my_buffer)
281+
);
282+
```
283+
284+
The library provides utilies for calculating the size that both approaches will use with a certain configuration. Notice that this amount of memory is only the dynamic usage or the usage in the user provided buffer, `sizeof(mypackage__msg__MyComplexType)` is not taken into account.
285+
286+
```c
287+
mypackage__msg__MyComplexType mymsg;
288+
289+
static micro_ros_utilities_memory_conf_t conf = {0};
290+
291+
size_t dynamic_size = micro_ros_utilities_get_dynamic_size(
292+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
293+
conf
294+
);
295+
296+
size_t static_size = micro_ros_utilities_get_static_size(
297+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
298+
conf
299+
);
300+
```
301+
302+
Finally, a destruction function is also provided for messages allocated in dynamic memory:
303+
304+
305+
```c
306+
mypackage__msg__MyComplexType mymsg;
307+
308+
// Memory allocation using micro_ros_utilities_create_message_memory
309+
// ...
310+
311+
bool success = micro_ros_utilities_destroy_message_memory(
312+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
313+
&mymsg,
314+
conf
315+
);
316+
```

0 commit comments

Comments
 (0)