eProsima / Micro-XRCE-DDS-Apps

Looking for commercial support? Contact info@eprosima.com
10 stars 5 forks source link

appMain failed at uxr_create_session #12

Closed vibnwis closed 3 years ago

vibnwis commented 3 years ago

Would you share what causes uxr_create_session() to fail. When I tested the Micro-XRCE-DDS-Apps, it could not create the session, printed out the " Error-Create session fail". Any advice is appreciated.

Thank you

pablogs9 commented 3 years ago

Is the Agent receiving the the XRCE CREATE message and answering it?

vibnwis commented 3 years ago

Nope. I think the buses timing are different, i.e., the bus timing on the microcontroller ( client) and PC (agent) are not the same. I am looking into it now. Many thanks.

On Mon, 30 Nov 2020 at 20:09, Pablo Garrido notifications@github.com wrote:

Is the Agent receiving the the XRCE CREATE message and answering it?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/eProsima/Micro-XRCE-DDS-Apps/issues/12#issuecomment-735597238, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADCYQVSX4V53XPCMH2CENL3SSNAKZANCNFSM4UGNBACA .

vibnwis commented 3 years ago

I have corrected the CAN bitrates. Now both micro-agent and micro-app can communicate. However, I revisited the code, and I was wondering if you could share some insight of the following implementation. The reason is I am not 100% sure it is right. I am still using the same arguments of

bool uxr_init_can_transport(
        uxrUDPTransport* transport,
        struct uxrUDPPlatform* platform,
        uxrIpProtocol ip_protocol,
        const char* ip,
        const char* port)

However, I don't need ip, port, ip_protocol, hence I simply filled them up for the sake of fooling the system. The platform->poll_fd.fd is not filled, as the CAN bus does not have it. See below code. Nevertheless, I can receive CAN data though recv_can_msg(). Appreciate your comment, please.

     ip_protocol = UXR_IPv4;
            ip = "192.168.1.10";
            port = "8888";

       //platform->poll_fd.fd = socket(AF_INET, SOCK_DGRAM, 0);     
            /* Setup platform. */
            transport->platform = platform;

            /* Setup interface. */
            transport->comm.instance = (void*)transport;
            transport->comm.send_msg = send_can_msg;
            transport->comm.recv_msg = recv_can_msg;
            transport->comm.comm_error = get_can_error;
            transport->comm.mtu = UXR_CONFIG_CAN_TRANSPORT_MTU;
            rv = init_CAN_bus();
//       }
pablogs9 commented 3 years ago

I think that it is ok to keep these fields unused at least for the first version.

vibnwis commented 3 years ago

Hi Pablogs9,

I have completed CAN-transport of Micro-Agent, and now trying to do the end-to-end testing.

I have read DDS-XRCE protocol that for uClient and uAgent to establish a communication, a u-client needs to make it known to u-Agent by sending a request message. With that I would see a call to send_can_msg in udp_transport_external.c. However, I don't see that happening, only recv_can_msg() is being called again and again.

I have checked that uxr_init_can_transport() succeeded the initialisation. It is also manifested by the calling of send_can_msg().

Also, how the request message looks like? FYI, CAN frame takes only 8 bytes, and normally it does not implement any multiple frames protocol. The reason I ask, is because, I can make-up are request message to transmit to u-Agent for testing if u-agent works as it should. FYI, at the moment of time, u-agent is at listening mode, and I can't really test any further. Of course, I made up a frame and send it to u-agent to test it for the moment. However, u-agent received but not acknowledging or responding to it.

Can you help please?

Appreciate your comments, please?

vibnwis commented 3 years ago

As far as I am concerned, CAN frames take only 8 bytes payload, if the existing upper layer protocol, ie applications sending out anything longer, it will be discarded. Any comment will be appreciated.

Thank you.

vibnwis commented 3 years ago

To be more specific, in the function

