# Roomba Create 2 problem reading distance traveled

I am trying to work with the create2. In using the "get distance traveled" command (id 142) I am getting back incorrect data. My simple test case logic is

I am working with the Create2_TetheredDrive.py example and adding this

    elif k == 'PLUS' or k == 'MINUS': # Move 200mm forward or backward
# reset distance measurement by sending request
sendCommandASCII('142 19')
recv_basic(connection)
# set velocity mm/s
v = 200;
if k=='MINUS':
v=-v
# start moving
cmd = struct.pack(">Bhh", 145, v, v)
sendCommandRaw(cmd)
# pause 1 second
time.sleep(1);
# stop moving
cmd = struct.pack(">Bhh", 145, 0, 0)
sendCommandRaw(cmd)
# get distance traveled
sendCommandASCII('142 19')
data = recv_basic(connection)
dist = struct.unpack('>h',data)
print(dist)


I consistently numbers near -25 for moving forward, and +25 for moving backward. If I wait for 2 seconds, I get -50 for moving forward, and +50 for moving backward. The documentation says it should return the distance traveled in mm, so these numbers seem to be off by a factor of -8.

Anyone have any suggestions? Thanks.

p.s. I had to add this function to the example as well

def recv_basic(the_socket):
the_socket.settimeout(0.1)
total_data=[]
while True:
try:
data = the_socket.recv(8192)
total_data.append(data)
except:
break
return ''.join(total_data)


There are two problems at work here.

First, you wrote a function to get data from the robot using sockets, but the robot is being connected to via a pySerial serial object. I wrote a function for you to use instead of recv_basic. I'll be sure to add this helper function and others like it to Create2_TetheredDrive.py when I can. Using this function, running your code gives me a result of around 185-190, which is about what I'd expect (given that the robot has to accelerate and decelerate during that one second; it doesn't immediately get up to speed).

# get16Signed returns a 16-bit signed value.
# Whether it blocks is based on how the connection was set up.
def get16Signed():
global connection

try:
except serial.SerialException:
print "Lost connection"
tkMessageBox.showinfo('Uh-oh', "Lost connection to the robot!")
connection = None
except struct.error:
print "Got unexpected data from serial port."
return None


Just add this function and replace your calls to recv_basic(connection) with get16Signed() (and also get rid of that call to struct.unpack as get16Signed will return an integer) and you should be all set!

Second, we found a bug with sensor packets which return values in units of millimeters in robot firmware versions prior to 3.3.0. The affected packets are '19' and '40.' Please see the relevant sections of the Open Interface Spec for more details.

Happy hacking!

Please note that while I'm an iRobot employee, the postings on this site are my own and don't necessarily represent iRobot's positions, strategies, or opinions.

• OK - I went back to a serial connection and used your function to read the distance traveled - mine still comes back and gives a -48 when I expect a number around +200. I'm getting to run a set of tests with different speeds and times, but it looks like the numbers are consistently off by a factor of around -4. Commented Mar 30, 2015 at 16:26
• Just a quick update - this has been determined to be a bug in the Create2 firmware - the iRobot folks were very helpful in tracking this down. They have suggested using either packet ID 43 or 44 (or both) to get the number of encoder counts per wheel, and then using the number of counts per rev (508.8) and diameter of the wheel (72 mm) as a temporary workaround to compute distance traveled. Commented Apr 3, 2015 at 8:22