eProsima / Micro-XRCE-DDS-Client

Micro XRCE-DDS Client repository. Looking for commercial support? Contact info@eprosima.com
Apache License 2.0
130 stars 82 forks source link

client on MCU create session failed #376

Closed Pansamic closed 9 months ago

Pansamic commented 9 months ago

description

I need to minimize project code and use CMake to build whole project so I need to use Micro-XRCE-DDS-Client rather than Micro-ROS, which use ros2 packages to compile.

client on MCU generate such data sequence when uxr_init_session(&session, &transport.comm, 0xAAAABBBB) and uxr_create_session(&session) were called.

80 00 00 00 00 01 10 00 58 52 43 45 01 00 01 0f aa aa bb bb 81 00 fc 03

Agent seems not to respond to this sequence.

I have another Micro-ROS project and Micro-ROS rmw_uros_ping_agent(100,1) function generates such sequence and received response data from Agent.

7e 00 00 10 00 80 00 00 00 02 01 08 00 00 0a ff fd 02 00 00 00 cf 12

So I'm doubting that the client sent wrong sequence to Agent?

This is code in main()`:

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  MX_USART1_UART_Init();

  uxrCustomTransport transport;
  uxr_set_custom_transport_callbacks(
      &transport,
      false,
      my_custom_transport_open,
      my_custom_transport_close,
      my_custom_transport_write,
      my_custom_transport_read);

  if (!uxr_init_custom_transport(&transport, &huart1))
  {
      while(1);
  }

//  while(!uxr_ping_agent(&transport.comm, 200))
//  {
//
//  }
//  uint8_t ping_buf[23]={0x7e, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00,
//                      0x00, 0x02, 0x01, 0x08, 0x00, 0x00, 0x0a, 0xff,
//                      0xfd, 0x02, 0x00, 0x00, 0x00, 0xcf, 0x12};
//  while(1)
//  {
//    HAL_UART_Transmit(&huart1, ping_buf, 23, HAL_MAX_DELAY);
//    HAL_Delay(1000);
//  }

  uxrSession session;
  uxr_init_session(&session, &transport.comm, 0xAAAABBBB);
  if (!uxr_create_session(&session))
  {
      while(1);
  }

  while (1)
  {
      HAL_Delay(1000);
  }
}

custom porting

Use custom transport - UART

collect the following source files:

    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/stream/input_best_effort_stream.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/stream/input_reliable_stream.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/stream/output_best_effort_stream.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/stream/output_reliable_stream.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/stream/stream_storage.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/stream/stream_id.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/stream/seq_num.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/session.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/session_info.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/submessage.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/object_id.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/serialization/xrce_types.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/serialization/xrce_header.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/serialization/xrce_subheader.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/util/time.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/util/ping.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/common_create_entities.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/create_entities_ref.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/create_entities_xml.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/create_entities_bin.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/read_access.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/core/session/write_access.c
    Middlewares/Micro-XRCE-DDS-Client/src/c/profile/transport/custom/custom_transport.c
    Middlewares/micro-cdr/src/c/common.c
    Middlewares/micro-cdr/src/c/types/*.c

Include folders

Middlewares/Micro-XRCE-DDS-Client/include
Middlewares/micro-cdr/include

modified int64_t uxr_nanos(void) function in src/c/utils/time.c - remove clock_gettime() and use HAL ticks as time source temporarily.

int64_t uxr_nanos(
        void)
{
#ifdef WIN32
    ......
#else
    /* 1702265653 is December 11 2023 time stamp offset */
    /* HAL_GetTick() returns miliseconds */
    return (1702265653000000000ULL)+(HAL_GetTick()*1000000) ;
#endif /* ifdef WIN32 */
}

Include generated config.h:

#ifndef _UXR_CLIENT_CONFIG_H_
#define _UXR_CLIENT_CONFIG_H_

#define UXR_CLIENT_VERSION_MAJOR 2
#define UXR_CLIENT_VERSION_MINOR 4
#define UXR_CLIENT_VERSION_MICRO 2
#define UXR_CLIENT_VERSION_STR "2.4.2"

#define UCLIENT_PROFILE_DISCOVERY

// #define UCLIENT_PROFILE_UDP
// #define UCLIENT_PROFILE_TCP
/* #undef UCLIENT_PROFILE_CAN */
// #define UCLIENT_PROFILE_SERIAL
#define UCLIENT_PROFILE_CUSTOM_TRANSPORT
/* #undef UCLIENT_PROFILE_MULTITHREAD */
/* #undef UCLIENT_PROFILE_SHARED_MEMORY */
// #define UCLIENT_PROFILE_STREAM_FRAMING

/* #undef UCLIENT_PLATFORM_POSIX */
/* #undef UCLIENT_PLATFORM_POSIX_NOPOLL */
/* #undef UCLIENT_PLATFORM_WINDOWS */
/* #undef UCLIENT_PLATFORM_FREERTOS_PLUS_TCP */
/* #undef UCLIENT_PLATFORM_RTEMS_BSD_NET */
/* #undef UCLIENT_PLATFORM_ZEPHYR */

#define UXR_CONFIG_MAX_OUTPUT_BEST_EFFORT_STREAMS     1
#define UXR_CONFIG_MAX_OUTPUT_RELIABLE_STREAMS        1
#define UXR_CONFIG_MAX_INPUT_BEST_EFFORT_STREAMS      1
#define UXR_CONFIG_MAX_INPUT_RELIABLE_STREAMS         1

#define UXR_CONFIG_MAX_SESSION_CONNECTION_ATTEMPTS    10
#define UXR_CONFIG_MIN_SESSION_CONNECTION_INTERVAL    1000
#define UXR_CONFIG_MIN_HEARTBEAT_TIME_INTERVAL        100

#ifdef UCLIENT_PROFILE_UDP
#define UXR_CONFIG_UDP_TRANSPORT_MTU                  512
#endif
#ifdef UCLIENT_PROFILE_TCP
#define UXR_CONFIG_TCP_TRANSPORT_MTU                  512
#endif
#ifdef UCLIENT_PROFILE_SERIAL
#define UXR_CONFIG_SERIAL_TRANSPORT_MTU               512
#endif
#ifdef UCLIENT_PROFILE_CUSTOM_TRANSPORT
#define UXR_CONFIG_CUSTOM_TRANSPORT_MTU               1024
#endif

#ifdef UCLIENT_PROFILE_SHARED_MEMORY
#define UXR_CONFIG_SHARED_MEMORY_MAX_ENTITIES          4
#define UXR_CONFIG_SHARED_MEMORY_STATIC_MEM_SIZE       10
#endif

#define UCLIENT_TWEAK_XRCE_WRITE_LIMIT

/* #undef UCLIENT_HARD_LIVELINESS_CHECK */

#ifdef UCLIENT_HARD_LIVELINESS_CHECK
#define UXR_CONFIG_HARD_LIVELINESS_CHECK_TIMEOUT_STR     "10000"
#endif

// Version checks
#if UXR_CLIENT_VERSION_MAJOR >= 3
#error UCLIENT_HARD_LIVELINESS_CHECK shall be included in session API
#error MTU must be included in CREATE_CLIENT_Payload properties
#error Reorder ObjectInfo https://github.com/eProsima/Micro-XRCE-DDS/issues/137
#endif

#endif // _UXR_CLIENT_CONFIG_H_

custom_transport code

a copy from repo - micro_ros_stm32cubemx_utils/extra_sources/microros_transports/it_transport.c:

#include <uxr/client/transport.h>

#include "main.h"
#include "uxr_transport.h"
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#if 1

// --- micro-ROS Transports ---
#define UART_IT_BUFFER_SIZE 2048

static uint8_t it_buffer[UART_IT_BUFFER_SIZE];
static uint8_t it_data;
static size_t it_head = 0, it_tail = 0;

extern UART_HandleTypeDef huart1;

bool my_custom_transport_open(struct uxrCustomTransport * transport){
    UART_HandleTypeDef * uart = (UART_HandleTypeDef*) transport->args;
    HAL_UART_Receive_IT(uart, &it_data, 1);
    return true;
}

bool my_custom_transport_close(struct uxrCustomTransport * transport){
    UART_HandleTypeDef * uart = (UART_HandleTypeDef*) transport->args;
    HAL_UART_Abort_IT(uart);
    return true;
}

size_t my_custom_transport_write(struct uxrCustomTransport* transport, uint8_t * buf, size_t len, uint8_t * err){
    UART_HandleTypeDef * uart = (UART_HandleTypeDef*) transport->args;

    HAL_StatusTypeDef ret;
    if (uart->gState == HAL_UART_STATE_READY){
        ret = HAL_UART_Transmit(uart, buf, len, HAL_MAX_DELAY);
        while (ret == HAL_OK && uart->gState != HAL_UART_STATE_READY);

        return (ret == HAL_OK) ? len : 0;
    }else{
        return 0;
    }
}

size_t my_custom_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* err){
    size_t wrote = 0;
    while ((it_head != it_tail) && (wrote < len)){
        buf[wrote] = it_buffer[it_head];
        it_head = (it_head + 1) % UART_IT_BUFFER_SIZE;
        wrote++;
    }

    return wrote;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(it_tail == UART_IT_BUFFER_SIZE)
        it_tail = 0;

    it_buffer[it_tail] = it_data;
    it_tail++;

    HAL_UART_Receive_IT(huart, &it_data, 1);
}

#endif
pablogs9 commented 9 months ago

Which is the output of the XRCE Agent with the -v6 flag?

Pansamic commented 9 months ago

Nothing. image

pablogs9 commented 9 months ago

That means that your board is not sending anything via UART port. Could you debug that?

Pansamic commented 9 months ago

Agent didn't respond to this client. I use cutecom to monitor UART output and get Sequence-1 when program runs to uxr_init_session(&session, &transport.comm, 0xAAAABBBB)

Sequence-1 generated by uxr_init_session(&session, &transport.comm, 0xAAAABBBB)

// Sequence-1
80 00 00 00 00 01 10 00 58 52 43 45 01 00 01 0f aa aa bb bb 81 00 fc 03
pablogs9 commented 9 months ago

The agent did not receive anything as you can see in your image. Are you choosing the right serial device and baudrate?

Pansamic commented 9 months ago

Yes, I've checked serial device and baudrate (default is 115200) countless times.

Sequence-2 is the client output of rmw_uros_ping_agent(100,1) of a Micro-ROS project.

// Sequence-2
7e 00 00 10 00 80 00 00 00 02 01 08 00 00 0a ff fd 02 00 00 00 cf 12

If I manually send Sequence-2 through UART just like the commented lines in main() above, MCU received responding data. UART rx buffer has something in it. But if I uxr_init_session() doesn't receive anything.

pablogs9 commented 9 months ago

You are not waiting timeout in my_custom_transport_read, also in uxr_set_custom_transport_callbacks you are setting false to the framing option, which is required for serial communications

Pansamic commented 9 months ago

Thank you for your help, I've solve this problem. It's because I set framing option false in uxr_set_custom_transport_callbacks(). Client create session successfully now. So stream framing is an indispensable builtin feature of Micro-XRCE-DDS-Client? image