bool uxr_create_session_retries(uxrSession* session, int retries)
{
    uxr_reset_stream_storage(&session->streams);

    uint8_t create_session_buffer[CREATE_SESSION_MAX_MSG_SIZE];
    ucdrBuffer ub;
    ucdr_init_buffer_origin_offset(&ub, create_session_buffer, CREATE_SESSION_MAX_MSG_SIZE, 0u, uxr_session_header_offset(&session->info));

    uxr_buffer_create_session(&session->info, &ub, (uint16_t)(session->comm->mtu - INTERNAL_RELIABLE_BUFFER_OFFSET));
    uxr_stamp_create_session_header(&session->info, ub.init);

    bool received = wait_session_status(session, create_session_buffer, ucdr_buffer_length(&ub), (size_t) retries);

    received = true;

    printf("\n\rSESSION STATUS received = %d\n\r", received);
    bool created = received && UXR_STATUS_OK == session->info.last_requested_status;
    printf("\n\rSESSION created  %d \n\r", created);
    return created;
}

If it send out or trigger the transmitting send_can_msg(), it would display printf("\n\rHAL_CAN_AddTxMessage() Passed \n\r");

But it does not take place. Hence, by my understanding it will not pass bool created = received && UXR_STATUS_OK == session->info.last_requested_status;

Does it make sense?

vibnwis commented 3 years ago

These the display messages for debugging purposes. Hope these are helpful.


cb_read_CAN_frame() entered

circularByteBuffer length 0

recv_can_msg() bytes_received is 0

SESSION STATUS received = 1

SESSION created 0

appMain: Error-Create session fail

pablogs9 commented 3 years ago

Can you share a trace from the agent using the verbosity flag -v6 I would like to see if the agent is receiving the CREATE_SESSION message

vibnwis commented 3 years ago

I use gdb, and I display any messages (CAN frames) at the transport, and I did not see any messages by far. For that reasons, I sent my own messages to test the Agent CAN transport implementation. The tests were then with the Client connected to Agent. How I know they are connected or the CAN transport work? By opening another Term and send a CAN frame, I can see the client received it and displayed it.

Nevertheless, here is the trace, ./MicroXRCEAgent can2 -v6 can_frame is 16 bytesSocketCAN bind() succeeded SocketCAN getsockopt() succeeded SocketCAN error none SocketCAN for interface can0 succeeded CAN2Agent::recv_message() entered SocketCAN:: handler 3 SocketCAN::read getsockopt() succeeded len = 4 SocketCAN:: Read() - A Frame memory space is ready and about to read from CAN interface can0 [1607947178.308166] info | Root.cpp | set_verbose_level | logger setup | verbose_level: 6

vibnwis commented 3 years ago

Don't get confused by the "SocketCAN::read getsockopt() succeeded len = 4", it has nothing to do with incoming CAN frame. You see that "SocketCAN:: Read() - A Frame memory space is ready and about to read from CAN interface can0" is at listening state waiting for frames, and it will then read and show it immediately. This is the time, where I use another Term to fire "cansend 123#1122334455667788", and the Agent would then shows the frame contents.

pablogs9 commented 3 years ago

It seems that your Agent is not receiving anything (any complete XRCE frame). Do you have any way of checking if frames are arriving?

vibnwis commented 3 years ago

However, from the Client side, I did not see anything being sent as well. See below.

cb_read_CAN_frame() entered <---- this reading the incoming frame buffer

circularByteBuffer length 0

recv_can_msg() bytes_received is 0 <---- this is the reading zero

SESSION STATUS received = 1 <-- this is the session thingy

SESSION created 0

appMain: Error-Create session fail

Count 0
cb_read_CAN_frame() entered

circularByteBuffer length 0

Count 1
cb_read_CAN_frame() entered

circularByteBuffer length 0

vibnwis commented 3 years ago

send_can_msg() routine not being called by far but only recv_can_msg()

vibnwis commented 3 years ago

Hi Pablo,

Would you mind sharing if any of the following routines sending out session request? I follow through it, but don't seem able to identify any sending out the session request. Can you help, please?

uxr_init_session(&session, &transport.comm, 0xBA5EBA11); uxr_set_topic_callback(&session, (void *)on_topic, NULL);

