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

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

Open
victor-velezmoro opened this issue Sep 1, 2023 · 4 comments
Open

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

victor-velezmoro opened this issue Sep 1, 2023 · 4 comments

Comments

@victor-velezmoro
Copy link

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

@pablogs9
Copy link
Member

pablogs9 commented Sep 4, 2023

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

@victor-velezmoro
Copy link
Author

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 ?

@victor-velezmoro
Copy link
Author

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;
}

@pablogs9
Copy link
Member

pablogs9 commented Sep 5, 2023

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).

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