Firstly, to explain this post to the outside world; CSCS (Cool Stuff in Computer Science) consists of a group of students at the University of Kent who gather to do interesting things involving Lego Mindstorms, occam and other things in the vague subject area. It’s organised mostly by four post-graduate students; Matt, Christian, Brad and Damian, who make everything happen. Also of note is that Matt & Christian wrote the Transterpreter, which is the occam runtime we use on the Lego (which also runs on other interesting things), and also the library we use to make the occam talk to the Lego (along with contributions from another post-graduate student, Adam, from the looks of the file).
Over the last 5-6 weeks, we’ve been working with the Lego Mindstorms and controlling them with code written in the parallel computing language occam, which has proven to be an interesting experience. After the first week, where parts lists were used to gather together the sets for use, we started on the building and coding in week 2. The group I’m in chose to build a wheeled platform, and more specifically a traditional four-wheeled chassis. For drive, we chose to use the rear axle, leaving us the front axle for steering. In the first week we managed to build the chassis and drive-train, and get the initial occam code provided to work, which simply turned all of the attached motors infinitely.
In the second & third weeks we chose to work on the steering, which uses a traditional rack & pinion layout. Initially this posed some problems with construction, which were overcome through the inventive mounting of a motor to power the steering. Once the build was complete, attention turned to the code to take care of the steering rack, and make it move in some controlled and useful way. This was done by simply making the motor turn for a fairly short period of time, then leaving it alone, causing the robot to move around in circles on the floor. This revealed issues with the theoretical approach we had taken to handling the steering, in that real-world movement and play in the wheel position caused the steering to become inaccurate and unable to recover to a given position.
Work with this set-up has continued until recently, with the rotation sensor being introduced as a potential solution to the steering problems we are encountering, and provoking thought on the issue of fully utilising occam’s parallel nature in approaching the problem. This kind of approach seems to involve developing procedures to watch the rotation of the axle independent of the main program, which run in parallel, and send messages through channels to other procedures that can adjust the steering constantly, so that at a base level the robot abstracts issues with the robustness and stability of lego through the code, and the other pieces of code can use a fully theoretical model for their steering actions, regardless of the abilities of the lego. (I think I explained that right, although there are still aspects that may be incorrect or ill-conceived due to the idea not having been implemented yet).
Another recent development, has been the addition of a bump sensor to the front of the robot to direct when we have run into a wall. This was mostly a diversion to keep us occupied while a nice interface to the lego rotation sensor makes its way into the
legolib.occ library we use for abstracting away the direct control of the Mindstorms’ inputs and outputs. (We know the details of how the rotation sensor works, in terms of using another set of methods in the library to control it, but preferred to wait until those armed with more knowledge than us tackled the problem). The bump sensor required some innovative mounting to avoid breaking the structure when it collided, but once a suitable mount was created, the issue returned to code. At this point the code is current, and can be seen below:
#INCLUDE "legolib.occ" PROC chdirOnBump (CHAN BYTE speedA, dirA, CHAN BOOL bumpA) BOOL hasBumped: BOOL isOddBump: SEQ isOddBump := TRUE dirA ! FWD speedA ! FULL WHILE TRUE SEQ bumpA ? hasBumped IF isOddBump = TRUE SEQ dirA ! HALT isOddBump := FALSE isOddBump = FALSE SEQ dirA ! FWD isOddBump := TRUE : PROC main() CHAN BYTE speedA,speedB,speedC: CHAN BYTE dirA,dirB,dirC: CHAN BOOL bumpA: PAR motors.speed(speedA,speedB,speedC) motors.dir(dirA,dirB,dirC) bump.sensor(SENSOR.A,bumpA) chdirOnBump(speedA, dirA, bumpA) :
Disclaimer: I’m writing this up almost a week and a half after the last time I hacked on that code, and I’m not sure what state it was in last time it was being worked on. It looks reasonable to my (untrained) eye.
Basically the code has four procedures that run in parallel, 2 that control the motor’s speeds and directions, one that operates the bump sensor, and one that waits for the bump sensor to detect something and takes action upon it happening. The procedure is there because it means we can take action following a bump without locking all of the other processes, and that code can keep running independently of everything else. It uses a simple boolean value to switch from one behaviour to another on subsequent bump events, and is generally meant to change the direction. The code is just an experiment at this point, and is not really to a standard where we’re ready to move on and build upon it with other functionality.
To round up this entry with the rest of the material, and to clarify a few points referenced within this entry, I’ll include random pieces of information about how we’ve been doing this.
For the development environment, we use a package prepared by the post-graduate students who created the occam runtime that we use on the Mindstorms (which also works in other cool places except lego), which bundles jEdit with an occam syntax and indentation module, and an extra plug-in which provides compilation and upload to lego facilities for the programs we write. Although there are some minor inconveniences (not prompting to save before compiling caused a few 5 minute confusion sessions in tracking down non-existent errors), the solution as a whole works really well, and allows you to focus on your code rather than any other technical issues in the implementation. It provides a rapid code → compile → test cycle, with rapid turnover, and although there is a slight delay in uploading the program & runtime to the Mindstorms (which is soon to be fixed in upcoming revisions of the plug-in), that time has often come in handy for running an eye over the code pre-execution to catch any glaring mistakes in the code.
Within the code, we include a file called
lego.occ), which provides us with very handy abstractions around the major components within the Mindstorms environment. This library has grown over time, and makes getting started very simple (even for people with no previous occam experience, like me), it is also relatively compact and short piece of code, which makes it a useful tool for learning some of the techniques to use in occam, and also how to interact with the pieces themselves.
Both the development environment and
legolib.occ were made available from the Transterpreter website for us, and things like the sources for the jEdit plug-in have additionally been made available to us recently. Thanks to Christian I managed to get a nice editing environment for occam on my laptop, so that should be useful when I come to hack on some more code later this week. I think that’s about all for now, this was a pretty wordy post and its length probably makes reading it from end to end an exercise in extreme time-wasting. Hopefully future updates should be more “oh look we did this” instead of short novels, and maybe there’ll even be visuals, who knows.