micro-ROS / micro_ros_arduino

micro-ROS library for Arduino
Apache License 2.0
435 stars 112 forks source link

In debugging micro-ROS, the characters output using serial print tend to get cut off or appear garbled. #1381

Closed sugithub7 closed 1 year ago

sugithub7 commented 1 year ago

Hardware description: ESP32 RTOS: Yes Installation type: Arduino IDE Version or commit hash: Humble Framework: Arduino

I am working on creating a program that can communicate with ROS2 Humble using micro-ROS. I am using an ESP32 device and connecting it to a computer via USB.

I am trying to display information using serial print for debugging the program, but the characters are getting cut off, garbled, and the debugging messages are not being utilized effectively. I suspect that the characters are not being displayed correctly because they are overlapping with the communication information between the micro-ROS and the PC.

I will attach sample programs and images of the serial monitor, so could you please advise me on how to efficiently debug this issue?

Steps to reproduce the issue Please flash this program onto the ESP32 and run it.

#include <micro_ros_arduino.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <std_msgs/msg/string.h>
#include <std_msgs/msg/int32.h>

rcl_node_t      node;
rcl_allocator_t allocator;
rclc_support_t  support;
rclc_executor_t executor;
rcl_subscription_t sub_task1Rcv, sub_task3Rcv;
rcl_publisher_t    pub_task1Snd, pub_task2Snd;
std_msgs__msg__String task1_recv_msg, task1_send_msg;
std_msgs__msg__String task2_msg;
std_msgs__msg__Int32  task3_recv_msg;

const size_t MAX_STRING_SIZE = 120;

// task
void task1(void *pvParameters);
void task2(void *pvParameters);
void task3(void *pvParameters);

// Function
void task1_callback(const void *msgin) {
  const std_msgs__msg__String *msg = (const std_msgs__msg__String *)msgin;
  Serial.print("task1 received: ");
  Serial.println(msg->data.data);
  snprintf(task1_send_msg.data.data, 30, "rcv:%s", msg->data.data);
  task1_send_msg.data.size = strlen(task1_send_msg.data.data);
  rcl_publish(&pub_task1Snd, &task1_send_msg, NULL);
  Serial.print("task1 published: ");
  Serial.println(task1_send_msg.data.data);
}

void task3_callback(const void *msgin) {
  const std_msgs__msg__Int32 *msg = (const std_msgs__msg__Int32 *)msgin;
  Serial.print("task3 received: ");
  Serial.println(msg->data);
}

// Setup
void setup() {
  set_microros_transports();
  Serial.begin(115200);
  WiFi.mode(WIFI_OFF);

  delay(2000);

  allocator = rcl_get_default_allocator();

  // Initialize node
  rcl_init_options_t init_options = rcl_get_zero_initialized_init_options();
  rcl_init_options_init(&init_options, allocator);
  rcl_init_options_set_domain_id(&init_options, 77);
  rclc_support_init_with_options(&support, 0, NULL, &init_options, &allocator);
  rclc_node_init_default(&node, "esp32_node", "", &support);

  // Initialize publishers and subscriptions
  rclc_publisher_init_default(&pub_task1Snd, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, String), "task1Snd");
  rclc_publisher_init_default(&pub_task2Snd, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, String), "task2Snd");
  rclc_subscription_init_default(&sub_task1Rcv, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, String), "task1Rcv");
  rclc_subscription_init_default(&sub_task3Rcv, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), "task3Rcv");

  // Initialize messages
  std_msgs__msg__String__init(&task1_recv_msg);
  std_msgs__msg__String__init(&task1_send_msg);
  std_msgs__msg__String__init(&task2_msg);
  std_msgs__msg__Int32__init(&task3_recv_msg);

  task1_recv_msg.data.data = (char *)allocator.allocate(MAX_STRING_SIZE, allocator.state);
  task1_recv_msg.data.capacity = MAX_STRING_SIZE;
  task3_recv_msg.data = 0;

  // Initialize executor
  rclc_executor_init(&executor, &support.context, 2, &allocator);
  rclc_executor_add_subscription(&executor, &sub_task1Rcv, &task1_recv_msg, &task1_callback, ON_NEW_DATA);
  rclc_executor_add_subscription(&executor, &sub_task3Rcv, &task3_recv_msg, &task3_callback, ON_NEW_DATA);

  // TaskCreate
  xTaskCreatePinnedToCore(
      task1,
      "task1",
      2048,
      NULL,
      1,
      NULL,
      0);

  xTaskCreatePinnedToCore(
      task2,
      "task2",
      2048,
      NULL,
      2,
      NULL,
      1);

  xTaskCreatePinnedToCore(
      task3,
      "task3",
      2048,
      NULL,
      1,
      NULL,
      1);
}

// Loop
void loop() {
  //ヾ(o・ω・)ノ Please tell me!
}

void task1(void *pvParameters) {
  while (1) {
    rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100));
    delay(10);
  }
}

void task2(void *pvParameters) {
  while (1) {
    strcpy(task2_msg.data.data, "Hello World");
    task2_msg.data.size = strlen(task2_msg.data.data);
    rcl_publish(&pub_task2Snd, &task2_msg, NULL);
    Serial.print("task2 published: ");
    Serial.println(task2_msg.data.data);
    delay(100);
  }
}

void task3(void *pvParameters) {
  while (1) {
    rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100));
    delay(10);
  }
}

Actual behavior

Screenshot from 2023-04-27 13-41-34

Additional information I cannot share the details of the program I recently created here, but compared to this sample, the processing is more complex and the number of characters output is much larger, making the issue more serious.

Thank you for your assistance.

Acuadros95 commented 1 year ago

I suspect that the characters are not being displayed correctly because they are overlapping with the communication information between the micro-ROS and the PC.

Exactly, you need to use a different serial port to send debug messages.

Also, are you building with multithread support enabled?

sugithub7 commented 1 year ago

Dear Acuadros95, thank you very much for your advice regarding serial print.

I usually work on developing PC software, and this is my first time implementing a program on an ESP32. I am using Arduino IDE 1.8.19, but I couldn't find any information on how to configure the multi-threading support. I apologize for the inconvenience, but could you please guide me on how to set it up properly?

I apologize if this deviates from the main topic of my question, but I am also trying to subscribe to UInt8MultiArray messages in another program. When I published the message from my PC, the micro-ROS callback did not function. However, when I changed the message type to String and tested the subscription, it worked. I thought there might be a mistake in the way I allocated memory for the UInt8MultiArray messages, so I tried various methods while researching, but I have not been successful. I am sorry for being presumptuous, but could you please show me the correct way to allocate memory for UInt8MultiArray messages?

Acuadros95 commented 1 year ago

Here is a tutorial on how to enable the multi thread support: tutorial

As for the message memory issues, check this tutorial on message memory management: tutorial. Pay special attention to the sequence types.

Anyway, if you are using an ESP32, I encourage you to check the micro-ROS component for ESP-IDF. It even include a multithread publisher example.

sugithub7 commented 1 year ago

Dear Acuadros95,

I truly appreciate your thoughtful and thorough responses to my questions. I will continue to learn and gain experience with micro-ROS, striving to create something useful for others.

Thank you very much for your help.