Skip to content

Commit 7dbc0c4

Browse files
pablogs9Acuadros95
andauthored
Add Galactic type handling (#329)
* Update galactic memory handling tutorial * Update * Apply suggestions from code review Co-authored-by: Antonio Cuadros <49162117+Acuadros95@users.noreply.github.com> * Update _docs/tutorials/advanced/handling_type_memory/index.md Co-authored-by: Pablo Garrido <pablogs9@gmail.com> Co-authored-by: Antonio Cuadros <49162117+Acuadros95@users.noreply.github.com>
1 parent ca2f2b3 commit 7dbc0c4

1 file changed

Lines changed: 131 additions & 3 deletions

File tree

  • _docs/tutorials/advanced/handling_type_memory

_docs/tutorials/advanced/handling_type_memory/index.md

Lines changed: 131 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ 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](#micro-ros-foxy)
13+
- [Sequence types in micro-ROS](#sequence-types-in-micro-ros)
14+
- [Compound types in micro-ROS](#compound-types-in-micro-ros)
15+
- [Sequences of compound types](#sequences-of-compound-types)
16+
- [micro-ROS Galactic](#micro-ros-galactic)
17+
18+
# micro-ROS Foxy
19+
1020
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:
1121
- Basic type
1222
- Array type
@@ -58,7 +68,7 @@ In the case of `MyType.msg`, the `values` sequence member is represented in C99
5868

5969
```c
6070
typedef struct rosidl_runtime_c__int32__Sequence
61-
{
71+
{
6272
int32_t* data; /* The pointer to an array of int32 */
6373
size_t size; /* The number of valid items in data */
6474
size_t capacity; /* The number of allocated items in data */
@@ -94,7 +104,7 @@ for(int32_t i = 0; i < 3; i++){
94104

95105
## Compound types in micro-ROS
96106

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

99109
For example in the `MyType.msg` example, the `header` member has the following structure:
100110

@@ -148,7 +158,7 @@ int8[10] coefficients
148158
string name
149159
```
150160
151-
In this case, the generated typesupport will be:
161+
In this case, the generated typesupport will be:
152162
153163
```c
154164
typedef struct mypackage__msg__MyComplexType
@@ -191,3 +201,121 @@ for(int32_t i = 0; i < 3; i++){
191201
mymsg.multiheaders.size++;
192202
}
193203
```
204+
205+
# micro-ROS Galactic
206+
207+
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).
208+
209+
The documentation of the package [`micro_ros_utilities`](https://github.com/micro-ROS/micro_ros_utilities) is available [here](https://micro.ros.org/docs/api/utils/).
210+
211+
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:
212+
213+
```c
214+
mypackage__msg__MyType mymsg;
215+
216+
static micro_ros_utilities_memory_conf_t conf = {0};
217+
218+
bool success = micro_ros_utilities_create_message_memory(
219+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyType),
220+
&mymsg,
221+
conf
222+
);
223+
```
224+
225+
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:
226+
- String will have 20 characters
227+
- ROS 2 types sequences will have a length of 5
228+
- Basic types sequences will have a length of 5
229+
230+
This defaults can be overriden using:
231+
232+
```c
233+
mypackage__msg__MyType mymsg;
234+
235+
static micro_ros_utilities_memory_conf_t conf = {0};
236+
237+
conf.max_string_capacity = 50;
238+
conf.max_ros2_type_sequence_capacity = 5;
239+
conf.max_basic_type_sequence_capacity = 5;
240+
241+
bool success = micro_ros_utilities_create_message_memory(
242+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyType),
243+
&mymsg,
244+
conf
245+
);
246+
```
247+
248+
To customize the length of each member of the struct, a complex rules approach can be used as in the following example:
249+
250+
```c
251+
mypackage__msg__MyComplexType mymsg;
252+
253+
static micro_ros_utilities_memory_conf_t conf = {0};
254+
255+
micro_ros_utilities_memory_rule_t rules[] = {
256+
{"multiheaders", 4},
257+
{"multiheaders.frame_id", 60},
258+
{"name", 10}
259+
};
260+
conf.rules = rules;
261+
conf.n_rules = sizeof(rules) / sizeof(rules[0]);
262+
263+
// member named "values" of MyComplexType will have the default max_basic_type_sequence_capacity
264+
265+
bool success = micro_ros_utilities_create_message_memory(
266+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
267+
&mymsg,
268+
conf
269+
);
270+
```
271+
272+
Is also possible to use a user-provided buffer to allocate memory:
273+
274+
```c
275+
mypackage__msg__MyComplexType mymsg;
276+
277+
static micro_ros_utilities_memory_conf_t conf = {0};
278+
279+
static uint8_t my_buffer[1000];
280+
281+
bool success = micro_ros_utilities_create_static_message_memory(
282+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
283+
&mymsg,
284+
conf,
285+
my_buffer,
286+
sizeof(my_buffer)
287+
);
288+
```
289+
290+
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.
291+
292+
```c
293+
mypackage__msg__MyComplexType mymsg;
294+
295+
static micro_ros_utilities_memory_conf_t conf = {0};
296+
297+
size_t dynamic_size = micro_ros_utilities_get_dynamic_size(
298+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
299+
conf
300+
);
301+
302+
size_t static_size = micro_ros_utilities_get_static_size(
303+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
304+
conf
305+
);
306+
```
307+
308+
Finally, a destruction function is also provided for messages allocated in dynamic memory:
309+
310+
311+
```c
312+
mypackage__msg__MyComplexType mymsg;
313+
314+
// Release memory previously allocated with micro_ros_utilities_create_message_memory
315+
316+
bool success = micro_ros_utilities_destroy_message_memory(
317+
ROSIDL_GET_MSG_TYPE_SUPPORT(mypackage, msg, MyComplexType),
318+
&mymsg,
319+
conf
320+
);
321+
```

0 commit comments

Comments
 (0)