Multiple broadcasts of same type

Hi!

At some occasions I am publishing additional multiple broadcasts from my node.
Like this:

my_publisher.publish(my_data1);
my_publisher.publish(my_data2);
my_publisher.publish(my_data3);
my_publisher.publish(my_data4);
my_publisher.publish(my_data5);
my_publisher.publish(my_data6);
my_publisher.publish(my_data7);

to generate 7 (or more) broadcasts of the same type but with different values.

I have noticed that this might result in un-finished transfers on the bus. If I add a node.spin([some ms]) between each publish call it works.

My best guess is that my_dataN are stored sequentially in outgoing buffer that becomes full.
(Other publishing messages or other stuff may also co-exist in the buffer). Can this be the case?

Is there a way to get status on current publish progress? In that way the status can be checked before adding more messages to the buffer to prevent it getting full.

Regards

There is no API at the moment for querying the status of the transmission queue. If desired, it can be trivially added here: https://github.com/UAVCAN/libuavcan/blob/c9a4021933239be43e879f14276349aff10ab702/libuavcan/include/uavcan/transport/can_io.hpp#L128-L176. However, this is not what most hard real-time applications would benefit from, since their publishing rates are generally known in advance and buffers are sized statically.

You seem to be correct at guessing that your issues are caused by the TX queue overflow. If lowering the publishing rate is not an option, consider increasing the size of the transmission queue (by allocating more memory for the library) and also make sure that your outgoing transfers are not being preempted by higher-priority frames on the bus (adjust priorities if necessary).

Yes, good idéa. My linux platform does not suffer from memory constrains, so I may try adjusting buffer size.

Thanks!

I thought I knew where to adjust TX queue size, but no…
Is it in any of the linux drivers header files?

Oh. If you are on Linux (for some reason I assumed that you are running that on an embedded platform), the queue size is probably not an issue, because it is sized by default to be 512 kibibyte large:

You can still increase it by instantiating your node manually instead of using the helpers, but it is unlikely to help. I am now suspecting that the culprit is your SocketCAN backend driver. Do I recall correctly that some months ago you were asking on this forum about the SocketCAN driver getting stuck because of malfunctioning frame loopback logic? How did you go about fixing that? If you simply disabled the loopback checks, then I am inclined to suspect that your modified SocketCAN driver simply overwhelms the underlying driver with too many frames; i.e., the problem lies not within libuavcan but rather within SocketCAN.

Do I recall correctly that some months ago you were asking on this forum about the SocketCAN driver getting stuck because of malfunctioning frame loopback logic?

Correct. However, that issue was related to another linux platform with very old kernel were required looback function wasn’t available in the driver.

How did you go about fixing that?

I compare frame IDs in buffers, you can see it in socketcan.hpp (25.7 KB) were #if defined(LOOPBACK_FIX) can be seen.

I do not use the attached fix for this particular platform. But I can use it to test…

Okay, what if your underlying SocketCAN driver returns your loopback frames before the corresponding outgoing frames are actually emitted to the bus? If that were the case, libuavcan would likely unload its TX queue faster than the controller can emit frames, leading to the behavior you are observing with frame losses. Do you think that might be the case? Can you inspect the driver code or perhaps conduct a test to establish whether the loopback return actually waits for the completion of the corresponding transmission?

1 Like