Thursday, November 11, 2004

Uploading to Gmail

I recently signed up for a Gmail account. Normally, I get my mail through my ISP and download it to Outlook, and I want to keep doing this. At the same time, I'd like to have Gmail as a backup and a permanent store that I can access anywhere. There are some tools on the web for uploading your email to Gmail, notably GMLW. However, none of them work with Outlook, and though there are utilities which will extract from Outlook into a format GMLW can use (e.g. outport, readPST), I have not found them to work very well.

So I am writing some Perl scripts to do this. It's not too hard to read the Outlook mailbox, but there are some suprisingly difficult things, such as finding the email address of the sender, the reply-to address, and determining whether the message is plain text, RTF or HTML. In the case of RTF orHTML, there is also a problem of decoding it from the compressed form that Outlook uses. I've found solutions to most of these problems, through a combination of playing around, porting scripts from other languages (e.g. the RTF decompressor and the HTML-from-RTF extractor), and just picking up tricks here and there (e.g. how to get the SMTP transport headers).

The scripts are not yet ready to use, but I am working on them. Leave a comment if you might be interested.

Monday, October 04, 2004

Line Follower using Navigation

For the final version of the Line Follower control program, I used the Navigator API. The code is here. I like this approach: the code is much simpler and cleaner than the other versions, although it does rely on the calibration parameters being accurate.

One minor problem is this: when the robot needs to turn in order to find the line, it uses the navigator's rotate method. If the turn causes it to pass completely over the line from one side to the other, it will fail to notice that it has done so. I looked at the source code for rotate, and what it does is to calculate how long it needs to run the motors for in order to turn through the specified angle, and then sleeps (using Thread.sleep) until this time has elapsed. So I considered setting up a separate thread which watched the light sensor, and interrupting the sleep if this happens. If the sleep call in rotate is interrupted, it just stops the motors.

In the end, I decided this was too much hassle. However, it turns out there is another problem as well. The TimingNavigator class maintains an instance variable (called angle) containing the current angle. The rotate method updates this to the target value, i.e. the current value plus the rotation, before starting to run the motors. So if the thread is interrupted, angle will contain the wrong value.

A possible improvement to the class would be to update angle to the actual angle, based on when the thread was interrupted. Another change which might make life nicer would be to have a rotateUntil() method, which rotates through an angle or until some other condition is met. I would prefer this, as it gives you tighter control over how to interrupt the turn, and avoid the overhead of having a separate thread and catching the exception.

Sunday, October 03, 2004

Line Follower robot, version 2; The Calibrator

I recoded the line follower to use behaviors. It doesn't really seem to be an improvement in terms of clarity, though there may be better ways of coding it. Take a look here.

For the next step, I want to try out the Navigator API, in its TimingNavigator version. I will return to this in a later posting. The TimingNavigator takes parameters specifying the time to travel a standard linear distance, and to make a rotation. To help determine these, I wrote a class called the Calibrator. I was also finding myself spending some time setting the motor powers to get the robot to run straight, and finding the sensor thresholds for the light and dark levels. The class includes methods to help determine all of these. See the comments in the code for details. There is also a main method, which allows you to execute each of the tests in turn.

Wednesday, September 29, 2004

Line Follower robot, version 1

I built the LineFollower, using chapter 3 of the O'Reilly book referred to in the previous entry. Here's the first version of the line follower control program. The robot follows a dark line on a white background (e.g. the Lego testpad). If the leaves the line, it turns a bit to the right looking for it, and if this fails turns further to the left, then yet further to the right and so on. The decision about whether it is on the line uses some thresholds on the light sensor value, which may need to be changed for different conditions. It works better following a line which is curving to the right because of the search strategy, and sometimes it will get confused and turn right round. I have a short movie of it, but I'm short of web space, so if you want to see it, leave me a comment with your email address.

[Later note: another reason why the robot works better following a right curving line is that the motors appear unbalanced. With the sensor disabled, it tends to curve slightly right. Changing the power setting on the motors helps to fix this, e.g. 8 for motor A and 5 for motor C.]

The style of the program is rather cruddy. It's a very procedural approach. For the next step, I aim to rewrite it using some of the more advanced APIs in LeJos.

Monday, September 27, 2004

Robots (.txt)

A few years ago, I was given the Lego Mindstorms robotics kit. For those of you who don't know, this is a kit for building programmable robots, based on hardware originally developed for teaching at MIT. You get a bunch of Lego pieces including motors, touch and light sensors, gears and the bricks we know and love from when we used to get them stuck in improbable orifices as children. The centerpiece of the kit is the RCX, which contains a microprocessor with a small amount of memory, outputs for driving the motors and inputs for connecting to the sensors. You program it by writing programs on a PC and sending them over an infrared link.

I didn't do very much with the kit when I first got it, partly because there were some faulty pieces (particularly the cable that links the PC to the infrared "tower" used to transmit to the RCX), and partly because I didn't like the visual programming environment that comes with it. I also found the mechanical design of robots very hard. The instructions with the kit do include some examples, but not much guidance on learning how to go about coming up with a design. Maybe it's difficult to teach this.

I recently decided to take another look at it. In the intervening time, someone had written a Java virtual machine for the RCX and created a class library. It's called LeJos. There is even a plugin for my favourite Java IDE, Eclipse. I still haven't found a good source on mechanical design. An O'Reilly book gives some example constructions, though with limited discussion of how to come up with a design. They are at least better than Lego's own rather flimsy designs.

I'm planning to post examples of the code I develop and of the robots themselves over the next few days and weeks. But first, here's a couple of gotchas that I found which held me up.

I use Windows 2000 on an IBM Thinkpad, and at first couldn't get the PC to communicate with the IR tower via the serial port. The first thing to look for is that the serial port (COM1 for me) is enabled in the BIOS. It was, but something else was using it. This turned out to be ActiveSync, the program for connecting to PDAs. ActiveSync starts some kind of service, and this claims any communication devices you've selected for it. As I don't usually use the serial connection to my PDA, I went to the options for ActiveSync and told it not to use COM1. This made the communication to the tower work (you can tell because a green light comes on when data is being sent to it), but the communication from the tower to the RCX still failed. I tracked this down to interference from the Thinkpad's own IR port. Placing something opaque over the port fixed it.

After this, everything worked fine. The Eclipse plugin allows you to download the firmware (the JVM), the write the Java code and download it.

Next time, I'll give an example...