ros-drivers / rosserial

A ROS client library for small, embedded devices, such as Arduino. See: http://wiki.ros.org/rosserial
515 stars 525 forks source link

Possible partial packet bug #237

Open SteveEasley opened 8 years ago

SteveEasley commented 8 years ago

The way MSG_TIMEOUT (https://github.com/ros-drivers/rosserial/blob/jade-devel/rosserial_client/src/ros_lib/ros/node_handle.h#L69) works seems to cause partial packets in the ring buffer to get dropped in most cases.

If a packet is only partially received into the buffer when spinOnce() is called, spinOnce() will properly return leaving the state of the process in tact. But once you call nh->getHardware()->delay (for times > 20ms), the subsequent call to spinOnce will drop the packet due to the 20ms timeout. See https://github.com/ros-drivers/rosserial/blob/jade-devel/rosserial_client/src/ros_lib/ros/node_handle.h#L69.

Was the idea that you should be delaying < 20ms? Seems like this could be implemented better, but before I offered a fix, I wanted to check if this was intentional.

Pikrass commented 7 years ago

I'm experiencing the same issue. Any packet too large to be sent in a single burst (around 60 bytes in my case if I remember well) will get dropped because of delay and processing time in the loop. I'm using rosserial_python and rosserial_arduino's ros_lib with an Arduino Mega.

I'm not sure what would be a good way to fix this. Maybe by using a unique packet header (a sequence of bytes that'd need to be escaped if seen in data) and constantly checking for it when receiving. That way truncated messages wouldn't mess everything up without the need for a timeout.

tom-f-oconnell commented 7 years ago

I increased the MSG_TIMEOUT to 5000 (milliseconds), as a workaround, and it works OK for my application. I also decreased the baud rate to 9600, because at baud rates >~20000 my messages were not reliably read out of the USB buffer before being overwritten. This was for messages of beteween 100 - 300 bytes (usually in the middle of the range), using rosserial_python and an Arduino Mega.

Setting the baud rate consists of nh.getHardware()->setBaud(9600); before the call to nh.initNode();, and then adding an appropriate baud parameter when launching the rosserial_python or rosserial_server node.

Pikrass commented 6 years ago

I'm working on the problem right now, I should be done in the beginning of next week. I went ahead with my idea of changing the protocol to allow for detecting partial packets without any timeout.