Robot Control Meta Language (RCML)

2.1 Language Alphabet and the Use of Characters

RCML language alphabet comprises:

  1. Symbols used to compile identifiers
    • Latin lowercase or uppercase characters;
    • Arabic numerals 0 to 9;
    • Underscore character «_»;
  2. Separator characters:
    • Space character;
    • Tab character;
    • Line break characters;
  3. Special symbols – symbols that perform specific functions in construction of various language constructs: + - * / = { } ( ) <> , ; : ~ # @ ! "
  4. Composing characters – a group of characters that are seen by the compiler as a unified whole:  ::  ->  ==  >=  <=  !=
  5. “Unused” characters – characters that are not included in the set indicated above, but, nevertheless, can be used in comments or to set values of the constants and strings;
  6. Reserved words described below.

2.2 Rules for Identifier Compilation

The identifier is the name for program elements (functions, variables, etc.) freely selected by the programmer:

  • The identifier must begin with a letter or underscore character;
  • Numbers can be used in the identifier along with the letters starting from the second position;
  • The characters input are case sensitive when specifying identifiers;
  • Space is a separator and can not be used inside the identifier;
  • Reserved words are not allowed as identifiers.

2.3 General Structure of Programs in RCML

RCML program consists of two key sections: the section of inclusions and the section of functions.

Example of RCML program:

// Section of inclusions
includefunction.rcmlincludeC:/robot/robot.rcml”

// Section of functions
function sum(a, b) {
	c = a + b;
	return c;
}
function main() {
	s = sum(1, 2);
	echo(“sum = ”,s,”\n”);
}

Other RCML program files with the text that should be included in this program may be specified in the section of inclusions. It can be sets of any functions, additional libraries, etc. However, the section of inclusions may be empty as well.

The section of functions starts after the first mention of function keyword. Main program code is specified in the section of functions, which consists of functions. 

By analogy with C and C++ programming languages, execution begins with a function named main, which must be present. This statement refers to executable RCML programs (not libraries). The difference between the library and the executable program will be described later.

2.4 Inclusion of Additional RCML Files into the Program

Additional files of RCML programs are included as follows: each file to be included is written from a new line. Include keyword must be placed in the beginning followed by a path to the file to be included in double quotes through the separating character (for example, space character).

Syntax:

include “path_to_file”

Examples:

includefunction.rcmlincludeC:/robot/robot.rcmlinclude “../libs/robot.rcml

The path to the file to be included can be absolute or relative. In case of a relative path, the compiler first calculates the absolute path to the file relative to the absolute path to the file, where this inclusion structure is found. If the file is not found by the resulting path, the compiler calculates the absolute path relative to each variant of the path from path parameter of lib_search_paths section in config.ini configuration file in the order in which these paths have been specified in the configuration file.

This path parameter from lib_search_paths section of the configuration file is called “default search path”. The syntax for specifying default search paths is as follows:

[lib_search_paths]
path = path_1
path = path_2

The order of inclusion of additional files with the code is the same in which they have been listed in the original rcml file.

Important! If non-empty section of inclusions is found in the file to be included, files from this section will be included in the source file immediately after inclusion of the file (right after the line with include word) where they were found.

The absolute path is calculated for each included file, and files included again with the same absolute path will not be included in the program.

You should understand a mechanism to include additional files in the program. This is analogous to the fact that instead of include structure, the text of the included file is placed in its entirety. The syntax of each file included is checked before inclusion, and the program is compiled taking into account all calculations and optimization only after preparation of the full text of the program considering all the included files.

2.5 Including RCML Library Files into the Program

Additional libraries written in RCML are included as follows: each library included is written in a new line from include_lib keyword in the beginning followed by a separating character (for example, space character), followed by the identifier – library name (to use to apply to the library in the code), and then a separating character and a path to the file with library byte code (pc-file) in double quotes.

Syntax:

include_lib library_name “path_to_library_file”

Example of the program including math library:

include_lib math "../export_library/etalon.rcml.pc"
function main() {
	s = math.sum(1,2);
	system.echo("\n1 + 2 =",s,"\n");
}

The process of creating the library is described in Section "Creating RCML Library File".

Library file search process by the compiler is similar to the search of the file to be included. However, the library code is not included into the executable program code. A link to the library file is created in the executable program, and running such a program will also require the file of the library compiled, as in case of compilation.

You can include the same library file under different names-identifiers. 

