Assignment #1
Task Summary:
Program an iRobot Create to, starting from an unknown location, seek out and dock with the Roomba docking station.
Code (gelliott_robotics_asn1.zip):
The program for this assignment communicates with the Create via Bluetooth, so virtually any robot control program environment is possible. My solution was coded and runs on MacOS X. The program is written in C++.
The code makes use of two code packages (both are included in the source code above):
1)libcreateoi - A GPL library that wraps several communication details of the OI standard. Simplifies commands to such APIs as drive(), turn(), and getBumper(). The library also handles serial port details.
2)pthread++ - A small package of my own of simple C++ wrappers around pthread primitives.
Compiling and Running the Code:
The code should compile and run on any posix-compliant system (simply do g++ *.cpp -lm -pthread), though this has not been tested. The code package is distributed as a MacOS X Xcode 3.1 project package. The source code may be compiled and run from there.
The program takes an optional argument (Roomba <serial port>) of the path to the serial port to use for communication. If not supplied, the serial port of /dev/tty.roomba is used.
The default port is specified by the global variable serialPort found in main.cpp. Also note that on MacOS X, Bluetooth serial port names may be changed in the advanced Bluetooth settings dialog.

You may run my program from either Xcode or command-line.
Description of Solution:
- Algorithm -
On start, the Create will begin a random walk (state = RandomWalk) where it will travel in slight arcs. This will continue until the Create has detected either a wall (wall sensor value >= 5) or detects docking station IR buoy.
In the case a wall is detected, the Create will attempt to maximize the wall sensor reading (using a binary search of rotations positions) and continue along the wall (state = WallFollow) and will do its best to maintain a high wall sensor value. The Create will move in a slight right-turn arc as to not lose track of the wall (and sharp arc in case of a drastic drop-off in wall sensor value). This will continue until the Create detects a docking station IR buoy or the wall is totally lost. In this last case, the Create reverts to the random walk after 4 seconds.
On detection of the IR buoy, the Create will continue to drive straight forward (state = Dock) until the IR signal degrades. When this occurs, the Create will stop and attempt to maximize the IR signal using a binary search of rotation positions. The Create will always move in a forward direction towards the docking station. If the create bumper is hit on both right and left sides while all three IR sensors are active (Red, Green, and Force Field), the Create will switch to passive mode and attempt to charge/dock. If after 3 seconds, the Create is not charging, it will back up and start again. Otherwise the program will terminate. If at any point the IR signals are completely lost, the Create will revert back to the random walk after 10 seconds in this state.
- State Machine -
The code is organized into a state machine with three states (besides Initial and Shutdown). The current state may transition to a new state on the following inputs: onEnter(), onBump(), onTimeout(), onWallOverThreshold(), onWallUnderThreshold(), and onIR(). The states are executed in a single StateMachine class which executes an event-loop of Create sensor polling and dispatching of events; an event-loop iteration is executed about every 100ms.
Regarding onTimeout(), states may “communicate” with the StateMachine to set up timers to track events such as “time away from wall.” Timeouts are used as fail-safes for the Create to revert to its random walk behavior. States may also communicate with the StateMachine to control desired sensor thresholds for event notifications.
Here is a basic design of the state machine state transitions:
onIR() - any combination of IR buoys.
onWallOverThreshold() - wall sensor value >= 5.
onBump() - If all three IR signals are active and the Create is charging.
onIR() - any combination of IR buoys.
onTimeout() - Transition if IR signal = 0
Timeout is 10 seconds.
onTimeout() - Transition if wall sensor value < 4. Timeout is 4 seconds.
The states also loop on the following inputs (most interesting behaviors take place here):
RandomWalk
onBump() - Back up 2cm and turn around at a random angle and continue driving. If the bump is on the right, the random angle is between (0, 90) degrees. If on the left, the angle is between (0, -90). If on both, the angle is (90, 180).
WallFollow
onWallUnderThreshold() - If the sensor drop is significant (> 20), then make a sharp right turn to attempt to find the wall (also set the “lost wall” timeout). Otherwise, try to maximize the wall sensor with a binary search. If this fails to bring the wall sensor to an acceptable level, set a “lost wall” timeout.
onBump() - Back up 2cm. If bumped on the right, turn 20 degrees. If left, turn -20 degrees. If both, turn 90 degrees. Resume drive, with slight arc towards the wall.
Dock
onIR() - If the new IR signal is worse than before, attempt to improve it with a binary search. If the IR signal have changed, but are of equal value (such as Red is to Green), attempt to orient the Create back towards the docking station. If the IR signal has been totally lost, set a timer for the RandomWalk fail-safe (cancel the fail-safe if an IR signal is active).
onBump() - (assuming not all three IR signals are active) Back up 50cm. If bumped on the right, turn 10 degrees. If left, turn -10 degrees. If both, turn 45 degrees. Resume drive toward IR.
Remark on IR rankings
The IR signals are ranked as follows (useful for comparing signal improvement):
Force Field = 1.5
Green = 1.0
Green + Force Field = 2.5
Red = 1.0
Red + Force Field = 1.5 // This is a bug, but I am afraid to change it to 2.5 without first retesting!!!!
Red + Green = 2.0
Red + Green + Force Field = 3.0
Results
Given enough time, the Create will eventually find and dock with the charging station. Please note that once the IR has been detected it will take some time before the Create will actually dock. This is because it will (1) take several tries, and (2) will take a while (5 - 15 minutes). The binary search algorithm used to maintain the best IR signal is *very* slow and the Create will pause frequently and run this sequence to maintain the best IR value possible. Please be very patient.
I have observed the Create to fail to dock with the station. The Create will sometimes approach the charging station from an undesirable angle. From this angle, it is possible for the bumper to get caught on the charging station. Human intervention is required to remedy the problem.
Overall, while the Create will successfully dock, I feel that my approach is not the best one. I did little to exploit the physical space such as estimating the distance from the charging station given various IR combinations. For instance, it would have been useful to trace along the Red+Green buoy for an optimal approach to the charing station. My binary search to maintain IR signal is also poor in that (1) it takes time and (2) causes the Create to scoot backwards slightly which introduces errors into the binary search.
- Notes On the Test Environment -
My test environment was a living room and dinning room with couch, tables, and walls. The docking station was placed along a wall and free from any immediate obstacles. The walls in the room were white (which affects the wall sensor). Cliff sensors were enabled; I found this was required to account for my carpet depth.