Saturday, June 14, 2008

The snake wins me over

It has been an interesting day today - exam study combined with robot-related diversions that lead to the altering of two fundamental components of the robot.

As already mentioned, I initially started this project wanting the focus to be on developing light-weight effective vision-based algorithms (keeping my expectations to a minimum...)

I wanted to quickly develop a basic and robust platform that could handle a large range of programming ideas quickly. As part of this I devised an - in theory - fairly cross platform motor-control circuit based on a keyboard's caps/num/scroll-locking LEDs (described in articles below). Testing with the power of my index finger on the Caps-Lock key, I was able to reach a fairly high rate of switching, surely enough to form a rudimentary PWM system for the robot's motors.

Inline with my cross-platform ideals, I chose Java as my programming language, primarily due to its Toolkit method setLockingKeyState() for controlling the keyboard's LEDs. Also influencing this decision was a cross-platform (Windows/Linux) Serial IO class included in the CMUCam demo files.

Cobbling these together, I created my first Java application for the robot, implementing some very rudimentary functionality - the tracking of a big red box on a very not-red background. This worked, as described in the preceding article, the robot was able to lock onto the box's location. Unfortunately, a glaring problem quickly appeared - related to how Java implements the setLockingKeyState() method. This method is part of the Java GUI, Sun accompanying the method description with the following note (see here):

Many GUI operations may be performed asynchronously. This means that if you set the state of a component, and then immediately query the state, the returned value may not yet reflect the requested change.

This is certainly a bit of an understatement. The setting of the LED's current state via setLockingKeyState() virtually never reflects the LED's actual state, so the robot will occasionally just "bolt for the door" after turning "off" the LEDs, or just not move at all when told to turn etc.

This lead me to a dilemma. Along with the reasons stated above, I chose Java for its platform independence, and relative high-level programming methodology. I wanted to develop an aspect of the robot's programming on my desktop pc in Windows, test it in Windows, pop the file on a USB stick and run the code instantly on the robot for final debugging. I did not want to be altering the code per OS or hardware architecture. The speed of the program was (at the moment) not the most important thing, I just wanted rough results for my ideas in a short time-frame. On top of the keyboard LED problems, I was having problems with the Serial IO class, as I was taking it well beyond its initial specification (primarily in the areas of parsing input and timing).

These shortcomings, along with the amount of time spent debugging vs developing let me to the conclusion that I now had to try another programming language.

After much arm-waving, a possible solution hit me. I had used Pyro (Python Robotics) a couple of years ago to play with some simple neural-network ideas i'd had. Whilst not wanting to use the full Pyro system (yet), I did enjoy the high-level power of Python, and 10MB later, I was in business. In just 1 hour, the entire demo application that had taken me days to develop in Java (primarily messing with Serial comms) was recreated in Python. A fantastic side effect of the swap to Python is that swapping from Windows to Linux requires virtually no changes - just a change of the port label from "COM1" to "/dev/ttyS1" is all that is needed.

Naturally, there were problems. I was unable to find (so far) a method of altering the keyboard LEDs, so aside from the easy and robust cross-platform rs232 comms, I had hardly progressed. This lead me to google, which lead me to this.

Now came the second big change. Windmeadow's idea had me dump the keyboard-controller based interface, in favour of using both the rs232 RTS and DTR pins to control each motor via my second serial port (as a temporary fix at least). Whilst this is something that you could argue that I should have done at the start, I really wanted to use the keyboard io board as it would make use of the robot's unused (during operation) ps/2 port, possibly negating the need for a battery-hungry USB hub.

Regardless, after all this mucking around, I have decided that I will make the best use possible of robust the serial methods in python (via pyserial) and I will upgrade the motor control to an rs232 motor-controller board.

Oh, and despite the hacked nature of the RTS/DTR fix, I used it to attain the same functionality as the keyboard LEDs but with 100% reliability and excellent control. I was able to reliably send pulses to the motor with durations less than 1/10 of a second!

Well, that's it then. My suggestion, if you want to build something quickly that uses a lot of RS232, and does what you want when you ask it, try Python.