It should be noted that libraries can have links to other libraries, i.e., when compiling the library, it is allowed to include other libraries in it.

2.6 Functions

As noted earlier, the executable program that is not a library must always have a function called main (hereinafter the main function). Execution starts from it. It does not matter where the function will be placed: in the source file or in one of the included files. It is important that this function existed and was the only one.

Of course, a programmer can create new functions in addition to main function, with names corresponding to the rules for specifying identifiers, and apply to them both in main function, as well as in the others.

New function is specified starting from function keyword, followed by the name of the function through the separator, and then the list of parameters in parentheses that can be empty. The list of parameters is followed by a function code – a list of its operators in curly brackets.

Syntax for specifying a function:

function function_name(list_of_parameters) {
	list_of_operators
}

Example function:

function sum(a, b) {
	c = a + b;
	returnc;
}

A function in RCML language can either return a value or not return it. Values are returned (similar to exit from function) using return operator. 

It is optional to specify this operator it the end of the function if the value is not returned. If the function does not return the value, then by default the return value is considered to be zero – 0.0.

Function parameter values are always transferred by value, so they can be used as regular variables in a function body without fear of overwriting data in the function where the current one was called from.

The order of the functions with respect to each other is not important and does not affect the scope of their visibility. Each function can be called from any other function, except for the main function. Since execution begins from it, it cannot be called in the code of functions. It is worth noting that a function cannot be declared within the function.

The parameters in the main function (main) have a special meaning, see more in Section "Passing parameters to the RCML program"

2.7 Comments

Single- and multi-line comments are available in RCML. Single-line comment begins with double forward slash // and follows until the end of the line.

Example:

//This is a comment

Multi-line comments begin with a combination of characters /* and continues to the following combination of characters */

Example:

/* This
is a multi-line
comment */

2.8 Data Types

Explicit and implicit data types are available in RCML. The first group includes those data types with variables which can be created and used in various operations. The second group, on the contrary, includes variables which can not be created, but these data types may appear in some implicit operations, or they can be used as parameters for specific functions. Data type for connection with the physical robot is set aside from this classification.

It should be noted, that at this stage of RCML development, other data types, including arrays are not yet provided.

2.8.1 Explicit Data Types

There is only one explicit data type in RCML – the real numbers. All generated variables used in the operations, parameters and return values of user-defined functions, and also of all functions of modules and robots are the real numbers.

2.8.2 Implicit Data Types

Logical and string types are implicit data types in RCML language.

Data used in calculation of logical expressions are forcibly converted to the logical data type.

String data type is used only to specify string constants that can be parameters for the system-level functions (RCML system functions, functions of robot modules and functional modules). A string constant is a sequence of any characters enclosed in double quotes, while the following control character sets can be specified in a string constant, deemed a single character:

  • \n – word wrap;
  • \” – inserting the double quote character;
  • \\ - inserting a backslash.

2.9 Variables

A variable in RCML language is initialized when you first assign it a value, and it remains visible from the point of initialization to the end of the function body where it is used. A single character “=” is used to assign a value to a variable. Constant values, results of expressions and function calls can be assigned to variables. A variable can be transferred as argument to the function. Variables that are the parameters of the function are initialized when transferring of execution to this function.

Example of using variables in a function:

function sum_by_abs(a, b) {
	c = a + b;
	if (c < 0) {
		с = -с;
	}
	return c;
}

There are no global variables in RCML.

The programmer may not take care of memory consumption, and may not delete the variables used when they are no longer needed. The compiler takes care of it in optimizing the resulting byte code, calculating the life paths of each variable. However, this does not apply to specific variables related to the physical robots.

2.10 Expressions and Operations

Expressions in RCML can consist of numeric constants, variables and returned function results that can be used as operands of the mathematical and logical operations as part of the expression. Operations, in turn, may be unary or binary. Priority of operations in expressions is given in parentheses, just as it is in mathematics. The result of the expression can be assigned to a variable or transferred as a parameter to a function. It is possible for those function parameters that work with these data types. Using special variables to communicate with a robot in the context of expressions is prohibited at the level of syntax rules.

Example expressions:

a = 1 + 1;
a – 5;
c = a * b;
d = sum(a, с) * 10 * (a / c);
e = -d + 15;
f = d >= 10;
!f;

2.10.1 Mathematical Operations

The following binary mathematical operations are available in RCML:

  • «+» - addition operator;
  • «-» - subtraction operator;
  • «*» - multiplication operator;
  •  «/» - simple division operator;
  •  «%» - taking remainder of division operator.

And one unary operation:

  • «-» - sign change.

2.10.2 Logical Operations

The following binary operations from logical operations are available in RCML:

  • «==» - checking equality;
  • «!=» - checking inequality;
  • «>=» - checking greater than or equal to;
  • «<=» - checking less than or equal to;
  • «>» - checking greater than;
  • «<» - checking less than;
  • «&&» - conjunction, AND operation;
  • «||» - disjunction, OR operation.

And one unary operation:

  • «!» - logical negation.

2.11 Converting Data Types

By using different types of operations in one expression, expression result data type is implicitly converted to the expected type of the operand of the next operation. The result will be real if it is saved in a variable or transferred as a function parameter, or strictly logical if it is used in a conditional operator.

The following rule applies when converting real type into logical type: 

if the element is not zero, then the result is true, otherwise – false. 

The following rule applies in reverse conversion:

if true, the result is 1.0, if false, the result is 0.0.

2.12 Control Structures

RCML provides a standard set of structures affecting the progress of the program execution. They can be divided into conditional, cyclic and unconditional.

2.12.1 Conditional Control Structures

RCML has only one conditional transfer operator – if. Its syntax is as follows:

if (expression) {
	//set of operators, if the result of expression is true
} else {
	// set of operators, if the result of expression is false
}

The result of expression in parentheses is reduced to a logical type, and if the result is true, then the first block of operators in curly brackets is executed, otherwise – the second block of operators following else keyword. The second block of operators with else keyword can be omitted when specifying a conditional operator.

2.12.2 Cyclic Control Structures

Cycle (loop) operator in RCML is also unique. It is loop operator. It is a simplified cycle operator in comparison with similar operators in traditional programming languages. It is unconditional, and its block of operators will be executed endlessly, unless it has an appropriate exit structure with prerequisite or without it. The syntax of loop operator is as follows:

loop {
	// set of loop operators
}

2.12.3 Other Control Structures

Other control structures in RCML are operators of unconditional transfer. When reaching them, the program goes to a particular section.

The operator of transfer to the beginning of the cycle – continue. When it is reached, the program goes to the beginning of the current cycle. It is used without parameters.

The operator of loop exit – break. When it is reached, the current loop is interrupted. It is used without parameters.

The operator of function exit – return. It may be used both with an expression, and without it. In the first case the result of the function will be the result returned by the expression. In the second case, the function will return the default value of 0.0.

The syntax of return operator with expression return:

return expression;

Without expression return:

return;

Examples of return operator:

return 2+2; //function exit with expression return
return; // function exit without expression return

If a return operator is specified in the main function, its implementation will lead to termination of the RCML program, and the value passed via this operator will be passed to the OS as the program exit status. However, the passed value will be rounded to integer by dropping the fraction part.

The operator exiting the program – exit. When it is reached, the program stops executiong regardless of function where it is specified. This operator (like return) may be called both with an expression, and without it. In the first case, the result of the expression is returned to the OS as the exit code of the program, in the second case the exit code of the program is considered to be equal to 0.

The syntax of exit operator with expression return:

exit expression;

Without expression return:

exit;

2.13 Exceptions

In RCML, it is available to handle exceptions occurring in a particular block of code, as in some other programming languages. General type of exception handling structure begins with try operator, then it is followed by a block of operators, where an exception can occur in execution of the operators of this block, then it can be followed by catch operator, and a block of operators to be executed in case of an exception. General type of exception handling structure is as follows:

try {
	//block of operators, where an exception can occur
} catch {
	//block of operators to handle the case with an exception
}

When an exception appears in try block, the program goes to catch block operator. It should be noted that catch operator and its block may be omitted, and then the program goes to the operator following the block of try operator. Exception handling structure may be nested in another one, and, in case of an exception, it will be handled by the current structure.

Exceptions may occur when executing various functions provided by external or system RCML modules, such as function modules or robot modules, but an exception can be called manually using throw operator. When executing this operator, an exception will immediately be thrown.

Work of the mechanism of exceptions as an example of a simple program for division of numbers:

