Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rcl_executor_spin stuck on freeRTOS #667

Open
N-K1998 opened this issue Sep 28, 2023 · 5 comments
Open

rcl_executor_spin stuck on freeRTOS #667

N-K1998 opened this issue Sep 28, 2023 · 5 comments

Comments

@N-K1998
Copy link

N-K1998 commented Sep 28, 2023

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;
}
@pablogs9
Copy link
Member

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
}

@N-K1998
Copy link
Author

N-K1998 commented Sep 29, 2023

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?

@pablogs9
Copy link
Member

yes, if you block in the read operation it will block the spin.

@N-K1998
Copy link
Author

N-K1998 commented Sep 29, 2023

And also the main thread that has set the custom transport?

@pablogs9
Copy link
Member

no, the read operation happens inside the spin, so only is blocked the task that runs the spin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants