micro-ROS/micro-ROS-Agent

How to use SHM in mico-ROS (Using docker)

ge65luz opened this issue · 4 comments

Issue template

  • Hardware description: docker, Ubuntu 22.04
  • RTOS:
  • Installation type:
  • Version or commit hash: humble

Steps to reproduce the issue

Hey, i have created a publisher and subscriber chain with micro-ROS nodes in a docker container , to analyze latencies. It works fine when i use the Agent. Now i want to use SHM. Therefore, i added "-DUCLIENT_PROFILE_SHARED_MEMORY=ON" to my colcon.meta. Do i still have to build the agent and the other steps like:

ros2 run micro_ros_setup build_firmware.sh
source install/local_setup.bash
ros2 run micro_ros_setup create_agent_ws.sh
ros2 run micro_ros_setup build_agent.sh
source install/local_setup.bash
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888 -v6

I am not using a microcontroller, does this still work.? I want to see how big the latency is with and without the Agent. I am using Cyclone DDS, is this maybe the problem?

All nodes are in the same container.

Are there any modifications I forgot to do ?

Expected behavior

Actual behavior

Additional information

Cyclone DDS is not compatible with micro-ROS. Please recheck with Fast DDS.

Thanks for the answer. I now tried Fast DDS. With the Agent running, the communication works (but using the Agent). If I launch the nodes without the Agent, the nodes abort after a short time.
This i the error message i get:

root@docker-desktop:/microros_ws# ros2 run micro_ros_demos_rclc LIDAR
[ERROR 1693841179.668659857]: [rclc_init] Error in rcl_init: error not set, at ./src/rcl/init.c:218

Failed status on line 66: 1. Aborting.

In line 66 of my code is this:
RCCHECK(rclc_support_init(&support, argc, argv, &allocator));

and i use the default allocator:

rcl_allocator_t allocator = rcl_get_default_allocator();
rclc_support_t support;

All nodes are sourced and run on rmw_microxrcedds:

source /opt/ros/humble/setup.bash
source install/local_setup.bash
export RMW_IMPLEMENTATION=rmw_microxrcedds
ros2 run micro_ros_demos_rclc LIDAR

Any idea why is does not work ?

i did not change the code of my nodes for the use of SHM. Do i have to do that ?
this is e.g. the code for my publisher node at the beginning of the chain:

#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <errno.h>
#include <std_msgs/msg/string.h>
#include <sys/time.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <string.h>

#define ARRAY_LEN 200

#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); return 1;}}
#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 publisher;
rcl_timer_t timer;
std_msgs__msg__String msg;
int msg_count = 0;  // Variable to hold the current message count

FILE* pub_file;

void get_timestamp(char* timestamp, size_t size)
{
    struct timeval tv;
    
    // Get the current time
    gettimeofday(&tv, NULL);
    
    // Convert the time to microseconds
    unsigned long long current_time_microseconds = (unsigned long long)(tv.tv_sec) * 1000000 + tv.tv_usec;
    
    snprintf(timestamp, size, "%llu", current_time_microseconds);
}

void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
    if (timer != NULL) {
        snprintf(msg.data.data, ARRAY_LEN, "%d", msg_count++); // Fill msg.data with incrementing numbers
        msg.data.size = strlen(msg.data.data);
        msg.data.capacity = ARRAY_LEN;

        RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));

        char timestamp_pub[26];
        get_timestamp(timestamp_pub, sizeof(timestamp_pub));

        int res = fprintf(pub_file, "%s - %s\n", msg.data.data, timestamp_pub);
        if (res < 0) {
        perror("Failed to write to micro_pub.csv");
        } else {
        fflush(pub_file);
        }

        printf("Publishing (Controller, '%s'): ' %s'\n", timestamp_pub, msg.data.data);
    }
}

int main(int argc, const char * const * argv)
{
	rcl_allocator_t allocator = rcl_get_default_allocator();
	rclc_support_t support;

	RCCHECK(rclc_support_init(&support, argc, argv, &allocator));

	rcl_node_t node;
	RCCHECK(rclc_node_init_default(&node, "string_node", "", &support));

	RCCHECK(rclc_publisher_init_best_effort(
		&publisher,
		&node,
		ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, String),
		"/sensor_data"));

	const unsigned int timer_timeout_ms = 100;
	RCCHECK(rclc_timer_init_default(
		&timer,
		&support,
		RCL_MS_TO_NS(timer_timeout_ms),
		timer_callback));

	rclc_executor_t executor = rclc_executor_get_zero_initialized_executor();

	RCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));
	RCCHECK(rclc_executor_add_timer(&executor, &timer));

	msg.data.data = (char * ) malloc(ARRAY_LEN * sizeof(char));
	msg.data.size = 0;
	msg.data.capacity = ARRAY_LEN;

    if (msg.data.data == NULL) {
    fprintf(stderr, "Failed to allocate memory for msg.\n");
    return 1;
    }

    pub_file = fopen("/microros_ws/src/_csv_files/lidar_sensor_pub.csv", "w");
    if (pub_file == NULL) {
        perror("Failed to open micro_pub.csv");
        return 1;
    }
    fprintf(pub_file, "Lidar-PUB\n");

	rclc_executor_spin(&executor);

	fclose(pub_file);

	RCCHECK(rcl_publisher_fini(&publisher, &node));
	RCCHECK(rcl_timer_fini(&timer));
	RCCHECK(rcl_node_fini(&node));

	return 0;
}

The micro-ROS client needs an agent to init the session, the SHM mechanism is a way of communicating entities inside an up-and-running XRCE session (that needs an agent to be valid).