function main() {
	try {
		echo(“this simple division program\n”);
		echo(“c = a / b \n”);
		try {
			echo(“input a\n”);
			a = input();
			echo(“input b\n”);
			b = input();
			if (!b) { // if b is zero, division cannot be executed
				throw; //throw an exception
			}
			c = a / b;
			echo(“c = ”, c, “\n”);
		} catch {
			echo(“b is zero!”); //exception will be handled in this block
		}
	} catch {
		//this block will never be executed
	}
}

However, in RCML, focused on robotics, unlike other programming languages, try operator can have parameters that specify exactly how it should work. The first parameter of try operator is a string constant specifying the mode of operation. The second parameter of real data type may be given depending on the specified mode.

Try operator has three modes of operation:

  • “error_default” – default mode of operation as a common try operator. In this case, the second parameter is not specified. If the parameters of try operator are omitted as in the above example, then try operator operates in this mode.
  • “error_time_limit” – mode of operation with a countdown of time limit in which a block of code of try operator should be executed. In this case, the second parameter is given to specify the number of milliseconds limiting execution of the block of code of try operator. If this block is not executed within the specified time, an exception will be thrown. If an exception is thrown earlier, the countdown will be stopped, and the exception will be handled normally.
  • “error_try_count” – mode of operation with a count of the number of attempts to execute the block of try operator. In this mode, the second parameter takes a number of allowed attempts to execute the block. In each thrown exception, the count of the number of attempts in try operator block will be reduced by 1, and if it reaches zero, the exception will be handled normally.

Despite the fact that try operator may take the parameters, it is not a function and does not returns a value.

Example of using the above modes to handle success of robot performance of its function giving it three attempts with a time limit of 2 seconds for each:

try(“error_try_count”, 3) {
	try(“error_time_limit”, 2000) {
		robot->do_something();
	} catch { //if time is out
		throw; //then throw an exception to end the attempt
	}
} catch {
	//this block is executed when all attempts are ended 
	//with no result obtained
}

Using the throw operator, the exception may be used for passing some value (exception value). In this case, the syntax of the throw operator will be the following:

throw expression;

For processing the value of the thrown exception, the try operator will have a slightly different syntax: the parameters of the catch operator should specify the identifier, i.e., the name of the variable to which the exception will be written:

try {
	//the block of operators in which the exception may occur
} catch (variable_name) {
	//the block of operators for handling an exception
}

If at the time of exception the specified variable does not exist, it will be created, otherwise it will be overwritten.

try {
	throw 3;
} catch (E) {
	system.echo(“E = ”, E, “\n”); //will show E = 3
}

The variable, to which the value of the exception will be written, will be available in the catch block and beyond it till the end of the function.

An example of creating the variable:

system.echo(“E = ”, E, “\n”); //error E does not exist yet
try {
	throw 3;
} catch (E) {
	system.echo(“E = ”, E, “\n”); //will show E = 3
}
system.echo(“E = ”, E, “\n”); //will show E = 3, since E has been created in the catch block

An example of overwriting the value:

E = 5;
system.echo(“E = ”, E, “\n”); //will show E = 5
try {
	throw 3;
} catch (E) {
	system.echo(“E = ”, E, “\n”); //will show E = 3
}
system.echo(“E = ”, E, “\n”); //will show E = 3

In this way it is possible not only to process exception values passed via the throw operator, but also to process exception values passed from functions of robot modules and functional modules, and libraries.

Example:

try {
	robot_test->throw_value(10);
} catch (E) {
	system.echo(“E = ”, E, “\n”); //will show E = 10
}

If the thrown exception has not been intercepted in the RCML program, the RCML program will terminate with code 1, i.e., an error, which may be a communication tool between the OS and the RCML program (read more in Section "Communication with the OS"). In this case, the value of the exception will be lost. 

2.14 Calling Functions

RCML language functions can be internal or external.

Internal functions refer to the functions described in RCML language in the current file of program source code or in included files with the source code in RCML. The code of these functions is within the current program and will be compiled into an executable file of the current program.

External functions refer to the functions of RCML libraries already compiled, linked to the current program or the functions of functional modules, i.e., the code of these functions is outside the current program in RCML.

Syntactically, internal functions in RCML are called in the same manner as in other programming languages. You must first specify an identifier – the function name, and then a list of arguments given to it in parentheses:

identifier(argument1, argument2, argument3)

The result of any function call can be assigned to a variable or used in the expression. It should be noted that in the function call, all parameters specified in its description should be transferred through arguments, except for some RCML system functions.

Calling an external function has a different syntax:

