Page 137 - Hacking Roomba
P. 137
118 Part I — Interfacing
If you saw this code without knowing about serialEvent(), it would appear nonsensical.
First sensorsValid = false and then it’s repeatedly checking to see if it’s true. But know-
ing about serialEvent(), it’s easy to see what’s going on: The sensors() method sends the
SENSORS command to the Roomba and then it waits for up to 20 × 50 = 1000 milliseconds for
the Roomba to send back data. If sensorsValid results in true, the loop is exited early. In
either case, the value of sensorsValid() is returned so that the caller of updateSensors()
can quickly know if it worked or not.
With updateSensors() your Roomba control code (which doesn’t have a user interface or
anything else time-sensitive) can look similar to what the hypothetical pseudo-code looked
like. In use, you do this:
boolean valid = roombacomm.updateSensors();
if( !valid ) {
System.out.println(“Couldn’t get sensors from Roomba.”);
}
Further Improvements
When not using updateSensors(), you must poll the sensorsValid flag regularly to make
sure the data you read is reliable. A way to improve on this is to present an event-based inter-
face to users of RoombaComm. Just like RXTX’s SerialPort and its listeners, there could be
RoombaComm sensor listeners that get notified whenever sensor data is valid. This hasn’t been
implemented, but feel free to experiment and make it work. You already have a start on it with
the callback to the computeSensors() method after receiving a full sensor packet. Changing
this to be a general event-based system would simply mean you add a method like the RXTX
addEventListener() method. Then, in addition to computeSensors(), call a method on
each listener (maybe called sensorDataAvailable()?) to notify them of new sensor data.
Parsing Sensor Data
Now that you have the sensor data in a little 26-byte array, the task is to figure out how to parse it.
Recall from Figures 2-5, 2-6, and 2-7 the organization of the sensor data packet. For SENSORS_ALL,
Roomba sends the data as a single 26-byte chunk.The first byte is the bumps and wheeldrops bit
field, the second byte is the wall value, and so on.The data has different formats:
Word values: Two bytes joined together form a 16-bit value.
Bit fields: A single sensor byte contains several independent binary values.
Enumerations: A non-numeric byte with arbitrary values.
Byte values: A byte contains a byte. This is the easy case, mostly.
And for the non-bit values, there are the unsigned and signed (positive and negative) variants.
Dealing with just the raw byte array with all these different types of data would be a big pain in
the neck, so it’s time to design some wrappers.