micro_ros_setup
micro_ros_setup copied to clipboard
rcl_executor_spin stuck on freeRTOS
Issue template
- Hardware description: STM
- RTOS: freeRTOS
- Installation type:
- Version or commit hash: iron
I am trying to define a pub/sub node on microros. Using the following code the execution stops at rclc_executor_spin. Is there something wrong with the initialization?
/* timer callback */
void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
(void) last_call_time;
if (timer != NULL) {
RCSOFTCHECK(rcl_publish(&publisher, &pub_msg, NULL));
printf("Publishing: %d\n", pub_msg.data);
pub_msg.data++;
}
}
static void microros_thread_custom( void *pvParameters ){
// set custom transport
rmw_uros_set_custom_transport(
false, // Framing disable here
(void *) NULL, // transport->args
shm_transport_open,
shm_transport_close,
shm_transport_write,
shm_transport_read);
// Get empty allocator to define a custom one
rcl_allocator_t custom_allocator = rcutils_get_zero_initialized_allocator();
rclc_support_t support;
// Set custom allocation methods for freeRTOS
custom_allocator.allocate = microros_allocate;
custom_allocator.deallocate = microros_deallocate;
custom_allocator.reallocate = microros_reallocate;
custom_allocator.zero_allocate = microros_zero_allocate;
// Set default allocator to custom
if (!rcutils_set_default_allocator(&custom_allocator)){
printf("# Setting custom allocator as default: FAILED\r\n");
return;
}
// get the default allocator
rcl_allocator_t allocator = rcl_get_default_allocator();
// create init_options
RCCHECK(rclc_support_init(&support, 0, NULL, &allocator)); // argc:0, argv: NULL
// create node
rcl_node_t node;
RCCHECK(rclc_node_init_default(&node, "int32_publisher_subscriber_rclc", "", &support));
// topics
const char * pub_topic_name = "freeRTOS_publisher";
const char * sub_topic_name = "linux_publisher";
// create publisher
RCCHECK(rclc_publisher_init_default(
&publisher,
&node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32),
pub_topic_name)); // topic name
// create subscriber
RCCHECK(rclc_subscription_init_default(
&subscriber,
&node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32),
sub_topic_name));
// create timer,
rcl_timer_t timer;
const unsigned int timer_timeout = 1000;
RCCHECK(rclc_timer_init_default(
&timer,
&support,
RCL_MS_TO_NS(timer_timeout),
timer_callback));
// create executor
rclc_executor_t executor = rclc_executor_get_zero_initialized_executor();
unsigned int num_handles = 1 + 1; // 1 timer + 1 sub callback
RCCHECK(rclc_executor_init(&executor, &support.context, num_handles, &allocator));
RCCHECK(rclc_executor_add_timer(&executor, &timer));
RCCHECK(rclc_executor_add_subscription(&executor, &subscriber, &sub_msg, &subscription_callback, ON_NEW_DATA)); // sub
pub_msg.data = 0;
RCCHECK(rclc_executor_spin(&executor));
// fini functions
RCCHECK(rcl_subscription_fini(&subscriber, &node));
RCCHECK(rcl_publisher_fini(&publisher, &node));
RCCHECK(rcl_node_fini(&node));
RCCHECK(rcl_timer_fini(&timer));
return;
}
Avoid using rclc_executor_spin
in embedded systems, it can freeze your scheduler.
Use this approach:
while(1){
delay execution for letting other tasks to run
spin some the rclc executor
}
Just a question. If I define a custom transport in the microros thread task like this:
static void microros_thread_custom( void *pvParameters ){
// set custom transport
rmw_uros_set_custom_transport(
false, // Framing disable here
(void *) NULL, // transport->args
shm_transport_open,
shm_transport_close,
shm_transport_write,
shm_transport_read);
// whatever code
}
And then in the transport_read i call a blocking task operation like:
size_t shm_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* err){
// Whatever
vTaskDelay(x10second);
// Whatever
}
Does this operation affect the execution of the main thread? The main thread won't execute until the end of the delay inside the read or will it normally continue its execution?
yes, if you block in the read operation it will block the spin.
And also the main thread that has set the custom transport?
no, the read operation happens inside the spin, so only is blocked the task that runs the spin.