November 18, 2002
The Fruits of My Labors

Today at work we posted the beta of the next software release. This is what I've been so busy on lately. I'm pretty invested in this release, as the most significant new feature is the result of the work I've been doing since I started at Evolution seven months ago: A new, relatively easy way to program our robots in C++ and Python.

my friend john

When you hear about robot software, the focus tends to be on two ends of a spectrum. At one end is the subfield of AI known as planning, which in caricature has the goal of building a superbrain capable of general problem solving. You tell it what you want to do (e.g., get to the upstairs bedroom from the downstairs kitchen). It thinks, then spits out a complete and detailed plan for achieving your goal (turn 190 degrees to your right, move forward 3 feet, turn right 90 degrees, move forward 7 feet, turn right 60 degrees, engage stair-climber treads, etc.).

This was the traditional AI approach to robotics for many years. It turned out to have some real drawbacks, however. Coming up with a plan that was detailed enough to be helpful could take a long time, during which the robot might be unresponsive. Then once a plan was ready the dynamic nature of the world soon made it obsolete; "No plan survives first contact with the enemy" is a military saying, but to a robot the whole world is the enemy. People open or close doors, roads get washed out, sensors are inaccurate, and mechanical parts fail. Attempting to create plans that anticipate all possible failures or try to take advantage of new opportunities quickly becomes unwieldy.

fun at the wisconsin state fair

On the other end of the spectrum is Rodney Brooks' subsumption architecture, which was developed as a reaction against the whole symbolic representation and planning approach. Robots are wired with tight feedback loops and little or no internal state. They're like cockroaches, walking nervous systems that rarely do anything optimally but are very robust. Unfortunately it gets very hard very fast to figure out how to program robots in this way to do anything other than simple insect-like behaviors.

Now if chocolate represents a deliberative planner, and peanut butter represents a subsumption architecture, and... well, yeah, you've got the idea. It turned out to work pretty well to glue two software layers together. Except in this case we make it twice as tasty by adding a middle layer of delicious marshmallow-flavor whip, which in the ingredients list shows up as "Sequencer" or "Task Execution System". This third layer, the sequencer, selects which low-level reactive behaviors should be active based on the robot's higher level goals. The three layer architecture has become a popular and successful way of writing robotic software.

The software I wrote is called the Task Execution Layer (TEL), and sits on top of the lower level behavior layer. Writing new behaviors to control the robot is probably beyond most hobbyists, but with the TEL they can write code that looks a lot like a traditional program yet still takes advantage of the supplied library of robust reactive behaviors. (We don't have a planning layer, at least not yet.)

the empty bottle in chicago, one of my favorite bars

Writing C++, however, may be beyond a lot of hobbyists too. And hell, even as a non-hobbyist I'd still prefer to write as little of it as possible. So I developed a Python interface to the TEL.

I should admit I don't really think much of Python. It's ok for what it is, but I don't think it deserves nearly the attention and praise it gets. Until recently I would have said that nobody would write large software systems in Python. It's not particuarly clean or elegant, it's not fast, it's not all that powerful. But it is really easy to learn. And while it loses pretty badly compared to lisp, it's quite nice compared to C++.

Compare C++:

TaskFunctor* Add = TaskRegistry::find_task("Example.Add");
TaskArg add_args[] = { -2.0, 5.0 };
TaskContext* context = TaskContext::task_args(2, add_args);
TaskValue* value = Add->run(context);
if (value != NULL) {
  std::cout << *value << std::endl;
  delete value;
delete context;

To Python:

print ersp.task.example.Add(-2.0, 5.0) is a more complete example that demonstrates simple voice control of a robot.

Lisp would have been a much nicer language in which to implement an interface to the TEL (or even just implement the whole TEL) since what I really wanted to do was either create my own language (as in Jim Firby's RAP system) or extend the host language syntax a bit (as in Erann Gat's ESL). Maybe there will be a lisp interface one day, but I have to admit that while Python was quite easy to extend and embed I don't know of an existing lisp implementation that would have met our technical (native threads, callbacks between languages, embed in shared libraries, support linux & windows) and licensing (must be 100% free) requirements.

Posted by jjwiseman at November 18, 2002 11:55 PM

I don't know of an existing lisp implementation that would have met our technical (native threads, callbacks between languages, embed in shared libraries, support linux & windows) and licensing (must be 100% free) requirements.

You know, there are SBCL and CMUCL developers queuing up for contracts to add features like that. Unless by "100% free" you mean gratis as well as libre; you might have to wait a while longer for that

Interesting article.

Posted by: Daniel Barlow on November 19, 2002 06:04 AM


I think we would have been willing to pay a small licensing/redistribution fee but not to fund (or wait for) development.

Our requirements were pretty specific, and I think we were lucky to find anything that fit that didn't completely suck (though the Python approach to being 'native threaded' is to allow native threads to timeslice into the runtime, not much differently from user-level threads).

The end of my post may sound a little forlorn. Really the impetus was behind Python by the time I got to Evolution, and I was just speculating about what what it would take if I decided to add a lisp interface as a personal project.

Posted by: jjwiseman on November 19, 2002 09:47 AM
Post a comment

Email Address:


Unless you answer this question, your comment will be classified as spam and will not be posted.
(I'll give you a hint: the answer is “lisp”.)


Remember info?