micro_ros_setup: Can't initialize node to subscribe String topic
Issue template
- Hardware description: https://github.com/Needrom/Microros-on-DIscovery-board
- RTOS: freertos
- Installation type: micro_ros_setup
- Version or commit hash: foxy
Steps to reproduce the issue
I add string subscriber to ping_pong
app, and when initialize it, I get some error from the printf.
Expected behavior
I should finish initialization and subscribe the topic.
Actual behavior
[ERROR] [ld.ld] [rclc]: [rclc_subscription_init_best_effort] Error in rcl_subscription_init: error not set
Additional information
Code in app.c
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <std_msgs/msg/header.h>
#include <std_msgs/msg/string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#endif
#define STRING_BUFFER_LEN 50
#define RCCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){printf("Failed status on line %d: %d. Aborting.\n",__LINE__,(int)temp_rc); vTaskDelete(NULL);}}
#define RCSOFTCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){printf("Failed status on line %d: %d. Continuing.\n",__LINE__,(int)temp_rc);}}
rcl_publisher_t ping_publisher;
rcl_publisher_t pong_publisher;
rcl_subscription_t ping_subscriber;
rcl_subscription_t pong_subscriber;
rcl_subscription_t string_subscriber;
std_msgs__msg__Header incoming_ping;
std_msgs__msg__Header outcoming_ping;
std_msgs__msg__Header incoming_pong;
std_msgs__msg__String test_data_String;
int device_id;
int seq_no;
int pong_count;
void ping_timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
RCLC_UNUSED(last_call_time);
if (timer != NULL) {
// printf("%s : 1 \r\n", __func__);
seq_no = rand();
sprintf(outcoming_ping.frame_id.data, "%d_%d", seq_no, device_id);
outcoming_ping.frame_id.size = strlen(outcoming_ping.frame_id.data);
// Fill the message timestamp
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
outcoming_ping.stamp.sec = ts.tv_sec;
outcoming_ping.stamp.nanosec = ts.tv_nsec;
// printf("%s : 2 \r\n", __func__);
// Reset the pong count and publish the ping message
pong_count = 0;
rcl_publish(&ping_publisher, (const void*)&outcoming_ping, NULL);
// printf("Ping send seq %s\n", outcoming_ping.frame_id.data);
}
}
void ping_subscription_callback(const void * msgin)
{
const std_msgs__msg__Header * msg = (const std_msgs__msg__Header *)msgin;
// Dont pong my own pings
if(strcmp(outcoming_ping.frame_id.data, msg->frame_id.data) != 0){
printf("Ping received with seq %s. Answering.\n", msg->frame_id.data);
rcl_publish(&pong_publisher, (const void*)msg, NULL);
}
}
void pong_subscription_callback(const void * msgin)
{
const std_msgs__msg__Header * msg = (const std_msgs__msg__Header *)msgin;
if(strcmp(outcoming_ping.frame_id.data, msg->frame_id.data) == 0) {
pong_count++;
printf("Pong for seq %s (%d)\n", msg->frame_id.data, pong_count);
}
}
void string_subscription_callback(const void * msgin){
const std_msgs__msg__String * msg = (const std_msgs__msg__Header *)msgin;
if(msg == NULL){
printf("Callback : msg NULL \r\n");
} else {
printf("Callback : I Heard : %s \r\n", msg->data.data);
}
}
void appMain(void *argument)
{
int test_printf_count = 0;
rcl_allocator_t allocator = rcl_get_default_allocator();
rclc_support_t support;
// create init_options
RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));
rcl_node_t node;
RCCHECK(rclc_node_init_default(&node, "pingpong_node", "", &support));
RCCHECK(rclc_publisher_init_default(&ping_publisher, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Header), "/microROS/ping"));
// Create a best effort pong publisher
RCCHECK(rclc_publisher_init_best_effort(&pong_publisher, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Header), "/microROS/pong"));
RCCHECK(rclc_subscription_init_best_effort(&ping_subscriber, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Header), "/microROS/ping"));
// Create a best effort pong subscriber
RCCHECK(rclc_subscription_init_best_effort(&pong_subscriber, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Header), "/microROS/pong"));
// Create a best effort String subscriber
RCCHECK(rclc_subscription_init_best_effort(&string_subscriber, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, String), "/microROS/String"));
// Create a 3 seconds ping timer timer,
rcl_timer_t timer;
RCCHECK(rclc_timer_init_default(&timer, &support, RCL_MS_TO_NS(1000), ping_timer_callback));
// Create executor
rclc_executor_t executor;
RCCHECK(rclc_executor_init(&executor, &support.context, 3, &allocator));
RCCHECK(rclc_executor_add_timer(&executor, &timer));
RCCHECK(rclc_executor_add_subscription(&executor, &ping_subscriber, &incoming_ping,
&ping_subscription_callback, ON_NEW_DATA));
RCCHECK(rclc_executor_add_subscription(&executor, &pong_subscriber, &incoming_pong,
&pong_subscription_callback, ON_NEW_DATA));
RCCHECK(rclc_executor_add_subscription(&executor, &string_subscriber, &test_data_String,
&string_subscription_callback, ON_NEW_DATA));
// Create and allocate the pingpong messages
char outcoming_ping_buffer[STRING_BUFFER_LEN];
outcoming_ping.frame_id.data = outcoming_ping_buffer;
outcoming_ping.frame_id.capacity = STRING_BUFFER_LEN;
char incoming_ping_buffer[STRING_BUFFER_LEN];
incoming_ping.frame_id.data = incoming_ping_buffer;
incoming_ping.frame_id.capacity = STRING_BUFFER_LEN;
char incoming_pong_buffer[STRING_BUFFER_LEN];
incoming_pong.frame_id.data = incoming_pong_buffer;
incoming_pong.frame_id.capacity = STRING_BUFFER_LEN;
device_id = rand();
rcl_ret_t ret = 0;
while(1){
ret = rclc_executor_spin_some(&executor, RCL_MS_TO_NS(10));
// printf("ret: %d \r\n", ret);
usleep(10000);
}
// Free resources
RCCHECK(rcl_publisher_fini(&ping_publisher, &node));
RCCHECK(rcl_publisher_fini(&pong_publisher, &node));
RCCHECK(rcl_subscription_fini(&ping_subscriber, &node));
RCCHECK(rcl_subscription_fini(&pong_subscriber, &node));
RCCHECK(rcl_node_fini(&node));
}
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 22 (10 by maintainers)
You are creating the executor with 3 slots for execution entities:
and then you are adding 4 entities, the last one will raise an error. Please check the API documentation here.