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

rosserial_python: Serial Port Read Behaviour #247

Open davidshin172 opened 8 years ago

davidshin172 commented 8 years ago

After upgrading from ROS indigo to kinetic, an instance of rosserial_python/serial_node.py generates the following error, repeatedly: Serial Port read returned short (expected 99 bytes, received 64 instead). Prior to the upgrade, the instance worked fine. Arduino code was simply recompiled with the kinetic's support code. My investigation leads me to believe that the serial port read behaviour is not suitable for specified timeout. In SerialClient.py, Line 401, tryRead(), it seems that rosserial_python expects a serial read operation to return exactly the amount of data requested:

try:
     bytes_read = self.port.read(length)
     if len(bytes_read) < length:
         # ...
         raise IOError()

However, as per the pySerial documentation, this is true only if timeout is set to 0. That isn't the case for the serial port used in SerialClient.py (By default), as seen around Line 324:

def __init__(self, port=None, baud=57600, timeout=5.0):
    # ...
    self.timeout = timeout
    # ...
    else:
        try:
            self.port = Serial(port, baud, timeout=self.timeout*0.5)

With the default arguments, the timeout value is nonzero. The issue is fixed when tryRead() is changed such that self.port.read() gets called in a loop until length amount of data. This was a stopgap measure from my side; if the client actualy stops short, the read operation will get stuck. I don't know why migrating from trusty/indigo to xenial/kinetic aggravated this issue. May be related to #186.

mikepurvis commented 8 years ago

Please send a PR with your fix; I'd be delighted to merge it.