ParLang is a robot programming language based on techniques I developed some years ago at the Edinburgh University Artificial Intelligence Department.
The target application area of the work was robotic assembly. Robotic assembly is subtly different from, say, mobile robotics. In robotic assembly, you always have a very tightly defined goal. The robot is following a sequence of steps each of which must succeed.
Our long term goal was to develop a methodology to simplify programming assembly robots. We hoped the methodology would help the programmer to produce programs which are more reliable and which can encompass wider variations in the assembly task. Our approach to this problem was bottom-up and we started with the lowest layer of the complete system.
Assembly is performed by stringing together a number of behavioural modules. A module can be thought of as a kind of procedure or function. Modules have two important properties:
Pascal distinguishes between statements which do something (for instance, assignment) and statements which make decistions (for instance, if ... then). All our modules do both. In that way, they are more like Snobol statements which always return a status. However, unlike Snobol statements, our modules do not "succeed" or "fail". They are like a function that returns a value: a status code. 'Hopping' returns one of the codes 'fell into a hole', 'hit a wall' or 'hopped too far'. It's up to the calling module to decide what to do next. Success or failure depends on the context, it is not a feature of a module.
Modules can be grouped hierarchically to form new modules. Some of the new modules are specific to a particular assembly, like "insert long contact into base". Others, like Peg-in-Hole, can be reused and are kept in a library of modules.
For a full dicussion of these ideas and to understand the philosophy of Parlang, you should download and read this.
ParLang is a graphical programming language which implements these ideas.
The remainder of this page gives an informal definition of ParLang and shows example programs.
Parlang exists. The diagrams below are real screen shots. However, ParLang only works with a simulated robot, not a real one. You can download a copy to play with.
This program does the following:
Turn on the motor forward and wait for one of:
|Turn on the motor backward and wait for one of:|
No matter how you exit, turn off the motor
A program is a collection of blocks wired together. A block has a single entrance and one or more exits.
Exits can be connected to entrances by plugging the blocks together.
All connections must be downwards; so loops cannot be made.
A collection of blocks can be enclosed in a border to make a block. The block can then be collapsed down to it's simple representation or enlarged to show its contents. "Primitive" blocks cannot be enlarged.
The block can be named: the name is only used in drawing (and saving to a library) and is of no interest to the compiler.
Every block has a "standard" exit. A block can also have other exits defined by the user; if the user doesn't name each exit, the compiler will. When execution runs off the contained blocks into the grey area, then execution continues from the standard exit. Alternatively, a pipe connects the exit of one or more of the contained blocks to a user-defined exit.
A block can contain a finally block. No matter how the block exits, the blocks in the finally will be executed.
Double-clicking in the white border opens up the border and the block will now loop either indefinitely or for a fixed number of times.
The block loops (i.e. is executed again) when all the threads are dead (i.e. have run off into the grey void).
The block exits via an explicit exit or after the specified number of loops. A block which loops indefinitely has no standard exit.
The Repeat Until b > 10 block loops until the condition is true. It then exits via the standard exit. In the example above, a and b must have been declared in an enclosing block.
A For b=10 block loops firstly with b set to 10, then with b set to 9, etc. After it has been exectued with b set to 1, it exits via the standard exit. In the example above, b is declared by the "For b=..." text; a must have been declared in an enclosing block.
The Repeat block repeats until it exits via a user's exit.
Attaching several blocks to the top opens up the border and the block now contains parallel threads. The block exits either when all the threads are dead or when there's an explicit exit (which always kills all the other threads). A thread is dead when it runs off into the grey void.
Only blocks which are attached to the top are executed.
There is no way to connect an explicit exit to the standard exit (but you could put this block inside a surrounding block which connects the exits that way.)
In a block such as:
when execution runs off the exits of both C and E, both thread terminate and the block exits via the standard exit. When execution runs off the exit of D, all threads are terminated and the block exits via the second exit.
However, the following block can never terminate via the standard exit:
When the left thread terminates, the block waits for the right thread. But when the right thread terminates, the block terminates via the second exit.
The rule is: in a parallel block, if any of the threads can only exit via a non-standard exits then the standard exit can never be reached.
A block can both loop and contain parallel threads. When an explicit exit occurs, all the contained threads will be terminated including loops and other parallel blocks. The Finally blocks of the contained blocks will be executed.
The following program is illegal:
A is connected to C. So C is run in thread A. C cannot also be connected to B because C would have to be able to run in two threads at the same time. Due to limitations of the PIC chip, every block can only be run in one thread. So threads cannot converge into a single block inside a par block. However, they can converge on an exit because an exit always kills all the threads in the block:
The user can define a block then name it and save it to the library.
There is also a textual form of the language. It's too
complicated to describe here. Email me if you're keen.
Double-clicking on the blue border reveals the variable and parameter declarations:
Ton and Toff are parameters. The expression of the right of the declaration is the actual value of the parameter. The compiler knows they are parameters because they appear in the title of the block. The expression may not be blank.
A is a variable. The expression of the right of the declaration may be blank.
Parameters are be displayed in the compact version of the block:
An actual parameter value is any expression and may include variables and parameters from the immediately enclosing block.
If the actual parameter is the name of an external variable then the variable will be passed by reference. If the actual parameter is any other expression then the value of the expression will be calculated on block entry:
The name of the block ("Motor_on_Ton_off_Toff_sec_1") is distinct from the title ("Motor on Ton off Toff sec"). There may be several copies of the block which have the same title but all blocks must have different names.
Bitmap file names are allowed in a title. The title
(bmp=cwmotor.bmp) M1 forward
is displayed as:
A saved block can optionally contain a single "container" block. This is an empty block. When the user loads a block from the library, the "container" block becomes the void in the centre of a Repeat block:
The repeat_for_10_sec block could be:
Questions or comments ? E-mail me at firstname.lastname@example.org
No part of this web page may be reproduced in any form or by any means, including photocopying and recording, for any purpose without the express written permission of Analogue Information Systems Ltd.
This web page is copyright © 2008 Analogue Information Systems Ltd., 1 Warrender Park Crescent, Edinburgh EH9 1DX, Scotland, UK, Tel: +44 (0) 131 228 6008. All Rights Reserved