if(!uxr_create_session(&session))
{
    printf("\n\rappMain: Error-Create session fail\n\r");
    vTaskSuspend( NULL );
}
vibnwis commented 3 years ago

Hi pablogs9,

Okie, further trace, I found that uxr_create_session(&session) indeed calls send_message() routine below, and the send_msg() also correctly calls the send_can_msg() of CAN-Transport implementation. However, here it comes the issue, from the gdb, I could see that the length of the buffer (ie request message) is 20. However, CAN bus could only take 8 bytes. Would you able to help advising what would be the best strategy for resolving the solution. I can think of reducing it to 8, but I do not know abou the implication of it may involve for other parts of the system. Obviously, its counterpart, uagent will need to change accordingly. Would you help to discuss it with jamoralp too. I am happy to make those changes here. However, your advice and assistance are very much needed, please. I look forward to hearing from you soon.

inline bool send_message(const uxrSession session, uint8_t buffer, size_t length) { bool sent = session->comm->send_msg(session->comm->instance, buffer, length); UXR_DEBUG_PRINT_MESSAGE((sent) ? UXR_SEND : UXR_ERROR_SEND, buffer, length, session->info.key); return sent; }

pablogs9 commented 3 years ago

The session creation message should be as it is. So, the point is that your transport functionsis like:

size_t uxr_write_udp_data_platform(
        uxrUDPPlatform* platform,
        const uint8_t* buf,
        size_t len,
        uint8_t* errcode);

Here in the len you will receive the 20 B of the message length and of course the buf will have 20 B, now you have multiple options:

  1. Implement a for loop inside the function that sends the 20 B in groups of 8 B.
  2. Just send 8 B and return 8, this return will tell the library that you only have been able to send 8 and it should call again if wants the 20 Bytes sent.

For your info, here you have a transport (radio transport) that only allow to send 30 B per message: https://github.com/micro-ROS/freertos_apps/blob/19e7d4a81348c91c8b9784ddd80c07872b5aa138/microros_crazyflie21_extensions/src/crazyflie_transport.c#L59

vibnwis commented 3 years ago

Would you be able to comment on the uAgent side when receiving only 8 bytes?

On Tue, 15 Dec 2020 at 20:03, Pablo Garrido notifications@github.com wrote:

The session creation message should be as it is. So, the point is that your transport functionsis like:

size_t uxr_write_udp_data_platform( uxrUDPPlatform platform, const uint8_t buf, size_t len, uint8_t* errcode);

Here in the len you will receive the 20 B of the message length and of course the buf will have 20 B, now you have multiple options:

  1. Implement a for loop inside the function that sends the 20 B in groups of 8 B.
  2. Just send 8 B and return 8, this return will tell the library that you only have been able to send 8 and it should call again if wants the 20 Bytes sent.

For your info, here you have a transport (radio transport) that only allow to send 30 B per message: https://github.com/micro-ROS/freertos_apps/blob/19e7d4a81348c91c8b9784ddd80c07872b5aa138/microros_crazyflie21_extensions/src/crazyflie_transport.c#L59

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/eProsima/Micro-XRCE-DDS-Apps/issues/12#issuecomment-745097837, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADCYQVXNOGZYHQY2YVRMQNDSU4C3LANCNFSM4UGNBACA .

pablogs9 commented 3 years ago

In your agent CAN transport you should be handling this stream, I mean, in these radio transport that I have provided you, for example, we have an intermediate program that receives these radio messages and streams them to an XRCE serial Agent. So, as you are implementing a uAgent CAN transport, this transport should be in charge of receiving CAN frames, joining them and provided them to the XRCE engine of the agent as XRCE frames.

vibnwis commented 3 years ago

After long consideration which I had thought it before, I think I will implement a messaging protocol in the CAN frames. I was hesitant as the CAN classic frames are 8 bytes, with addition of byte length and sequence, left only 7 bytes. However, in this case for conforming the existing messaging, I would be cleaner to implement in the CAN-protocol.

Thank you