The Aseba language (up to version 1.1)

This help is also available within Aseba Studio in the Help->Language menu. When using technical words, these are linked to the corresponding Wikipedia article. You might also want to read the concepts page first. The page presents the language as of version 1.1 of Aseba and earlier, for later versions, please read this page.

The Aseba language resembles Matlab (a common scientific programming language); this similarity allows developers with previous knowledge of some scripting language to feel quickly at ease with Aseba and thus lowers the learning curve. Semantically, it is a simple imperative programming language with a single basic type (16 bit signed integers) and arrays. This simplicity allows developers to program behaviours with no prior knowledge of a type system, integers being the most natural type of variables and well suited to programming microcontroller-based mobile robots.

Comments

Comments allow to add information that is ignored by the compiler. Comments are very useful to annotate your code with human-readable notes or to temporary disable some code. Comments begin with a # and terminate at the end of the line.

Example:

# this is a comment
var b    # another comment

Comments spanning several lines are also possible. They begin with #* and end with *#.

Example:

#*
this is a comment spanning
several lines
*#
var b    # a simple comment

Variables

Variables refer either to single scalar values or to arrays of scalar values. The values are comprised between -32768 and 32767, which is the range of 16 bit signed integers. You can access array elements using the usual square parenthesis operator; array indexes begin at zero. You must declare all user-defined variables at the beginning of the Aseba script before doing any processing.

Example:

var a
var c[10]
var b = 0
var d[3] = 2, 3, 4

Events

Aseba is an event-based architecture, which means that events trigger code execution asynchronously.
Events can be external, for instance a user-defined event coming from another Aseba node, or internal, for instance emitted by a sensor which provides updated data. The reception of an event executes, if defined, the block of code that begins with the onevent keyword followed by the name of the event; the code at the top of the script is executed when the script is started or reset. The script can also send events by using the emit keyword, followed by the name of the event and the name of the variable to send, if any. If a variable is provided, the size of the event must match the size of the argument to be emitted. Events allow the script to trigger the execution of code on another node or to communicate with an external program.

To allow the execution of related code upon new events, scripts must not block and thus must not contain any infinite loop. For instance in the context of robotics, where a traditional robot control program would do some processing inside an infinite loop, an Aseba script would just do the processing inside a sensor-related event.

Example:

var run = 0

onevent start
run = 1

onevent stop
run = 0

onevent ir_sensors
if run == 1 then
    emit sensors_values proximity_sensors_values
end

Expressions and Assignations

Expressions allow mathematical computations and are written using the normal mathematical infix syntax. Assignations use the keyword = and set the result of the computation of an expression into a scalar variable or an array element. Aseba provides several operators. Please refer to the table below for a brief description, as well as for the precedence of each operator. To evaluate an expression in a different order, you can use a pair of parentheses to group a sub-expression.

Precedence Operator Description Associativity Arity
1 () Group a sub-expression unary
2 * / Multiplication, division binary
% Modulo binary
3 + - Addition, subtraction binary
4 << >> Left shift, right shift binary
5 | Binary or Left associative binary
6 ^ Binary exclusive or (xor) Left associative binary
7 & Binary and Left associative binary
8 - Unary minus unary
9 ~ Binary not unary
10 abs Absolute value unary
11 = Assignment binary
|= ^= &= Assignment by binary or, xor, and binary
~= Assignment by binary not binary
*= /= Assignment by product and quotient binary
%= Assignment by modulo binary
+= -= Assignment by sum and difference binary
<<= >>= Assignment by left / right shift binary
++ -- Unary increment and decrement unary

The assignment by versions of the binary operators work by applying the operator to a variable and storing the result in this same variable. For instance, A *= 2 is equal to A = A * 2. These short-cuts aim at making the code more readable.

Example:

a = 1 + 1
# Result: a = 2
a *= 3
# Result: a = 6
a++
# Result: a = 7

b = b + d[0]
b = (a - 7) % 5
c[a] = d[a]

Conditionals

Aseba provides two types of conditionals: if and when. These consist of a test of conditions and blocks of code. The test consists in comparisons, optionally grouped using the and (logical conjunction), or (logical disjunction), and not (logical negation) operators, and parentheses.
A comparison consists of an operator and two operands, and can either be true or false. The operands can be arbitrary expressions. The following table lists the comparison operators.

Operator Truth value
== true if operands are equal
!= true if operands are different
> true if first operand is strictly larger than the second one
>= true if the operand is larger or equal to the second one
< true if first operand is strictly smaller than the second one
<= true if the operand is smaller or equal to the second one

Both if and when execute a different block of code according to whether a condition is true or false; but when executes the block corresponding to true only if the last evaluation of the condition was false and the current one is true. This allows the execution of code only when something changes. The if conditional executes a first block of code if the condition is true, a second block of code to execute if the condition is false can be added using the else keyword. Furthermore, additional conditions can be chained using the elseif keyword.

Example:

if a - b > c[0] then
    c[0] = a
elseif a > 0 then
    b = a
else
    b = 0
end

if a < 2 and a > 2 then
    b = 1
else
    b = 0
end

when a > b do
    leds[0] = 1
end

Here the when block executes only when a becomes larger than b.

Loops

Two constructs allow the creation of loops: while and for.

A while loop repeatedly executes a block of code as long as the condition is true. The condition is of the same form as the one if uses.

Example:

while i < 10 do
    v = v + i * i
    i = i + 1
end

A for loop allows a variable to iterate over a range of integers, with an optional step size.

Example:

for i in 1:10 do
    v = v + i * i
end
for i in 30:1 step -3 do
    v = v - i * i
end

Subroutines

When you want to perform the same sequence of operations at two or more different places in the code, you can write common code just once in a subroutine and then call this subroutine from different places. You define a subroutine using the sub keyword followed by the name of the subroutine. You call the subroutine using the callsub keyword, followed by the name of the subroutine. Subroutines must be defined before they are called. Subroutines cannot have arguments, nor be recursive, either directly or indirectly. Subroutines can access any variable.

Example:

var v = 0

sub toto
v = 1

onevent test
callsub toto

Return Statement

It is possible to early return from subroutines and stop the execution of events with the return statement.

Example:

var v = 0

sub toto
if v == 0 then
    return
end
v = 1

onevent test
callsub toto
return
v = 2

Native Functions

We designed Aseba script to be simple so as to allow a quick understanding even by novice developers and to implement the virtual machine efficiently on a micro-controller. To perform complex or resource consuming processing, we provide native functions that are implemented in native code for efficiency. For instance, a native function is the natural way to implement a scalar product.

Native functions are safe, as they specify and check the size of their arguments, which can be constants, variables, or array accesses. In the latter, you can access the whole array, a single element, or a sub-range of the array. Native functions take their arguments by reference and can modify their contents but do not return any value. You can use native functions through the call keyword.

Example:

var a[3] = 1, 2, 3
var b[3] = 2, 3, 4
var c[5] = 5, 10, 15
var d
call math.dot(d, a, b, 3)
call math.dot(d, a, c[0:2], 3)
call math.dot(a[0], c[0:2], 3)
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License