source_name.function_name(argument1, argument2, argument3)

An identifier (name) of the library linked from the section of inclusions is used as the source name, or the name of the function module specified in the configuration file. Description of names and arguments of external functions can usually be found in the documentation for the respective source – the library or function module.

It should be noted that when searching for the external function, the desired source is in the first place sought among linked libraries and then among linked functional modules. If the source is found, the desired function is sought in it by name, if the function is found, the number of function parameters declared in the source is checked against the number of arguments transferred by the user. If the number of arguments and parameters is the same, it is believed that the desired function is found. In any other case, an error is issued.

RCML has system module, always available in the program and providing system functions of RCML language. If this name is specified as the source of external functions, the function is searched directly in this module, ignoring the libraries with the same name.

2.15 System Functions in RCML

System functions in RCML are available in RCML environment via system module. These functions are accessed in the same way as the external functions of the module, specifying “system” name.

The system module has the following functions:

  • system.input – a function of reading a number from a string resulting through standard input. The line read should consist of digits and optionally of the sign + or -. Then, it is converted to a number, which is returned as a result of function call. This function has no parameters.
  • system.echo – a function of data output transferred as arguments to the standard output. It can have any variable number of parameters including the numbers and string constants.
  • system.set – a function of change in RCML environment system parameters. It has two arguments: the name of a system parameter and its new value. The name of a system parameter is defined by a string constant, and the new value of this parameter depends on the system parameter specified. Now there is only one system parameter in RCML environment:
    • “behavior” – function execution behavior by default. The second parameter is the mode flag, character ~ or #. See Section "Batch Data Transmission to Robots" for details about execution modes.
  • system.sleep – a temporary pause in the program execution process. It has one numeric parameter – the pause time in milliseconds.
  • system.hand_control – enabling manual control for a robot. This function transfers the robot in hand control mode by the said control module. Execution of the main program for the period of hand control is suspended. This function has a variable number of parameters:
    • First parameter – a special variable associated with the appropriate physical robot. Mandatory parameter;
    • Second parameter – a string constant – control module name. Mandatory parameter;
    • Third parameter – a string constant - robot axis;
    • Fourth parameter – the name of control device axis as a string constant or an expression that will set the values for robot axis specified in the previous parameter.
    • Fifth and sixth, seventh and eighth, etc. parameters are always set in pairs: robot axis and the source of values for it.
  • system.send_package – a command to send the accumulated command package to robots. The only parameter is the flag for the mode of execution of commands from the package, ~ or #. Read more about this function in Section "Specifying Function Execution Modes".

2.16 Macros

RCML supports macros. A macro is a combination of an identifier – macro name – random text –macro contents. The macros are declared in the section of declarations by define keyword, followed by a separator, followed by an identifier (macro name), a separator again and macro text.

Macro syntax:

define macro_name macro_contents

All occurrences of the macro name in the text of the section of functions will be replaced by its contents. After defining a macro can not be re-defined by other macros.

The macro content includes any text between the separator character following the macro name and the line end. Macros can have multi-line content (use «\» character, i.e., shield the line end, as it is done in multi-line macros in C++). Then the macro content will be considered as the text until the end of the line following the line ending with this character. Line feed characters in multi-line macros are preserved.

Example use of macros

define ONE 1
define TWO 2
define TREE ONE + \
TWO
define TEST_MS "test message"

function main(){
	system.echo("1 = ",ONE,"\n");
	system.echo("2 = ",TWO,"\n");
	system.echo("3 = ",TREE,"\n");
	system.echo("Test print > ",TEST_MS,"\n");
}

This text after macros processing will be converted to the following text:

function main(){
	system.echo("1 = ",1,"\n");
	system.echo("2 = ",2,"\n");
	system.echo("3 = ",1 + 
2 ,"\n");
	system.echo("Test print > ","test message","\n");
}

The resulting text will already be compiled into the byte code. The result of this program will be as follows:

1 = 1.000000
2 = 2.000000
3 = 3.000000
Test print > test message
Important! It is dangerous to use macros, which recursively refer to each other. In this case, an infinite recursion occurs, which will cause the compiler crash. At this stage of language development, closed recursion in macros cannot be found.

Example closed recursion:

define ONE TWO
define TWO ONE

Address:

12, Monastyrskaya St., lit. A,
Office 600, Perm, Russia

Phone:

+7 (342) 214 01 84

E-mail:

info@robotct.ru