Robot Control Meta Language (RCML)

1 Установка и настройка компилятора и интерпретатораНаверх

1.1 Быстрый старт

Видео-руководство по быстрому старту RCML для Windows

 

Видео-руководство по быстрому старту RCML для Linux

 

Перейдите на страницу проекта на SourceForge по ссылке:

http://sourceforge.net/projects/rcmlang/files/

Из папки нужной Вам ОС скачайте архив с файлами компилятора rcml_build_X.zip и архив с файлами модулей rcml_modules_build_X.zip, где X – версия компилятора. Для этих двух архивов версии должны совпадать.

Распакуйте оба скачанных архива в одну папку.

Перейдите в папку с распакованными файлами и создайте в ней файл config.ini со следующим содержимым:

[robot_modules]
module = test
[function_modules]
[control_modules]
[repository]
[lib_search_paths]

В текущей папке создайте ещё один файл с именем hello.rcml и со следующим содержимым:

function main() {
	robot_test->print("Hello world!\n", 0);
}

Это будет первая Ваша программа на языке RCML, состоящая из одного оператора – вызова функции вывода в консоль строки "Hello world!\n" у тестового виртуального робота robot_test с задержкой в 0 сек.

Для компиляции программы запустите редактор командной строки в текущей папке и выполните следующую команду:

rcml_compiler.exe hello.rcml hello.rcml.pc

В текущей папке появится файл скомпилированной программы hello.pc, как показано на рисунке 1.

Рисунок 1 Результат компилирования программы

Чтобы выполнить скомпилированную программу, выполните команду:

rcml_intepreter.exe hello.rcml

Обратите внимание, что тут не указывается расширение pc у файла скомпилированной программы. Пример успешного выполнения файла показан на рисунке 2.

Рисунок 2 Результат успешного выполнения программы

1.2 Описание процесса подготовки программы на RCML

Написать программу на языке RCML можно в любом текстовом редакторе, сохранив её в обычный текстовый файл с расширением rcml.

Расширение rcml носит рекомендательный характер, на деле файл может иметь любое имя, поддерживаемое файловой системой вашей ОС.

В последующем данный файл компилируется компилятором языка RCML, в процессе компиляции выполняется ряд процедур по подготовке программы к исполнению, а именно:

  • проверка правильности синтаксиса программы;
  • проверка корректности вызовов функций, роботов и передачи параметров;
  • преобразование текста программы в байт-код;
  • выполнение различных модификаций с байт-кодом для ускорения его выполнения и оптимизации использования памяти.

При успешной компиляции программы компилятором языка RCML создается файл с байт-кодом программы, для которого рекомендуется двойное расширение rcml.pc (PCpseudo code). Под файлом с байт-кодом понимается уже бинарное содержимое, по своей структуре близкое к машинным кодам процессора, исполняемое собственной виртуальной машиной в виду некоторых особенностей языка RCML.

Непосредственное выполнение программы выполняется интерпретатором языка RCML, как следует из названия, интерпретирующим инструкции байт-кода посредством внутренней виртуальной машины в реальные команды процессора.

1.3 Установка и настройка компилятора и интерпретатора RCML

Компилятор и интерпретатор можно скачать со страницы проекта на SourceForge:

http://sourceforge.net/projects/rcmlang/files/

Компилятор и интерпретатор представляют собой два исполняемых файла, которые необходимо поместить в одну папку. Дополнительно в данной папке требуется создать текстовый файл config.ini, это конфигурационный файл среды RCML. Конфигурация едина для компилятора и интерпретатора.

Данный файл может содержать следующие секции:

  • [robot_modules] – секция подключения модулей роботов;
  • [function_modules] – секция подключения функциональных модулей;
  • [control_modules] – секция подключения модулей управления;
  • [choice_modules] – секция подключения модулей выбора робота.

Имя подключаемого модуля указывается в свойстве module в секции такого же типа, что и модуль. Если подключаемых модулей одного типа несколько, то на каждый из них отводится отдельная строка. Загрузка модулей определенного типа происходит в том порядке, в котором они были указаны в рамках своей секции.

Пример задания подключаемых модулей в config.ini:

[robot_modules]
module = test
module = tarakan
module = uarm
module = lego_ev3
[function_modules]
module = math
[control_modules]
module = test
module = keyboard
module = gamepad
module = myo
[choice_modules]
module = avg

Для модулей всех типов в папке с компилятором и интерпретатором должны быть созданы папки по названию секции (robot_modules, function_modules, control_modules или choice_modules). Для каждого модуля в соответствующей его типу папке должна быть создана директория с таким же именем, как и имя модуля, далее данная директория будет называться директорией модуля. Сам модуль представлен файлом динамически подключаемой библиотеки, который должен именоваться так же, как и модуль, но с добавлением суффикса module через нижнее подчеркивание. Файл модуля должен находиться в папке модуля. В папке модуля могут находиться прочие файлы, необходимые для работы модуля, например, файлы конфигурации.

Дополнительно в файле config.ini могут быть следующие секции:

  • [statisctic] – данная секция может иметь только одно свойство - db_path – путь к файлу базы данных куда будет записываться статистика выполнения роботами своих функций. Если файла базы не существует, он будет создан. Если база уже существует, то она будет дополнена. Если это свойство будет отсутствовать или будет пустым, статистика не будет записываться.
  • [lib_search_paths] – пути поиска скомпилированных библиотек RCML. В данной секции в свойстве path может быть указан путь по умолчанию где искать библиотеки для RCML. Путей может быть несколько, тогда каждый путь задается через отдельное свойство path. Поиск требуемой библиотеки по указанным путям производится в том же порядке, в каком были указаны пути в данной секции.
  • [locale_settings] – секция настроек текущей локали, может содержать только одно совйство – locale – в котором задаются параметры текущей локали для RCML в виде строки по правилам, принятым в Linux среде. По умолчанию текущая локаль является английской и задается значением en_US.UTF-8.

Например, чтобы переключить текущую локаль на русский язык необходимо указать ru_RU.UTF-8.

Важно! Опция locale_settings поддерживается только в ОС Windows.

Файлы всех поддерживаемых локалей можно скачать из соответствующей директории на официальной странице загрузок проекта на SourceForge:

https://sourceforge.net/projects/rcmlang/files/translations/

О том, как добавить свою собственную локаль в проект RCML можно прочитать на странице репозитория локалей для RCML:

https://github.com/RobotControlTechnologies/RCML_translations

1.4 Подробнее о модулях роботов

Модули роботов занимают одно из ключевых положений в языке RCML, поскольку именно через них осуществляется связь и передача команд физическому роботу, см. рисунок 3.

Рисунок 3 Роль модулей роботов в связи с физическими роботами

Модуль робота отвечает за передачу команд от интерпретатора языка RCML одному или нескольким роботам одного класса (или типа), которые объединены под этим модулем. Рекомендуется для каждого класса или типа робота использовать отдельный модуль. Интерпретатор RCML через задекларированный API устанавливает связь с модулем робота, который в свою очередь устанавливает связь с каждым закрепленным за ним роботом. Таким образом, через модуль робота скрывается реализация связи и управления роботом от интерпретатора, что позволяет подключать к нему самых разных роботов. О том, как написать свой модуль робота и подключить его к интерпретатору, читайте в разделе "Создание собственных модулей для языка RCML".

Дополнительно роботы модуля в зависимости от заложенного в них функционала могут предоставлять возможность ручного управления роботом посредством управляющего устройства, представленного в среде RCML соответствующим модулем.

1.5 Подробнее о модулях функций

Через модули функций возможно добавление в язык RCML новых функций, которые не целесообразно или невозможно реализовывать на данном языке, например, какие-либо сложные вычисления. Таким образом, через отдельный API модули функции позволяют реализовать связь RCML с прочим ПО.

1.6 Подробнее о модулях управления

Модули данного типа используются для принятия решения о выборе очередного робота при необходимости выполнения той или иной функции. Как вариант выбор может быть основан на накопленных ранее статистических данных, об этой функции, роботе или программе. Через модули выбора возможно произвести выбор робота по различным алгоритмам, заложенным в них (модулях). Обычно отдельный модуль представляет отдельный алгоритм выбора робота.

Без данных модулей выбор роботов происходит по решению модулей роботов. Подробнее о работе механизма выбора робота в разделе "Использование модуля выбора робота".

1.7 Компиляция и запуск программы RCML

Как отмечалось ранее, написанная на языке RCML программа сначала должна быть откомпилирована в байт-код, и лишь только потом она может быть запущена на выполнение интерпретатором RCML.

Для компиляции программы нужно запустить компилятор RCML, наименование его исполняемого файла по умолчанию (без расширения, так как в зависимости от ОС оно может быть различным) - rcml_compiler. При запуске компилятора ему нужно передать 2 параметра:

rcml_compiler <rcml_text_file> <rcml_pc_file>

В качестве первого параметра rcml_text_file указывается путь до файла с RCML программой, а в качестве второго параметра rcml_pc_file - путь до файла, в который нужно записать полученный байт-код данной программы.

Если компиляция будет выполнена успешно, то файл с байт-кодом будет создан или перезаписан, если он уже имеется. И теперь его можно запустить на выполнение через интерпретатор RCML, имя исполняемого файла которого по умолчанию - rcml_interpreter. Компилятор при запуске ожидает всего один параметр – файл с байт-кодом. Синтаксис команды запуска интерпретатора:

rcml_interpreter <rcml_pc_file>

Важно! К пути rcml_pc_file интерпретатор автоматически дописывает расширение .pc

1.8 Параметры командной строки RCML

Командная строка RCML компилятора имеет следующий шаблон:

rcml_compiler [--version] [--logfile log_file_path] <rcml_text_file> <rcml_pc_file>
  • --version - вывод текущей версии RCML компилятора, списка версий, поддерживаемого API модулей, а также даты сборки. При указании этого флага компилятор выводит информацию и сразу же завершает работу;
  • --logfile log_file_path - переключение вывода RCML компилятора в файл по пути log_file_path;
  • rcml_text_file - путь до файла с RCML программой в текстовом представлении;
  • rcml_pc_file - путь до файла, в который записать скомпилированную программу.

Командная строка RCML интерпретатора имеет следующий шаблон:

rcml_interpreter [--version] [--logfile log_file_path] <rcml_pc_file> [rcml_params]
  • --version - вывод текущей версии RCML интерпретатора, списка версий, поддерживаемого API модулей, а также даты сборки. При указании этого флага интерпретатор выводит информацию и сразу же завершает работу;
  • --logfile log_file_path - переключение вывода RCML интерпретатора в файл по пути log_file_path;
  • rcml_pc_file - путь до файла скомпилированной RCML программы;
  • rcml_params - параметры запускаемой RCML программы. Подробнее о параметрах RCML интерпретатора в разделе "Передача параметров в программу на RCML".

Важно! К rcml_pc_file интерпретатор автоматически дописывает расширение .pc

2 Основы построения программ на RCMLНаверх

2.1 Алфавит языка и специфика использования символов

Алфавит языка RCML составляют:

  1. Символы, используемые для составления идентификаторов:
    • латинские строчные или прописные буквы;
    • арабские цифры от 0 до 9;
    • символ подчеркивания «_»;
  2. Символы-разделители:
    • символ пробела;
    • символ табуляции;
    • символы переноса строки;
  3. Специальные символы – символы, выполняющие определенные функции при построении различных конструкций языка: + - * / = { } ( ) < > , ; : ~ # @ ! "
  4. Составные символы – группа символов, которые воспринимаются компилятором как единое целое: :: -> == >= <= !=
  5. «Неиспользуемые» символы – символы, которые не входят во множество выше обозначенных, но, тем не менее, могут быть использованы в комментариях или для задания значений констант и строк;
  6. Зарезервированные слова, рассмотренные далее.

2.2 Правила составления идентификаторов

Идентификатор – имя, свободно избираемое программистом для элементов программы (функций, переменных и т.д.):

  • идентификатор должен начинаться с буквы или символа подчеркивания;
  • начиная со второй позиции в идентификаторе можно применять наряду с буквами цифры;
  • при указании идентификаторов учитывается регистр вводимых символов;
  • пробел является разделителем и не может стоять внутри идентификатора;
  • зарезервированные слова в качестве идентификаторов не допускаются.

2.3 Общая структура программ в RCML

Программа на языке RCML состоит из двух ключевых разделов: раздел включений и раздел функций.

Пример программы на языке RCML:

// Раздел включений
includefunction.rcmlincludeC:/robot/robot.rcml”

// Раздел функций
function sum(a, b) {
	c = a + b;
	return c;
}
function main() {
	s = sum(1, 2);
	echo(“sum = ”,s,”\n”);
}

В разделе включений могут быть указаны другие файлы программ на RCML, текст которых нужно включить в данную программу. Это могут быть наборы каких-либо функций, дополнительные библиотеки и т.д. Однако раздел включений может быть и пустым.

Раздел функций начинается после первого упоминания ключевого слова function. В разделе функций указывается основной код программы, который состоит из функций. 

По аналогии с языками программирования C и C++, выполнение начинается с функции с именем main, которая обязательно должна присутствовать. Данное утверждение относится к исполняемым программам на RCML, не являющимся библиотеками. Разница между библиотекой и исполняемой программой будет рассмотрена далее.

2.4 Включение дополнительных файлов RCML в программу

Дополнительные файлы программ на RCML включаются следующим образом: каждый включаемый файл записывается с новой отдельной строки, в начале следует ключевое слово include, затем через разделяющий символ (например, пробел) путь до включаемого файла в двойных кавычках.

Синтаксис:

include “путь_к_файлу”

Примеры:

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

Путь до включаемого файла может быть абсолютным или относительным. В случае если путь относительный, то компилятор сначала вычисляет абсолютный путь до включаемого файла относительно абсолютного пути файла, в котором встречена данная конструкция включения. Если файл по полученному пути не найден, то компилятор вычисляет абсолютный путь относительно каждого варианта пути из параметра path из раздела lib_search_paths в конфигурационном файле config.ini в том порядке, в котором эти пути были указаны в файле конфигурации.

Данный параметр path из раздела lib_search_paths конфигурационного файла называется «путь поиска по умолчанию». Синтаксис задания путей поиска по умолчанию:

[lib_search_paths]
path = путь_1
path = путь_2

Порядок включения дополнительных файлов с кодом такой же, в каком они были указаны в исходном rcml файле.

Важно! В случае обнаружения во включаемом файле непустого раздела включений, файлы из этого раздела будут включены в исходный файл сразу после включения файла (сразу после строки со словом include), в котором они были обнаружены.

Для каждого включаемого файла вычисляется абсолютный путь, и вновь включаемые файлы с таким же абсолютным путем не будут включены в программу.

Следует понимать механизм включения дополнительных файлов в программу. Можно провести аналогию к тому, что вместо конструкции include будет помещен текст включаемого файла целиком. Проверка правильности синтаксиса каждого включаемого файла происходит перед включением, а компиляция программы с учетом всех вычислений и оптимизаций происходит только после составления полного текста программы с учетом всех включаемых файлов.

2.5 Включение файлов библиотек RCML в программу

Дополнительные библиотеки, написанные на RCML, включаются следующим образом: каждая включаемая библиотека записывается с новой отдельной строки, в начале которой следует ключевое слово include_lib, затем разделяющий символ (например, пробел), затем идентификатор - имя библиотеки (через которое будет происходить обращение к библиотеке в коде программы), затем разделяющий символ и путь до файла с байт-кодом библиотеки (pc-файл) в двойных кавычках.

Синтаксис:

include_lib имя_библиотеки “путь_до_файла_библиотеки”

Пример программы, использующей включение библиотеки math:

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

Процесс создания библиотеки описан в разделе "Создание файла библиотеки RCML".

Процесс поиска файла библиотеки компилятором аналогичен поиску включаемого файла. Однако включения кода библиотеки в исполняемый код программы не происходит. В исполняемой программе создается ссылка на файл библиотеки, и для запуска такой программы также потребуется файл скомпилированной библиотеки, как и при компиляции.

Допускается включение одного и того же файла библиотеки под разными именами-идентификаторами. 

Стоит отметить, что библиотеки могут ссылаться на другие библиотеки, т.е. при компиляции библиотеки допускается включение в неё других библиотек.

2.6 Функции

Как было отмечено ранее, в исполняемой программе, не являющейся библиотекой, всегда должна присутствовать функция с именем main (далее основная функция), именно с неё начинается выполнение. При этом неважно, где будет находиться данная функция: в исходном файле или в одном из включаемых. Важно, чтобы эта функция была одна и только одна.

Разумеется, программист вправе создавать новые функции, помимо функции main, с именами, соответствующими правилам задания идентификаторов, и обращаться к ним как в основной функции, так и в прочих.

Задание новой функции начинается с ключевого слова function, далее через разделитель следует наименование функции, затем в круглых скобках список параметров, который может быть пустым. После списка параметров в фигурных скобках следует код функции – список её операторов.

Синтаксис задания функции:

function имя_функции(список_параметров) {
	список_операторов
}

Пример функции:

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

Функция в языке RCML может как возвращать значение, так и не возвращать. Возврат значения, как и выход из функции происходит через оператор return

В конце функции данный оператор указывать необязательно, если значение не возвращается. Если функция не возвращает значения, то по умолчанию возвращаемое значение считается нулем - 0.0.

Значения параметров функции всегда передаются по значению, поэтому их можно использовать как обычные переменные в теле функции, не боясь перезаписи данных в функции, из которой была вызвана текущая.

Порядок расположения функций относительно друг друга не важен и никак не влияет на область их видимости. Каждая функция может быть вызвана из любой другой функции, за исключением основной функции.Поскольку с неё начинается выполнение, её вызов в коде функций запрещён. Стоит отметить, что внутри функции нельзя объявить функцию.

Параметры в основной функции (main) имеют особое значение, подробнее в разделе "Передача параметров в программу на RCML"

2.7 Комментарии

В RCML доступны однострочные и многострочные комментарии. Однострочный комментарий начинается с двойного знака косой черты // и следует до конца строки.

Пример:

//Это комментарий

Многострочный комментарий начинается со комбинации символов /* и следует до следующей комбинации символов */

Пример:

/* Это
многострочный
комментарий */

2.8 Типы данных

В RCML присутствуют явные типы данных и неявные. К первым относятся те типы данных, переменные которых могут быть созданы и использованы в различных операциях. Ко вторым же, наоборот, переменные которых не могут быть созданы, но эти типы данных могут неявно получиться при некоторых операциях, или их можно использовать как параметры для специфичных функций. От данного разделения обособлен тип данных для связи с физическим роботом.

Стоит отметить, что на данном этапе развития RCML иные типы данных, в том числе и массивы, пока не предусматриваются.

2.8.1 Явные типы данных

Явный тип данных в RCML всего один – это вещественные числа. Все создаваемые переменные, используемые в операциях, параметры и возвращаемые значения пользовательских функций, а также всех функций модулей и роботов являются вещественными числами.

2.8.2 Неявные типы данных

К неявным типам данных на языке RCML относятся логический и строковый типы.

В логический тип данных принудительно преобразуются данные, используемые при вычислении логических выражений.

Строковый тип данных используется только для задания строковых констант, которые могут быть параметрами для функций системного уровня (системные функции RCML, функции модулей роботов и функциональных модулей). Строковой константой является последовательность любых символов, заключенная в двойные кавычки, при этом в строковой константе могут быть указаны следующие управляющие наборы символов, считающиеся за один символ:

  •  \n – переход на новую строку;
  • \” – вставка символа двойной кавычки;
  • \\ - вставка символа обратной косой черты (обратный слэш).

2.9 Переменные

Переменная в языке RCML инициализируется в момент первого присвоения ей значения и остается видимой от точки инициализации до конца тела функции, в которой используется. Для присвоения значения переменной используется одинарный символ «=». Переменной могут быть присвоены константные значения, результаты выражений и вызовов функций. Переменная может быть передана как аргумент функции. Переменные, являющиеся параметрами функции, инициализируются при переходе выполнения в данную функцию.

Пример использования переменных в функции:

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

В RCML нет глобальных переменных.

Программист может не заботиться о расходе памяти и не удалять использованные переменные, когда в них отпадает необходимость. Об этом заботится компилятор при оптимизации получаемого байт-кода, просчитывая пути жизни каждой переменной. Однако, это не относится к особым переменным, связанным с физическими роботами.

2.10 Выражения и операции

Выражения в RCML могут состоять из числовых констант, переменных и возвращаемых результатов функций, которые могут быть использованы в качестве операндов математических и логических операций в составе выражения. Операции, в свою очередь, могут быть бинарными или унарными. Приоритет операций в выражениях задается круглыми скобками, так же, как это принято в математике. Результат выражения может быть присвоен в переменную или передан как параметр функции, что возможно для тех параметров функций, которые работают с данными типами данных. Использование особых переменных для связи с роботом в контексте выражений запрещено на уровне синтаксических правил.

Примеры выражений:

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

2.10.1 Математические операции

В RCML доступны следующие бинарные математические операции:

  • «+» - операция сложения;
  • «-» - операция вычитания;
  •  «*» - операция умножения;
  • «/» - операция деления без остатка;
  • «%» - взятие остатка от операции деления.

И одна унарная операция:

  • «-» - смена знака.

2.10.2 Логические операции

Из логических операций в RCML доступны следующие бинарные операции:

  • «==» -проверка равенства;
  • «!=» -проверка неравенства;
  • «>=» - проверка больше или равно;
  • «<=» - проверка меньше или равно;
  • «>» - проверка больше;
  • «<» - проверка меньше;
  • «&&» - конъюнкция, логическое «И»;
  • «||» - дизъюнкция, логическое «ИЛИ».

И одна унарная операция:

  • «!» - логическое отрицание.

2.11 Преобразование типов данных

При использовании различных типов операций в одном выражении происходит неявное преобразование типа данных результата выражения к ожидаемому типу операнда следующей операции. Результат будет вещественным, если он сохраняется в переменную или передается как параметр функции, или строго логическим, если используется в условном операторе.

При преобразовании вещественного типа в логический выполняется следующее правило: 

если элемент не равен нулю, то результат - истина, иначе - ложь. 

При обратном преобразовании выполняется правило:

если истина, то результат будет 1.0, если ложь, то результат 0.0.

2.12 Управляющие конструкции

Язык RCML предусматривает стандартный набор конструкций, влияющих на ход выполнения программы.Их можно разделить на условные, циклические и безусловные.

2.12.1 Условные управляющие конструкции

В RCML представлен всего один оператор условного перехода - if. Синтаксис его использования следующий:

if (выражение) {
	//набор операторов, если результат выражения истина
} else {
	//набор операторов, если результат выражения ложь
}

Результат выражения, заключенного в круглых скобках, приводится к логическому типу, и если результат – истина, то выполняется первый блок операторов в фигурных скобках, иначе — второй блок операторов после ключевого слова else. Второй блок операторов вместе с ключевым словом else может опускаться при задании условного оператора.

2.12.2 Циклические управляющие конструкции

Циклический оператор в RCML так же единствен, это оператор loop. Это более упрощенный оператор цикла по сравнению с аналогичными операторами в традиционных языках программирования. Он является безусловным, и его блок операторов будет выполняться бесконечно, если в нем не будет соответствующей конструкции выхода с предварительным условием или без него. Синтаксис оператора loop следующий:

loop {
	// блок операторов цикла
}

2.12.3 Прочие управляющие конструкции

К прочим управляющим конструкциям в языке RCML относятся операторы безусловного перехода, при достижении которых выполнение программы переходит на тот или иной участок.

Оператор перехода на начало цикла – continue. При его достижении происходит переход на начало текущего цикла. Используется без параметров.

Оператор выхода из цикла – break. При его достижении происходит прерывание текущего цикла. Используется без параметров.

Оператор выхода из функции – return. Может указываться как с выражением, так и без него, в первом случае результатом выполнения функции будет результат, возвращаемый выражением, во втором случае функция будет возвращать значение по умолчанию – 0.0.

Синтаксис использования оператора return с возвратом выражения:

return выражение;

Без возврата выражения:

return;

Примеры использования оператора return:

return 2+2; //выход из функции в возвратом значения
return; //выход из функции без возврата значения

В случае если оператор return будет указан в функции main, то его выполнение приведет к завершению работы RCML программы, а значение, переданное через данный оператор, будет передано в ОС как код завершения программы. Однако при этом передаваемое значение будет округлено до целых посредством отброса дробной части.

Оператор выхода из программы – exit. При достижении этого оператора происходит завершение выполнения программы независимо от того, в какой функции он указан. Данный оператор также, как и оператор return может вызываться как с выражением, так и без него. В первом случае в ОС возвращается результат выражения как код завершения программы, во втором случае код завершения программы считается равным 0.

Синтаксис использования оператора exit с возвратом выражения:

exit выражение;

Без возврата выражения:

exit;

2.13 Исключения

В RCML возможна обработка исключительных ситуаций, возникающих в определенном блоке кода, как и в некоторых других языках программирования. Общий вид конструкции обработки исключения начинается с оператора try, затем за ним следует блок операторов, в котором может возникнуть исключение в процессе исполнения операторов данного блока, далее может следовать оператор catch и блок операторов, который необходимо выполнить в случае появления исключения. Общий вид конструкции обработки исключений следующий:

try {
	//блок операторов, в котором может возникнуть исключение
} catch {
	//блок операторов для обработки ситуации с исключением
}

При появлении исключения в блоке оператора try выполнение программы переходит на блок оператора catch. Следует отметить, что оператор catch и его блок может быть опущен, и тогда выполнение программы перейдет на оператор, следующий за блоком оператора try. Конструкция обработки исключений может быть вложена одна в другую, и, в случае возникновения исключения, оно будет обрабатываться текущей конструкцией.

Исключения могут возникать при выполнении различных функций, предоставляемых внешними или системными модулями RCML, такими как функциональные или модули роботов, но выброс исключения можно вызвать и вручную, используя оператор throw. При выполнении этого оператора сразу же будет брошено исключение.

Работа механизма исключений на примере простой программы деления чисел:

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) { // если b ноль, то делить нельзя
				throw; //бросаем исключение
			}
			c = a / b;
			echo(“c = ”, c, “\n”);
		} catch {
			echo(“b is zero!”); //обработка исключения будет в этом блоке
		}
	} catch {
		//этот блок никогда не будет выполнен
	}
}

Однако в языке RCML, ориентированном на робототехнику, в отличие от других языков программирования, оператор try может принимать параметры, указывающие, как именно ему работать. Первый параметр, который принимает оператор try -  это строковая константа с указанием режима работы, в зависимости от указанного режима может указываться второй параметр вещественного типа данных.

Всего у оператора try три режима работы:

  • error_default” - режим работы по умолчанию, как обычный оператор try. В этом случае второй параметр оператора try не указывается. Если параметры оператора try опускаются как в вышеприведенном примере, то оператор try работает именно в этом режиме.
  • error_time_limit” – режим работы с отсчетом лимита времени, за который должен быть выполнен блок кода оператора try. В данном случае указывается второй параметр, который задает количество миллисекунд, являющийся лимитом на выполнение блока кода оператора try. В случае если данный блок не будет выполнен за указанное время, будет брошено исключение. В случае если исключение будет брошено раньше, отсчет времени будет прекращен, а само исключение будет обработано в обычном режиме.
  • error_try_count” – режим работы с отсчетом количества попыток, данных для выполнения блока оператора try. В данном режиме второй параметр принимает количество допустимых попыток исполнения данного блока. При каждом брошенном исключении в блоке оператора try счетчик количества попыток будет уменьшаться на 1, и если он достигнет нуля, то будет произведена обычная обработка исключения.

Несмотря на то, что оператор try может принимать параметры, он не является функцией и не возвращает значение.

Пример использования указанных режимов для обработки успешности выполнения роботом своей функции с выдачей ему трёх попыток с лимитом времени по 2 секунды на каждую:

try(“error_try_count”, 3) {
	try(“error_time_limit”, 2000) {
		robot->do_something();
	} catch { //если время вышло
		throw; //то бросаем исключение, чтобы исчерпать попытку
	}
} catch {
	//этот блок выполнится, когда все попытки будут исчерпаны, 
	//а результат так и не будет получен
}

Через оператор throw с исключением можно передать какое-либо значение (значение исключения). В данном случае синтаксис оператора throw будет следующий:

throw выражение;

Для обработки значения выброшенного исключения оператор try будет иметь немного иной синтаксис, в параметрах оператора catch должен быть указан идентификатор - имя переменной, в которую будет записано исключение:

try {
	//блок операторов, в котором может возникнуть исключение
} catch (имя_переменной) {
	//блок операторов для обработки ситуации с исключением
}

Если на момент появления исключения указанная переменная не существует, то она будет создана, в противном случае перезаписана.

try {
	throw 3;
} catch (E) {
	system.echo(“E = ”, E, “\n”); //выведет E = 3
}

Переменная, в которую записывается значение исключения, будет доступна не только в блоке catch, но и за его пределами до конца функции.

Пример с созданием переменной:

system.echo(“E = ”, E, “\n”); //ошибка E ещё не существует
try {
	throw 3;
} catch (E) {
	system.echo(“E = ”, E, “\n”); //выведет E = 3
}
system.echo(“E = ”, E, “\n”); //выведет E = 3, т.к. E была создана в блоке catch

Пример с перезаписью значения:

E = 5;
system.echo(“E = ”, E, “\n”); // выведет E = 5
try {
	throw 3;
} catch (E) {
	system.echo(“E = ”, E, “\n”); //выведет E = 3
}
system.echo(“E = ”, E, “\n”); //выведет E = 3

Подобным образом возможна обработка переданного значения исключения не только посредством оператора throw, но также и обработка значений исключений передаваемых из функций модулей роботов и функциональных модулей, а также библиотек.

Пример:

try {
	robot_test->throw_value(10);
} catch (E) {
	system.echo(“E = ”, E, “\n”); //выведет E = 10
}

Если выброшенное исключение не было перехвачено в RCML программе, то произойдет завершение работы RCML программы с кодом 1, т.е. с ошибкой, что может служить средством коммуникации ОС и RCML программы (подробнее в разделе "Коммуникация с ОС"). При этом значение исключения будет утрачено. 

2.14 Вызов функций

Функции на языке RCML могут быть внутренними и внешними.

Под внутренними функциями понимаются функции, описанные на языке RCML в текущем файле исходного кода программы или во включаемых файлах с исходным кодом на RCML. Код таких функций находится внутри текущей программы и будет скомпилирован в исполняемый файл текущей программы.

Внешние функции - это функции уже скомпилированных библиотек RCML, подключаемых к текущей программе, либо функции функциональных модулей, т.е. код таких функций находится вне текущей программы на RCML.

Синтаксически вызов внутренней функции в языке RCML выглядит так же, как и в других языках программирования. Сначала следует идентификатор – имя функции, затем в круглых скобках список передаваемых в неё аргументов:

идентификатор(аргумент1, аргумент2, аргумент3)

Результат вызова любой функции может быть присвоен переменной или использован в выражении. Стоит отметить, что при вызове функции должны быть переданы через аргументы все параметры, указанные в её описании, за исключением некоторых системных функций языка RCML.

Вызов внешней функции имеет иной синтаксис:

имя_источника.имя_функции(аргумент1, аргумент2, аргумент3)

В качестве имени источника используется идентификатор (имя) подключаемой библиотеки из раздела включений или имя функционального модуля, указанного в конфигурационном файле. Описание имен и аргументов внешних функций обычно можно найти в документации к соответствующему источнику - библиотеке или функциональному модулю.

Следует отметить, что при поиске внешней функции искомый источник ищется, в первую очередь, среди подключенных библиотек, затем среди подключенных функциональных модулей. Если источник найден, в нем по наименованию ищется требуемая функция, если функция найдена, то сверяется количество параметров функции, задекларированных в источнике, с количеством аргументов, передаваемых пользователем. В случае если количество аргументов и параметров совпадает, считается, что искомая функция найдена, в любом другом случае выдается ошибка.

RCML имеет системный модуль system, всегда доступный в программе и предоставляющий системные функции языка RCML. Если в качестве источника внешних функций указывается данное имя, то поиск функции происходит сразу в этом модуле, игнорируя библиотеки с аналогичным именем.

2.15 Системные функции языка RCML

Системные функции языка RCML доступны в среде RCML через системный модуль system. Доступ к данным функциям происходит так же, как ко внешним функциям модуля с указанием имени system.

Системный модуль имеет следующие функции:

  • system.input – функция считывания числа из строки, полученной через стандартный ввод. Считываемая строка должна состоять из цифр и опционально из знака + или -. Затем она преобразовывается в число, которое возвращается как результат вызова функции. Данная функция параметров не имеет.
  • system.echo – функция вывода данных, переданных в качестве аргументов в стандартный вывод. Может принимать любое переменное число параметров, среди которых допускаются строковые константы и числа.
  • system.set – функция изменения системных параметров среды RCML. Принимает два аргумента: название системного параметра и его новое значение. Название системного параметра задается строковой константой, а новое значения этого параметра зависит от указываемого системного параметра. Сейчас у RCML-среды существует только один системный параметр:
    • “behavior” – режим выполнения функций по умолчанию. В качестве второго параметра передается флаг режима, знак ~ или #. Подробнее о режимах выполнения читайте в разделе "Пакетная передача команд роботам".
  • system.sleep – временная пауза в процессе выполнения программы. Принимает один числовой параметр – время паузы в миллисекундах.
  • system.hand_control – включение режима ручного управления для робота. Функция переводит указанного робота в режим ручного управления посредством указанного модуля управления. Выполнение основной программы на период ручного управления приостанавливается. Данная функция принимает переменное число параметров:
    • первый параметр – специальная переменная, связанная с нужным физическим роботом. Обязательный параметр;
    • второй параметр – строковая константа – наименование модуля управления. Обязательный параметр;
    • третий параметр – строковая константа – ось робота;
    • четвертый параметр – наименование оси управляющего устройства в виде строковой константы или выражения, которые будут задавать значения для оси робота, указанной в предыдущем параметре.
    • пятый и шестой, седьмой и восьмой и т.д. параметры задаются всегда попарно: ось робота и источник значений для неё.
  • system.send_package – команда для отправки накопленного пакета команд для роботов. В качестве единственного параметра передается флаг режима выполнения команд из пакета, ~ или #. Подробнее о данной функции в разделе «Указание режимов выполнения функций».

2.16 Макросы

Язык RCML реализует поддержку макросов. Макросом является связка идентификатора – имени макроса -  с произвольным текстом – содержание макроса. Макросы объявляются в разделе включений через ключевое слово define, после которого следует разделитель, затем следует идентификатор, являющийся именем макроса, снова разделитель и текст макроса.

Синтаксис задания макроса:

define имя_макроса содержимое_макроса

Все вхождения имени макроса в тексте раздела функций будут заменены на его содержание. После определения макроса его невозможно переопределить другим макросом.

Содержимым макроса считается любой текст между символом-разделителем, следующим после имени макроса, и концом строки. Макрос может иметь многострочное содержимое, для его задания нужно поставить символ «\», т.е. экранировать конец строки, так же, как это делается в многострочных макросах на С++. Тогда содержимым макросом будет считаться всё до конца строки, следующей за строкой, оканчивающийся на данный символ. Символы перевода строки в многострочных макросах сохраняются.

Пример использования макросов:

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");
}

Данный текст после обработки макросов будет преобразован к следующему тексту:

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");
}

Полученный текст уже будет компилироваться в байт-код. Результат выполнения данной программы будет выглядеть следующим образом:

1 = 1.000000
2 = 2.000000
3 = 3.000000
Test print > test message
Важно! Опасно использовать макросы, которые рекурсивно ссылаются друг на друга, в данном случае образуется бесконечная рекурсия, которая приведет к зависанию компилятора. На данном этапе развития языка обнаружение замкнутой рекурсии в макросах не происходит.

Пример замкнутой рекурсии:

define ONE TWO
define TWO ONE

3 Особенности взаимодействия программы с роботомНаверх

Как отмечалось выше, язык RCML ориентирован на робототехнику и имеет довольно скудную составляющую как язык программирования, так как не предназначается для создания прикладного ПО общего назначения и нацелен на взаимодействие с робототехникой, позволяя достигать в этом отношении новых результатов.

3.1 Понятие робота в RCML

Робот в RCML представляется как некий исполнительный ресурс, который может быть задействован для выполнения определенной задачи (функции), а затем освобожден для повторного задействования, но, например, в уже другой задаче. Ближайшая аналогия — вычислительное ядро процессора, которое в конкретный момент времени может быть занято только одним процессом. Однако средствами ОС, выделяющей очень малые кванты процессорного времени разным программным процессам или задачам, возможно создание иллюзии, что одно ядро обрабатывает сразу несколько задач. В RCML же управлением роботом как ресурсом занимается интерпретатор, но робот задействован не на период времени, а на выполнение конкретной своей функции или нескольких, и, таким образом, время его задействования может быть разным.

Робот является объектом проявленного материального мира, и его действия зачастую не так мгновенны, как в приведенной аналогии с ядром процессора. И на выполнение своей функции ему требуется время, и это время может быть разным для одной и той же функции, поскольку на робота воздействует множество факторов материального объектного мира.

Модуль робота как таковой предоставляет среде RCML описание класса робота, закрепленного за ним, предполагается, что локально в объектном мире, где используется RCML, может быть, как один, так и несколько роботов одного класса, закрепленных за одним модулем робота. Причем в среде RCML в рамках модуля робота присутствует два ключевых типа объектов, в соответствии с рисунком 4:

  • модуль робота  исполняет функции контроллера роботов вверенного ему класса, то есть выполняет функции выбора свободного робота для задействования и освобождения робота после работы;
  • представление робота – отражение конкретного физического робота в виртуальной среде RCML, через него транслируются команды физическому роботу.

Рисунок 4 Виртуальное представление классов объектов в среде RCML

Следует отметить, что может быть подключено много классов роботов одновременно, то есть много модулей роботов, и каждый из них может предоставлять доступ сразу к нескольким роботам своего класса. Роботы в рамках одного класса должны быть одинаковы полностью, как в физическом представлении, так и в функциональном.

3.2 Использование робота в программе

Чтобы задействовать робота в программе, необходимо указать его класс и функцию, которую он должен выполнить. Именование класса робота совпадает с именованием модуля робота в файле config.ini, но класс робота в RCML программе должен указываться через ключевое слово robot и знак подчеркивания. 

Синтаксис задействования робота:

robot_класс_робота

Например, нужно вызвать робота из модуля test, тогда указание его класса будет иметь вид:

robot_test

Встретив наименование класса робота в тексте программы, система пошлет запрос к соответствующему модулю робота и остановит выполнение программы, пока не будет найден свободный робот требуемого класса.

3.3 Вызов функции робота

Получив робота нужного класса, программист может заставить его выполнить требуемое действие, т.е. вызвать выполнение какой-либо функции этого робота. Функции роботов программируются разработчиком робота вместе с модулем робота и описываются в документации к модулю робота.

Вызов функции визуально похож на вызов метода объекта в С-подобных языках программирования. Следует указание класса робота, затем через знак указателя -> указывается обозначается требуемая функция, затем в круглых скобках перечисляется список аргументов этой функции. 

Cинтаксис вызова функции робота:

robot_класс_робота->функция_робота(аргументы);

Например, из робота класса test нужно вызвать функцию do_something с одним аргументом 1000:

robot_test->do_something(1000);

Встретив подобную конструкцию, интерпретатор зарезервирует робота указанного класса, дождется, когда будет задействован реальный физический робот, и затем передаст команду представлению робота об исполнении указанной функции с указанными параметрами. После исполнения функции робот будет автоматически освобожден и переведен в статус свободного.

Следует отметить, что при таком указании вызова функции робота интерпретатор дождется подтверждения выполнения функции от представления робота и только затем продолжит выполнение остальной программы. Подробнее об флагах выполнения функции рассказано в разделе «Указание режимов выполнения функций».

В зависимости от того, как и где описано исполнение функций робота, их (функции) можно разделить на 3 типа:

  • пользовательские функции – функции, описанные на языке RCML в текущем файле исходного кода программы или во включаемых файлах с исходным кодом на RCML. Код таких функций находится внутри текущей программы и будет скомпилирован в исполняемый файл текущей программы;
  • библиотечные функции – функции уже скомпилированных библиотек RCML, подключаемых к текущей программе, т.е. код таких функций находится вне текущей программы на RCML;
  • системные функции – функции, которые предоставляет в среду RCML модуль робота. Код исполнения таких функций находится в модуле робота или в ПО самого робота.

Системная функция может быть переопределена библиотечной и пользовательской, библиотечная - только пользовательской. Пользовательская функция переопределена быть не может, при создании двух пользовательских функций с одинаковым наименованием компилятор выдаст ошибку. Данный механизм позволяет переопределять неэффективные функции того уровня, где это тяжелее сделать, функциями того уровня, где это легче сделать. Например, перекомпилировать модуль робота или библиотеку может быть затруднительно в виду отсутствия исходных кодов, однако переопределить нужную функцию в тексте своей программы легко.

Таким образом, в вызове функции указанная функция робота сначала ищется среди пользовательских функций. В случае если среди функций пользовательского типа искомая функция не найдена, поиск продолжается на среди библиотечных функций. На предмет искомой функции просматривается каждая библиотека в порядке включения в исходный текст программы. Следует отметить, что разные библиотеки могут включать одну и ту же функцию для одного и того же робота, поэтому будет выбрана первая найденная функция. В случае если среди библиотечных функций искомая функция также не будет найдена, поиск будет продолжен среди системных функций. В рамках модуля робота системных функций с одним именем может быть несколько, однако выбирается всегда первая найденная. Если среди системных функций искомая функция не будет найдена, то будет выдана ошибка.

Поиск функции производится только по её имени без учета числа параметров. Если найденная функция имеет количество параметров, отличное от количества передаваемых аргументов в вызове функции, то будет выдана ошибка.

Исходя из данного алгоритма поиска можно заключить, что наивысший приоритет в поиске имеют пользовательские функции, затем библиотечные и лишь потом системные функции.

Однако иногда перед программистом встаёт необходимость использовать именно системную функцию, которая переопределена библиотечной функцией. Данная ситуация возможна, когда библиотечная реализация функции является неэффективной, исходного кода библиотеки нет, а необходимость использовать данную библиотеку есть ввиду наличия в ней других функций. Прямое обращение к системной функции возможно, если указать перед наименованием функции символ точки «.», синтаксис вызова функции будет следующий:

robot_класс_робота->.функция_робота(аргументы);

И рассмотренный пример примет вид:

robot_test->.do_something(1000);

3.4 Работа с конкретным экземпляром робота

Часто бывает необходимо вызвать не одну функцию у робота, а сразу несколько, и их должен выполнить один робот как заданную последовательность действий. Если вызвать необходимую последовательность функций примером, описанным в разделе выше, то при наличии нескольких роботов одного класса вполне вероятно, что заданные функции будут выполняться разными роботами. В случае если же робот заданного класса всего один в наличии, то для каждой функции он будет каждый раз задействован и освобожден.

Наиболее эффективно и рационально задействовать робота единожды и передавать ему команды так, как это необходимо, а затем его освободить, таким образом реализовав сеанс работы робота. Для этого требуется задействовать робота нужного класса и запомнить связь с задействованным конкретным роботом. Это можно сделать, сохраняя робота в специальный тип переменных, перед идентификатором которых должен быть поставлен символ «@». Например, задействуем робота класса test и сохраним связь с конкретным полученным экземпляром в переменной @r:

@r = robot_test;

Встретив подобную конструкцию, интерпретатор, как и в случае вызова функции робота, пошлет запрос на задействование робота, но теперь робот не будет освобожден, пока не будет встречена команда освобождения этого конкретного робота.

Теперь, чтобы вызвать выполнение функции у данного задействованного робота, нужно вызывать функцию, обращаясь к данной переменной, а не к классу робота. Например, вызов у данного робота той же самой функции do_something с теми же параметрами:

@r->do_something(1000);

После выполнения функции робот так же останется задействованным, и можно вызывать следующую функцию у данного экземпляра.

Применение особых переменных со знаком @ в контексте выражений в RCML не допускается, они не могут участвовать в операциях, сравнениях и передаваться как аргументы функций (за исключением системной функции hand_control). Однако, возможно присваивание робота в другую переменную этого же типа, то есть связь с задействованным роботом можно хранить в нескольких переменных, например:

@r = robot_test;
@r2 = @r;
@r4 = @r3 = @r2;

В результате все переменные @r, @r2, @r3 и @r4 будут указывать на одного и того же робота.

В переменную, уже указывающую на конкретного робота, может быть присвоен указатель на совершенно другого робота, и даже другого класса робота:

@r = robot_test;
@r2 = @r;
@r = robot_tarakan;

Теперь @r указывает на робота класса tarakan, а @r2 на робота класса test. Следует отметить, что при смене робота, на которого указывает переменная, робот, на которого указывала она ранее, не будет освобожден.

3.5 Высвобождение задействованного робота

Робота, «сохраненного в особую переменную», можно освободить, используя специальный оператор delete, когда это потребуется. С данным оператором должна указываться специальная переменная, хранящая указатель на освобождаемого робота. Пример освобождения робота, указатель на которого был ранее присвоен в переменную @r:

delete @r;

Следует отметить, что все роботы, задействованные и не освобожденные через оператор delete, будут освобождены только при завершении выполнения функции, в которой они были задействованы. Данное утверждение не относится к функциям робота, написанным на языке RCML, т.к. в эти функции выполняются в контексте экземпляра робота, и в них нельзя задействовать экземпляр робота. Подробнее об этих функциях читайте в разделе "Написание собственных новых функций для роботов". 

Важно помнить, что, по аналогии с традиционными языками программирования, где программист может допустить утечку памяти, на языке RCML теперь можно допустить утечку роботов.

В разделе "Особенности выполнения функций роботами в разных режимах" есть важное дополнение про механизм освобождения задействованного робота.

3.6 Автоматический выбор робота

Одна из возможностей языка RCML— это автоматический подбор робота под задачу. Чтобы использовать данную возможность, нужно указывать только ключевое слово robot вместо конкретного класса робота в тех местах, где требуется указание класса робота: вызовы функций робота или присвоение робота в переменную. Например:

robot->do_something(1000);
@r = robot;
@r->do_something();

Использование только ключевого слова robot вместо полного имени класса робота далее будет называться абстрактным роботом.

При использовании абстрактного робота в вызове функции среда RCML автоматически проверит, какие типы роботов из имеющихся в системе имеют данную функцию с данным количеством параметров, и, если такие имеются, составит список кандидатов классов роботов, которые могут быть использованы в данном вызове функции. Таким образом, в данном вызове функции могут быть использованы не только разные роботы в пределах одного класса, но и разные роботы по классам.

В случае использования специальной переменной для связи с абстрактным роботом среда RCML проанализирует каждый вызов функции относительно данной переменной и составит список кандидатов только из тех типов роботов, которые имеют все вызываемые функции относительно данной переменной.

3.7 Использование модуля выбора робота

В способе задействования робота, описанном в разделе "Использование робота в программе", выбор конкретного физического робота, а точнее связанного с ним представления робота, производится самим модулем робота, который может ничего не знать о контексте использования задействованного робота, а потому вероятно произвести не самый оптимальный выбор робота-исполнителя. Чаще всего таким способом задействования первый доступный робот, в рамках конкретного модуля роботов, если был указан конкретный требуемый класс роботов. Или если был указан вызов абстрактного робота, то первый свободный робот у первого модуля роботов, имеющего свободных роботов, в порядке перечисления модулей роботов в config.ini.

В процессе работы интерпретатора RCML, если была включена опция записи статистики (см. раздел "Установка и настройка компилятора и интерпретатора RCML"), накапливается статистическая информация о работе роботов и скорости выполнения ими своих функций, подробнее о накапливаемых данных в разделе "Работа с RCML статистикой". Модули выбора роботов могут иметь доступ к данной информации и на основе её могут принять более рациональное решение по выбору робота.

Подключение модуля, или нескольких модулей выбора указывается в операторе задействования робота в угловых скобках <>, с перечислением модулей выбора через символ запятой. Синтаксис данной конструкции следующий:

robot_класс_робота<список_модулей_выбора>

Пример подключения модуля выбора avg к выбору робота класса tarakan:

robot_tarakan<avg>

В данном случае от модуля робота tarakan будут запрошены все представления свободных физических роботов, список которых будет передан модулю выбора avg. Из переданного списка модуль выбора выберет одного наиболее подходящего робота, который и будет задействован. Алгоритм выбора определяется модулем выбора.

Следует отметить, что выбор робота с помощью модуля выбора обычно происходит дольше чем без него, т.к. модулю требуется выполнить дополнительные действия связанные с принятием решения (запросы к БД статистики и пр.).

В случае если выбранный модулем выбора робот успел стать задействованным другим процессом, то процедура выбора начинается заново с запроса свободных роботов у модуля робота.

Указание модуля выбора возможно и при задействовании абстрактного робота. Например, указание модуля статистики avg, с абстрактным роботом:

robot<avg>

В данном случае RCML получит список всех представлений свободных роботов, от всех подходящих под данный вызов робота модулей роботов. Из списка представлений роботов также будет выбран только один робот конкретного класса.

В случае если при задействовании робота было указано несколько модулей статистики. Например: 

robot_tarakan<test1, test2, test3>

В данном случае каждому модулю выбора будет передан список представлений свободных роботов, из которого каждый модуль выбирает одного робота. В данном случае порядок указания модулей выбора определяет очерёдность принятия решения модулями, а также приоритетность выбранного робота конкретным модулем выбора, которую можно выразить в баллах. Первый указанный модуль выбора первым производит выбор робота и выбранный им робот будет иметь максимальный приоритет по баллам равный количеству указанных модулей выбора. Соответственно, последний указанный модуль принимает решение последним и выбранный им робот будет иметь приоритет равный одному баллу. Если модули выбора выберут из списка свободных роботов разных роботов для задействования, то будет задействован робот, набравший максимальное число баллов, т.е. робот с максимальным приоритетом. В случае если у выбранных для задействования роботов одинаковое количество баллов, то будет выбран робот, выбранный первым модулем выбора. 

Важно отметить, что возможна ситуация, когда конкретный модуль статистики по каким-либо причинам не может принять решение о выборе робота, в данном случае модуль уведомляет об этом среду RCML, и текущее поведение среды определяется таким образом, что будто этот модуль не был указан при задействовании робота.

4 Режим ручного управленияНаверх

4.1 Общие сведения

Среда RCML может предоставить возможность ручного управления конкретным экземпляром робота посредством конкретного управляющего устройства при вызове системной функции hand_control с соответствующими параметрами.

Основной принцип действия среды RCML при переходе в режим ручного управления заключается в связывании осей робота, по которым он может так или иначе передвигаться, с осями управляющего устройства, по которым данное устройство может фиксировать изменения, см. рисунок 5. 

Рисунок 5 Пример осей робота и управляющего устройства

В данном примере есть гусеничный робот (изображен слева), который может переходить в свое новое абсолютное положение на плоскости посредством ряда изменений своего положения по двум осям: оси передвижения R (вперед или назад) и оси вращения A (влево или право). И есть простое управляющее устройство по типу джойстика (изображено справа), которое может отклоняться в плоскости от своего начального положения по двум осям X и Y. Соответственно, через RCML возможно связать оси джойстика и робота так, чтобы отклонение джойстика приводило к движению робота. Например, отклонение джойстика по оси Y в положительную сторону приводило к движению вперед, а отклонение джойстика по оси X в отрицательную сторону приводило к повороту робота влево. Предположим, что данный робот представлен в среде RCML модулем tarakan, а джойстик, соответственно, модулем управления joy, тогда RCML код для их связи в режиме ручного управления для получения эффекта, приведенного в примере, будет следующим:

@r = robot_tarakan;
hand_control(@r, “joy”, “R”, “Y”, “A”, “Y”);

4.2 Принцип передачи значений

Таким образом, ось управляющего устройства является источником значений, ось робота — приемником, а сам робот — исполняющим устройством. Разумеется, масштабы или диапазоны значений осей робота и управляющего устройства могут не совпадать. Среда RCML автоматически производит приведение значения, получаемого от оси управляющего устройства, в диапазон значений для оси робота, соблюдая соотношение.

Информацию об осях робота и границах их значений среда RCML получает через API от модуля робота и соответственно они должны быть задекларированы к документации к данному модулю, чтобы программисты на языке RCML могли их использовать. Аналогично для управляющих устройств.

Данный принцип может быть расширен не только на реальные оси передвижения робота или его манипулятора, а на любые его функции, которые так или иначе могут принимать значения и менять состояние робота в режиме реального времени (в рамках возможностей ОС), например, включение световой индикации, блокировка передвижений робота и т.д. Единственное требование - они должны быть задекларированы в модуле робота и в документации к нему.

Дополнительно возможно создание так называемых дискретных осей, которые принимают небольшой диапазон значений, и каждое значение может соответствовать какому-либо состоянию робота или его механизма. Частный случай этого - «бинарные» оси, продуцирующие или принимающие значения 0 или 1, по аналогии с «вкл» или «выкл». Ярким примером тут может быть обычная компьютерная клавиатура, имеющая 101 клавишу и соответственно 101 бинарную ось. У робота такой осью может быть включение ламп и огней, или издание какого-либо звука, или включение режима голосовой связи. Вариации ограничиваются лишь фантазией разработчиков роботов и управляющих устройств, а также программистов на языке RCML, которые могут связывать оси тех или других устройств в произвольном порядке. Благодаря приведению значений к целым числам возможно связывание бинарных осей как робота, так и управляющего устройства с «небинарными» осями того или иного устройства.

Важно отметить, что среда RCML никак не контролирует частоту и изменчивость передачи значений от управляющего устройства к роботу. Если управляющее устройство каждый раз отсылает значение оси, то, даже если оно не изменилось, всякий раз данное значение будет передано роботу. Разработчикам модулей рекомендуется учитывать данный фактор. В частных случаях разработчикам модулей управляющих устройств стоит обратить внимание на фактор частоты передачи значений, ведь каждая передача достигнет робота, и он должен успеть среагировать. Разработчикам же модулей роботов рекомендуется не упускать из внимания тот факт, что возможна передача ряда одинаковых значений для той или иной оси только лишь потому, что он (ряд) был передан управляющим устройством.

4.3 Рекомендации по выбору осей робота для режима ручного управления

Данный раздел адресован разработчикам роботов и разработчикам модулей роботов для среды RCML. При выборе осей робота, для которых предоставляется управление, следует помнить о так называемой проблеме «альфа-5», справедливой для промышленных роботов, использующих шестиосевую кинематику, когда для незначительного перехода в декартовых координатах робот выполняет значительный переход в координатах осей двигателей. Причем часто это наиболее справедливо для двигателя пятой оси робота, откуда и следует название. Однако принцип этой проблемы может быть распространен на довольно широкий диапазон роботов, в том числе даже на такого простого гусеничного робота, рассмотренного ранее.

Данный принцип гласит, что незначительное изменение целевого значения оси, по которой робот должен занять новое положение, должно приводить к пропорциональным незначительным изменениям в осях поворота двигателей или узлов робота, по возможности создавая всего один этап работы задействованных двигателей в одном направлении, то есть без выполнения одним и тем же двигателем повторного разгона и торможения.

В противном слчае возможны резкие ускорения частей и механизмов робота, а небольшие изменения предполагают большую частоту их появления, и в сумме это может вызвать сильный износ и даже поломку робота или повреждение элементов окружающей его среды и людей.

В приведенном примере с гусеничным роботом данный принцип соблюдается. Однако если его нарушить и выбрать осями робота, например, стандартные декартовые оси пространства X и Y, описывающие плоскость, в которой передвигается робот, см. рисунок 6, то можно получить следующий ряд негативных эффектов.

 

Рисунок 6 Пример выбора осей робота

Например, незначительное положительное изменение в оси X в текущем положении потребовало бы от механики робота сначала развернуть робот вправо на четверть оборота и затем передвинуть его вперед. Каждый двигатель должен будет выполнить два сеанса работы: один для поворота, другой для движения, причем двигателю правой гусеницы пришлось бы ещё сменить направление вращения после поворота, что значительно увеличивает время выполнения роботом полученной команды, а, следовательно, снижает скорость отклика робота.

Дополнительно выбор таких осей перемещения для робота ведет к неопределенности, поскольку в новое положение можно перейти разными путями:

  • повернуть вправо на четверть оборота и проехать вперед;
  • повернуть влево на три четверти оборота и проехать назад.

В данном случае уже потребуется закладка в робота алгоритма выбора пути, который должен будет выполняться каждый раз при получении нового значения по оси и каждый раз отнимать часть процессорного времени, увеличивая время реакции робота.

5 Написание собственных новых функций для роботовНаверх

Написание собственных функций для уже существующих роботов — одна из возможностей языка RCML. Однако, следует отметить, что по всем канонам программирования новые функции должны строиться на тех, что предоставил разработчик робота через модуль робота для языка RCML. Данная возможность очень удобна для унифицирования имен и параметров одинаковых функций и роботов с целью их последующего использования через абстрактного робота. А если разработчик робота предусмотрительно оставил доступ к низкоуровневым функциям робота через модуль робота, то вполне возможно и расширение высокоуровневого функционала робота.

5.1 Написание функции для конкретного класса роботов

Задание новой функции робота начинается с ключевого слова function, далее через разделитель следует наименование класса робота, для которого создается новая функция, затем следует знак «::», затем следует имя новой функции и потом в круглых скобках список параметров, который может быть пустым. После списка параметров в фигурных скобках следует код функции – список её операторов. Синтаксис задания функции робота:

function класс_робота::имя_функции(список_параметров) {
	список_операторов
}

Пример задания новой функции sum для типа робота класса test:

function robot_test::sum(a, b) {
	c = a + b;
	robot->do_something(c);
	return c;
}

Задание функции робота очень похоже на задание обычной функции в языке RCML, однако выполнение такой функции имеет ряд существенных различий.

Ключевое отличие заключается в том, что функция робота выполняется в контексте конкретного экземпляра робота и его класса, поэтому невозможны обращения к другим роботам, и, соответственно, использование классов роботов запрещено. Для обращения к роботу, в контексте которого выполняется функция, используется абстрактный робот (третья строка приведенного примера). Разумеется, все вызываемые функции робота через абстрактного робота в рамках данной функции должны быть у данного класса робота, то есть их либо должен предоставлять модуль робота, либо они должны быть описаны в подключаемых библиотеках или других функциях в исходном тексте в данной программе.

В случае если в данной функции робота не происходит обращения к роботу, в рамках которого выполняется функция, для данной функции все равно будет зарезервирован реальный физический робот указанного класса.

Дополнительно в рамках функций роботов запрещено использование специальных переменных за ненадобностью, так как робот, в контексте которого выполняется данная функция, всегда доступен через обращение к абстрактному роботу.

В функции робота можно менять режимы выполнения других функций робота обычными способами. Подробнее об режимах выполнения функций и способах их изменения читайте в разделе «Указание режимов выполнения функций».

5.2 Написание функции для нескольких классов роботов

Задание новой функции сразу для нескольких классов роботов аналогично заданию новой функции для одного робота, за исключением того, что требуемые классы роботов указываются через запятую. Пример задания функции сразу для двух классов роботов test и tarakan:

function robot_test, robot_tarakan::sum(a, b) {…

Указываемые классы роботов для данной функции должны обладать всеми теми функциями, которые вызываются через абстрактного робота в рамках данной, в противном случае данная новая функция является противоречивой и неприменимой для указанного набора классов роботов.

6 Указание режимов выполнения функцийНаверх

Исполнение функций, написанных на языке RCML, может выполняться в двух основных режимах:

  • с ожиданием выполнения функции – в данном случае интерпретатор, встретив команду вызова функции, просто переходит на начало вызываемой функции и последовательно выполняет её код;
  • без ожидания выполнения функции – в данном случае запускается дочерний поток, который начинает выполнять код вызываемой функции. Исполнение функции, в которой произошел вызов, продолжается с места следующим за вызовом.

В случае выполнения функции «без ожидания», создаваемый поток может быть перенесен в отдельное вычислительное ядро средствами ОС, и таким образом может быть получен эффект параллельного выполнения кода на языке RCML.

По умолчанию все функции вызываются в режиме с ожиданием выполнения функции. Этот режим является режимом по умолчанию. Сменить режим выполнения функций можно несколькими способами.

К первому способу относится применение флагов режима, каждый из которых является одним символом и которых, так же, как и режимов, всего два:

  • # - флаг выполнения функции с ожиданием;
  • ~ - флаг выполнения функции без ожидания.

Флаг режима должен указываться при вызове функции перед указанием имени функции. Примеры использования:

~do_something(1000);
#do_anything(1000);

Ко второму способу изменения режима выполнения функции относится использование системной функции set с указанием в качестве первого параметра строковой константы “behavior”, а в качестве второго параметра - флага режима # или ~. Вызов данной функции с такими параметрами переопределяет режим выполнения функций по умолчанию, то есть, если флаг режима не будет указан явно в вызове функции, то функция будет выполняться в режиме, заданном вторым параметром функции set. Пример использования функции set:

set(“behavior”,~);
//все последующие вызовы функций будут выполняться
//без ожидания завершения
do_something(1000);
do_something(1000);
do_something(1000);
//режим не меняется, так как флаг совпадает со значением по умолчанию
~do_something(1000);
//явное изменение режима, но только для этого конкретного вызова функции
#do_something(1000);

Следует отметить, что функция не может быть вызвана в режиме без ожидания выполнения, если результат её вызова где-либо используется, например, сохраняется в переменную или участвует в выражении. В данном случае такая функция будет принудительно вызвана в режиме с ожиданием выполнения, независимо от настроек режима по умолчанию. Простановка же флага режима перед вызовом функции, результат которой используется, запрещена на уровне синтаксических правил, т.е. при попытке выполнения следующего примера компилятор выдаст ошибку:

function sum(a, b) {
	return a+b;
}
function main() {
	r = ~sum(1,2);
}

Выполнение системных функций (из модуля system) кроме функции send_package, о которой будет подробнее рассказано в следующем разделе "Особенности выполнения функций роботами в разных режимах", также всегда происходит в режиме «с ожиданием выполнения» и игнорированием флагов режима перед вызовом функции.

Если какая-либо функция была вызвана без ожидания выполнения, т.е. становится выполняемой параллельно, то значением режима выполнения по умолчанию в рамках данной функции остается «с ожиданием выполнения», т.е. все вызываемые в ней функции выполняются с ожиданием в её потоке, если не было явно указано изменение режима с помощью приемов, рассмотренных выше.

7 Особенности выполнения функций роботами в разных режимахНаверх

Прежде чем рассматривать режимы выполнения функций роботом, необходимо понять, как передаются команды представлению робота в среде RCML, которое уже в свою очередь передает команды физическому роботу. Передача команд физическому роботу находится в зоне ответственности модуля робота, а передача команд представлению робота – в зоне ответственности среды RCML. Каждое представление робота имеет очередь команд. При выполнении интерпретатором вызовов функций робота данная очередь заполняется командами с указанием выполнения требуемых функций. Представление робота читает команды последовательно, передавая их далее модулю робота, чтение следующей команды будет происходить только после того как модуль робота сообщил о завершении выполнения очередной функции. При этом передача команд представлению робота средой RCML может выполняться в двух основных режимах:

  • с ожиданием выполнения функции – при вызове функции робота интерпретатор RCML помещает команду в очередь команд представления робота и ожидает от него ответ об успешности или не успешности выполнения именно этой команды;
  • без ожидания выполнения функции – в данном режиме интерпретатор RCML также помещает команду в очередь команд представления робота, но не дожидается сообщения о её выполнении и продолжает выполнение основной программы.

Очевидно, что режимы выполнения функций роботом совпадают с режимами выполнения функций в среде RCML, поэтому управлять режимом исполнения функций роботом можно теми же средствами, что и для управления режимом исполнения функций средой RCML.

Пример использования флагов режима:

~robot_test->do_something(1000);
 #robot_test->do_something(1000);
@r = robot_test;
~@r->do_something(1000);
#@r->do_something(1000);

Пример использования системной функции set:

@r = robot_test;
set(“behavior”,~);
//все последующие вызовы функций робота будут выполняться
//без ожидания завершения
@r->do_something(1000);
@r->do_something(1000);
@r->do_something(1000);
//режим не меняется, так как флаг совпадает со значением по умолчанию
~@r->do_something(1000);
//явное изменение режима, но только для этого конкретного вызова функции
#@r->do_something(1000);

Следует отметить, что вполне возможна ситуация, когда очередь команд представления робота заполнена командами без ожидания выполнения, и при этом поступает команда с ожиданием выполнения. В таком случае интерпретатор RCML дождется сначала выполнения всех команд, предшествующих команде с ожиданием выполнения, а затем выполнения и этой команды, и только потом продолжит выполнение основной программы.

По аналогии с вызовом обычных функций, функция робота не может быть вызвана в режиме без ожидания выполнения, если результат её вызова где-либо используется.

Оператор освобождения робота, как и вызов функции робота, представляет собой передачу команды роботу, только уже системного типа – на освобождение. Поэтому к оператору освобождения робота тоже применим весь механизм флагов выполнения:

~delete @r;
#delete @r;

Ранее в разделе "Высвобождение задействованного робота", отмечалось, что при достижении конца функции интерпретатором роботы, использованные в ней и не освобожденные через оператор delete, будут освобождены интерпретатором автоматически. Такое освобождение робота тождественно передаче роботу команды на освобождение с ожиданием выполнения, т.е. интерпретатор при достижении конца функции дождется завершения выполнения всех команд всеми задействованными в этой функции роботами. Чтобы интерпретатор не дожидался завершения выполнения роботом всех переданных ему (роботу) команд, нужно явно передать команду роботу на освобождение без ожидания её выполнения. Такое действие как бы вычеркивает робота из списка роботов, освобождения которых нужно дождаться. Однако при достижении конца исполняемой программы, интерпретатор, прежде чем завершить свою работу, дождется освобождения всех роботов, независимо от того, в каком режиме они выполняют свои функции.

8 Пакетная передача команд роботамНаверх

Как отмечалось ранее, у представления робота в среде RCML есть очередь команд, которая наполняется командами путем вызова функций робота из кода на RCML. При поступлении команды в пустую очередь она (команда) почти сразу же будет передана роботу на исполнение. Пока исполняется первая команда, все вновь поступившие команды становятся в очередь. Такое происходит потому, что робот выполняет функцию в материальном мире обычно медленнее, чем RCML интерпретатор успевает выполнить очередной код на RCML и дойти до следующего вызова функции робота, т.е. обычно действия робота "медлительнее" действий вычислительного процессора.

Однако бывает иная ситуация, когда роботу необходимо выполнить серию быстрых перемещений без остановки, а расчет параметров этих перемещений занимает больше времени, чем выполняется перемещение. Тогда эффективнее заранее рассчитать параметры перемещений и передать роботу сразу пакет команд с рассчитанными параметрами, чтобы робот не «подвисал» в ожидании очередной команды. Бывают ситуации, что сам механизм вызова функций работает медленнее, чем робот исполняет команды, и возникает задержка в быстрой серии перемещений.

Чтобы скомпенсировать этот эффект, был введен механизм пакетной передачи команд роботу. Команды, получаемые посредством вызовов функций робота, можно скомпоновать в единый пакет и передать его целиком представлению робота. Чтобы отправить команду в пакет, нужно поставить перед вызовом функции символ «>». Чтобы отправить пакет на выполнение, нужно вызвать системную функцию send_package().

Пример:

//отправка команды в пакет
>robot_test->do_something(1000);
//отправка пакета на выполнение
system.send_package();

В данном примере сначала будет послан запрос на свободного робота класса test, и только когда робот будет найден, функция будет передана в пакет, и затем пакет будет отправлен. Как и в вызове функций робота, при пакетной передаче команд роботы исполнители резервируются заранее. После вызова функции send_package возможно формирование нового пакета, в том числе и не дожидаясь исполнения предыдущего пакета. Подробнее об этом далее.

Как уже известно, в ходе выполнения предыдущего примера в пакет будут отправлены две команды, хотя вызов функции всего один. Это непосредственно команда выполнения функции и команда на освобождение. В пакет команд для одного робота можно включить несколько вызовов функций. Однако, очевидно, что для этого уже надо использовать специальную переменную:

@r = robot_tarakan;
>@r->move(1, 100);
>@r->move(1, 100);
>@r->move(1, 100);
system.send_package();

После выполнения пакета команд кода, робот, связанный с переменной @r, не будет освобожден. Его можно будет использовать далее и освободить явно через оператор delete, или неявно и автоматически при достижении конца функции интерпретатором. Однако команду освобождения робота также можно включить в пакет:

@r = robot_tarakan;
>@r->move(1, 100);
>@r->move(1, 100);
>@r->move(1, 100);
>delete @r;
system.send_package();

Теперь робот будет освобожден в ходе выполнения пакета, и в коде после вызова функции send_package, робот не будет более доступен.

Возможно составление пакета сразу для двух роботов, команды из этого пакета будут переданы сразу двум представлениям роботов, дополнительно можно ещё и комбинировать типы вызовов функций:

>robot_test->do_something(1000);
@r = robot_test;
>@r->do_something(1000);
>delete @r;
system.send_package();

Другой пример:

>robot_test->do_something(1000);
>robot_test->do_something(1000);
system.send_package();

Согласно данному примеру, будут задействованы два робота одновременно, а не один и тот же два раза подряд. В таком случае выполнение первых команд в очереди каждого представления робота начнётся одновременно.

Данный механизм позволяет синхронизировать начало выполнения разными роботами своих команд, в отдельных случаях добиться синхронизации действий (в рамках возможностей используемого робототехнического комплекса, включая ОС и прочее ПО). Например:

@r1 = robot_test;
@r2 = robot_test;
>@r1->do_something(1000);
>@r2->do_something(1000);
system.send_package();
>@r1->do_anything(1000);
>@r2->do_anything(1000);
system.send_package();

В каждом пакете содержится по одной функции для каждого робота, интерпретатор отправляет команды на выполнение одновременно и ждет завершения выполнения команд обоими представлениями роботов перед сбором команд в следующий пакет.

При особом проектировании модуля робота можно добиться эффекта выполнения роботом одновременно нескольких действий с ожиданием завершения всей группы команд. Такой эффект может быть актуален для передвижных роботов, когда в процессе перехода в новую точку пространства робот выполняет какое-то ещё действие, например, наводит орудие, ведет огонь и пр.

Важно отметить, что пакет команд существует только в контексте текущей функции, т.е. у каждой функции он свой:

function foo() {
	>robot_test->do_something(1000);
	>robot_test->do_something(1000);
}
function main() {
	foo();
	system.send_package();
}

В ходе выполнения данного примера команды, помещаемые в пакет в функции foo, никогда не будут выполнены, т.к. пакет будет уничтожен с завершением выполнения данной функции. А функции main будет отправлен пустой пакет. При этом два робота будут задействованы и до конца программы будут бездействовать, т.к. команды на их освобождение были помещены в пакет, который не был исполнен. Это очередной пример утечки роботов на RCML.

Ранее отмечалось, что функция send_package принимает один параметр, это флаг режима выполнения, который указывает интерпретатору, как выполнить данный пакет:

  • # - интерпретатор дождется выполнения всего пакета команд:
system.send_package(#);
  • ~ - интерпретатор не будет ждать выполнения пакета команд и сразу после отправки пакета продолжит выполнение кода текущей функции:
system.send_package(~);

Дополнительно функция send_package единственная системная функция, которая учитывает флаг выполнения перед её вызовом, в том числе установленный флаг выполнения по умолчанию:

// складываем команду в пакет
>robot_test->do_something(1000);
// отправляем пакет без ожидания завершения
~system.send_package();
// формируем новый пакет, хотя предыдущий ещё выполняется
>robot_test->do_something(1000);
// меняем флаг выполнения по умолчанию
system.set(“behavior”, ~);
// снова отправляем пакет без ожидания, уже два пакета в работе
system.send_package();
// формируем очередной пакет
>robot_test->do_something(1000);
// а теперь отправляем пакет с ожиданием его выполнения
system.send_package(#);

Как видно из примера, наивысшим приоритетом среди способов задания режима выполнения функций в пакете является указание флага режима в качестве аргумента функции send_package, затем следует явное указание флага режима перед вызовом функции, и уже наименьший приоритет имеет флаг режима выполнения, установленный по умолчанию в рамках текущей функции.

9 Коммуникация с ОСНаверх

9.1 Передача параметров в программу на RCML

В RCML программу можно передавать данные из ОС через параметры командной строки, однако таким образом на данном этапе развития языка передаются только вещественные типы данных. Чтобы иметь доступ к переданным через командную строку параметрам в коде RCML, нужно в функции main добавить необходимые параметры.

Передача значений в эти параметры функции main осуществляет путем добавления значения параметра в команду вызова RCML интерпретатора после указания файла с PC кодом. Общий вид передачи параметра со значением следующий:

-Pимя_параметра=значение_параметра

В качестве примера был создан файл test.rcml со следующим содержимым:

function main(foo, bar) {
	sum = foo + bar;
	system.echo(“foo + bar = ”, sum, “\n”);
}

Команда компиляции RCML файла:

rcml_compiler test.rcml test.pc

Команда выполнения RCML программы с передачей значения параметру foo равным 1, и bar равным 3.5:

rcml_interpreter test –Pfoo=1 –Pbar=3.5

Результатом выполнения программы будет:

foo + bar = 4.5

При этом порядок передачи значений параметров не важен, т.к. они передаются по имени. Параметры, значения для которых не были переданы, будут равны 0.0.

При выполнении следующего примера:

rcml_interpreter test –Pfoo=1

Будет получен результат:

foo + bar = 1

В случае если было передано значение для параметра, которого не существует, то будет выдана ошибка при попытке выполнения RCML программы.

Следующий пример содержит ошибку, т.к. параметра err не существует:

rcml_interpreter test –Pfoo=1 –Perr=2.35

9.2 Передача значений из программы из RCML в ОС

Передача данных из RCML в ОС возможна двумя путями:

9.3 Передача исключений (ошибки) из программы в ОС

Передача исключений (ошибки) происходит посредством выброса исключения без его перехвата до самого верхнего уровня, т.е. до функции main включительно. При этом, произойдет завершение работы RCML программы с кодом 1, значение исключения передано не будет. О механизме обработки и передачи исключений подробнее в разделе "Исключения".

10 Создание файла библиотеки RCMLНаверх

Для создания библиотеки требуется использовать следующую номенклатуру описания создаваемого файла.

Самой первой строкой должен быть указан идентификатор интерфейса библиотеки (IID) - уникальный набор байт длиной 32 байта, характеризующий версию интерфейса библиотеки, т.е. текущий набор функций, которые предоставляет библиотека, и их параметров. Данный IID должен быть уникален, т.к. интерпретатор различает разные библиотеки только по данному параметру. Для придания большей уникальности рекомендуется использовать все 32 байта допустимой длины. Прочие байты, следующие по счету за 32-м, будут отброшены.

Синтаксис:

IID “идентификатор_интерфейса”

Пример названия идентификатора библиотеки:

IID “test_lib_v1.0”

При написании функций библиотеки программист может указать, какие из них следует экспортировать, т.е. делать доступными для вызова из других программ, как в разделе «Вызов функции робота». Пометить функцию для экспорта можно, проставляя ключевое слово export перед ключевым словом function:

export function имя_функции(список_параметров) {
	список_операторов
}

Экспорт функций роботов происходит аналогично:

export function класс_робота::имя_функции(список_параметров) {
		список_операторов
}

Пример листинга библиотеки:

IID "test_lib_v1.0"
export function sum(a,b){
	c = a + b;
	return c;
}
export function robot_test::user_function(s) {
	robot->print("Robot delay\n", 1000);
	robot->print("Robot Func All right\n", 0);
}

Следует помнить, что включение библиотеки в другую программу создает в этой программе зависимость от всех использованных во включаемой библиотеке модулей и прочих библиотек. Т.е. для исполнения такой программы интерпретатору потребуются модули и библиотеки с таким же IID, которые были использованы при её (программы) компиляции. Зависимость от IID не есть зависимость от конкретного файла модуля или библиотеки. Библиотека или модуль может быть изменена, улучшена или ухудшена, но если набор функций и их параметров, экспортируемых в среду RCML (т.е. IID), остался неизменным, то такая библиотека считается равной исходной. Подробнее об механизме IID в разделе "Подробнее об интерфейсных идентификаторах".

11 Перечень зарезервированных ключевых словНаверх

break

catch

continue

define

delete

else

exit

export

function

if

IID

include

include_lib

loop

return

robot

throw

try

12 Синтаксическая карта языка RCMLНаверх

ПРОГРАММА: IID ЗАГОЛОВКИ

IID:
|	IID_KEYWORD СТРОКА

ЗАГОЛОВКИ:
|	ЗАГОЛОВКИ INCLUDE
|	ЗАГОЛОВКИ DEFINE 

INCLUDE:
	include СТРОКА
	include_lib ИДЕНТИФИКАТОР СТРОКА

ПРОГРАММА: ФУНКЦИИ

ФУНКЦИИ:
	ФУНКЦИИ ФУНКЦИЯ

ФУНКЦИЯ:   ФЛАГ_ЭКСПОРТА function СПИСОК_РОБОТОВ :: ИДЕНТИФИКАТОР '(' ЛИСТ_ИДЕНТИФИКАТОРОВ ')' БЛОК_КОДА
|          ФЛАГ_ЭКСПОРТА function ИДЕНТИФИКАТОР '(' ЛИСТ_ИДЕНТИФИКАТОРОВ ')' БЛОК_КОДА

ФЛАГ_ЭКСПОРТА:
	export

СПИСОК_РОБОТОВ: ROBOT_ID
	СПИСОК_РОБОТОВ ',' ROBOT_ID

ЛИСТ_ИДЕНТИФИКАТОРОВ:
|	ИДЕНТИФИКАТОР
|	ЛИСТ_ИДЕНТИФИКАТОРОВ ',' ИДЕНТИФИКАТОР

БЛОК_КОДА: '{' ОПЕРАТОРЫ '}'

ОПЕРАТОРЫ: ОПЕРАТОР
|	ОПЕРАТОРЫ ОПЕРАТОР

ОПЕРАТОР: OPER ';'
|	if '(' ВЫРАЖЕНИЕ ')' БЛОК_КОДА
|	if '(' ВЫРАЖЕНИЕ ')' БЛОК_КОДА else БЛОК_КОДА
|	loop БЛОК_КОДА
|	try БЛОК_КОДА
|	try БЛОК_АРГУМЕНТОВ БЛОК_КОДА
|	try БЛОК_КОДА catch БЛОК_КОДА
|	try БЛОК_АРГУМЕНТОВ БЛОК_КОДА catch БЛОК_КОДА
|	try БЛОК_КОДА catch '(' ИДЕНТИФИКАТОР ')' БЛОК_КОДА
|	try БЛОК_АРГУМЕНТОВ БЛОК_КОДА catch '(' ИДЕНТИФИКАТОР ')' БЛОК_КОДА

OPER:	ФЛАГ_РЕЖИМА_ВЫПОЛНЕНИЯ ССЫЛКА_НА_РОБОТА -> ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ФЛАГ_РЕЖИМА_ВЫПОЛНЕНИЯ ССЫЛКА_НА_РОБОТА -> '.' ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ФЛАГ_РЕЖИМА_ВЫПОЛНЕНИЯ ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ФЛАГ_РЕЖИМА_ВЫПОЛНЕНИЯ ИДЕНТИФИКАТОР '.' ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ССЫЛКА_НА_РОБОТА -> ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ССЫЛКА_НА_РОБОТА -> '.' ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ИДЕНТИФИКАТОР '.' ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ВЫРАЖЕНИЕ
|	break
|	continue
|	exit
|	exit ВЫРАЖЕНИЕ
|	return
|	return ВЫРАЖЕНИЕ
|	delete ПЕРЕМЕННАЯ_РОБОТА
|	ФЛАГ_РЕЖИМА_ВЫПОЛНЕНИЯ delete ПЕРЕМЕННАЯ_РОБОТА
|	throw
|	throw ВЫРАЖЕНИЕ
|	ПРИСВОЕНИЕ_РОБОТА

ПРИСВОЕНИЕ_РОБОТА: ПЕРЕМЕННАЯ_РОБОТА '=' ПРИСВОЕНИЕ_РОБОТА
|	ПЕРЕМЕННАЯ_РОБОТА '=' ССЫЛКА_НА_РОБОТА

ВЫРАЖЕНИЕ:   ВЫРАЖЕНИЕ1
|	ИДЕНТИФИКАТОР '=' ВЫРАЖЕНИЕ

ВЫРАЖЕНИЕ1:  ВЫРАЖЕНИЕ2
|	ВЫРАЖЕНИЕ1 == ВЫРАЖЕНИЕ2
|	ВЫРАЖЕНИЕ1 <= ВЫРАЖЕНИЕ2
|	ВЫРАЖЕНИЕ1 >= ВЫРАЖЕНИЕ2
|	ВЫРАЖЕНИЕ1 != ВЫРАЖЕНИЕ2
|	ВЫРАЖЕНИЕ1 '>' ВЫРАЖЕНИЕ2
|	ВЫРАЖЕНИЕ1 '<' ВЫРАЖЕНИЕ2
|	ВЫРАЖЕНИЕ1 && ВЫРАЖЕНИЕ2
|	ВЫРАЖЕНИЕ1 || ВЫРАЖЕНИЕ2

ВЫРАЖЕНИЕ2:  ТЕРМ
|	ВЫРАЖЕНИЕ2 '+' ТЕРМ
|	ВЫРАЖЕНИЕ2 '-' ТЕРМ

ТЕРМ:	ЗНАЧЕНИЕ
|	ТЕРМ '*' ЗНАЧЕНИЕ
|	ТЕРМ '/' ЗНАЧЕНИЕ
|	ТЕРМ '%' ЗНАЧЕНИЕ

ЗНАЧЕНИЕ:    NUM
|	'-' ЗНАЧЕНИЕ
|	'!' ЗНАЧЕНИЕ
|	'(' ВЫРАЖЕНИЕ1 ')'
|	ИДЕНТИФИКАТОР
|	ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ИДЕНТИФИКАТОР '.' ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ССЫЛКА_НА_РОБОТА -> ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ
|	ССЫЛКА_НА_РОБОТА -> '.' ИДЕНТИФИКАТОР БЛОК_АРГУМЕНТОВ

ССЫЛКА_НА_РОБОТА: ПЕРЕМЕННАЯ_РОБОТА
|	ROBOT_ID МАРКЕР_ВЫБОРА
|	robot МАРКЕР_ВЫБОРА

МАРКЕР_ВЫБОРА:
|	'<' ЛИСТ_ИДЕНТИФИКАТОРОВ '>'

ФЛАГ_РЕЖИМА_ВЫПОЛНЕНИЯ:  #
|	~
|	'>'

БЛОК_АРГУМЕНТОВ: '(' АРГУМЕНТЫ ')'

АРГУМЕНТЫ:
|	АРГУМЕНТ
|	АРГУМЕНТЫ ',' АРГУМЕНТ

АРГУМЕНТ:	ВЫРАЖЕНИЕ
|	СТРОКА
|	ФЛАГ_РЕЖИМА_ВЫПОЛНЕНИЯ
|	ССЫЛКА_НА_РОБОТА

16 Список принятых сокращенийНаверх

Ниже приведен список принятых сокращений в данной книге в порядке первого их упоминания в тексте:

RCML - Robot Control Meta Language;

API – Application Programming Interface;

БД – база данных;

ПО – программное обеспечение;

ОС – операционная система;

PC – pseudo code.

17 Примеры подключения модулей к RCMLНаверх

RCML позволяет скооперировать разных роботов в рамках одной задачи. Таким образом, возможно реализовать одновременное выполнение группой роботов нескольких задач, а также переключение одного робота между несколькими задачами.

Решения технологических задач, реализованные на языке RCML, обеспечивают одинаковый результат для роботов с идентичными функциональными возможностями.

Среда RСML имеет ряд точек ввода/вывода (API) для интеграции с программными продуктами и различными системами, включая роботов. Дополнительно может быть расширен функционал самого языка через добавление в него новых функций путем подключения модулей.

Взаимодействие RCML с устройствами управления и исполнения

Модули расширения RCML бывают трех типов:

Далее более подробно будут рассмотрены примеры подключения каждого типа модуля.

17.1 Пример подключения модулей роботов

17.1.1 Быстрое подключение модуля робота test к RCML

Модуль робота test предназначен для имитации физического робота и проверки подключенных компонентов и программ.

Для включения модуля робота test необходимо в секции [robot_modules] конфигурационного файла RCML добавить свойство module и установить его равным значению test в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML". Дополнительной конфигурации модулю test не требуется.

Далее приведен текст программы на языке RCML. Программа обращается к тестовому роботу, и отправляет ему команду на выполнение функции do_ something(). Более подробно о том, что означает эта функция написано далее

function main() {
	@lr = robot_test; 
	@lr->do_something(1000);
}

Во время выполнения данной программы, тестовый робот имитирует физическое выполнение действия, которое бы заняло 1 секунду времени.

После подключения модуля программисту доступны следующие функции:

Наименование

Кол-во параметров

Возвращает значение

Бросает исключение

Описание

none

0

Нет

Нет

Ничего не делающая функция.

do_something

1

Нет

Нет

В качестве параметра функция принимает кол-во миллисекунд, на которые будет остановлен процесс выполнения программы.

get_some_value

1

Да

Нет

Возвращает значение, переданное на вход в качестве параметра.

throw_exception

0

Нет

Да

При вызове бросает исключение.

print

2

Нет

Нет

Принимает на вход, в качестве первого, строковый параметр и выводит его в консоли, спустя задержку, указанную в миллисекундах во втором параметре.

Кроме этого, тестовый робот имеет также оси:

Наименование

Верхняя граница

Нижняя граница

Примечание

X

100

-100

Y

1

0

Бинарная

Z

100

0

 

17.1.2 Быстрое подключение модуля lego_ev3 к RCML

Lego Mindstorms EV3 – третье поколение конструктора Lego.

Более подробно о конструкторе и его возможностях на официальном сайте компании Lego:

Модуль робота lego_ev3 используется для подключения блоков Lego Ev3 к RCML

    1. Для включения модуля lego_ev3 необходимо добавить запись в секцию [robot_modules] конфигурационного файла RCML свойство module и установить его равным lego_ev3 в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML"
    2. Следует произвести сопряжение Bluetooth-адаптера с модулем Lego Ev3.
    3. После сопряжения, следует зайти в свойства добавленного устройства. Необходимо узнать адрес COM-порта, с которым осуществляется взаимодействие.
  1. Далее следует произвести настройку модуля. А именно необходимо указать, через какой COM-порт следует взаимодействовать с модулем Ev3. Нужно перейти в каталог с модулями роботов (robot_modules), а затем в каталог модуля Ev3 (lego_ev3).
  2. В директории модуля lego_ev3 нужно создать файл config.ini со следующим содержанием:
[connections]
connection = COM6
[options]
dynamic_connection = 0

Файл настроек config.ini включает в себя следующие свойства, разнесенные на две секции [connections] и [options]:

В секции [connections] отражаются номера портов подключенных роботов, на каждого робота заводится надпись вида: 

connection = COMX, где X это номер порта, который используется в свойствах подключения.

Секция [options] содержит свойство dynamic_connection.

dynamic_connection используется для динамического подключения роботов, то есть позволяет менять состав используемых роботов прямо в момент исполнения программы. Однако каждое задействование робота занимает время на подключение к нему. Если значение dynamic_connection установлено равным 1, то Bluetooth соединение с роботом будет устанавливаться в момент запроса робота и разрываться при его освобождении, что может вызывать значительную временную задержку при задействовании робота в  RCML программе.

Если значение dynamic_connection установлено равным 0, то Bluetooth соединение с роботом будет устанавливаться в момент старта программы и разрываться при ее завершении.

По умолчанию будет присвоено значение 0.

Далее приведен пример текста программы на языке RCML. Программа обращается к роботу Lego и взаимодействует с двигателем, подключенным к блоку Ev3. Текст программы выглядит следующим образом:

function main() {
	@lr = robot_lego_ev3;
	@lr->motorMoveTo("B",10,200,0);
}

Первая строка создаст переменную, к которой будет прикреплен Lego робот.

Вторая строка переместит мотор B в позицию 200 со скоростью 10 не используя тормоз.

Кроме этого Lego робот, может быть представлен для RCML, как «Track Vehicle», что позволит обращаться к двум моторам робота Lego, как к единому целому и открывает дополнительные функции управления. Функция setTrackVehicle создана специально для роботов особых конфигураций, с двумя ведущими колесами и одним поворотным колесом/упором, или конфигураций роботов на гусеничном ходу, по 1 мотору на каждое колесо или гусеницу. Такой режим автоматизирует управление моторами для маневрирования робота. Для инициализации робота в режиме «Track Vehicle» необходимо использовать в программном коде функцию setTrackVehicle.

Далее приведен пример текста программы на языке RCML в которой создаётся «Track Vehicle» и происходит управление им.

function main() {
	@lr = robot_lego_ev3; 
	@lr->setTrackVehicle("B","C",1,1);
	@lr->trackVehicleForward(10);
	system.sleep(1000);
	@lr->trackVehicleOff();
}

В результате исполнения программы робот совершит симметричное вращение обоими двигателями, подключенными к портам B и С со скоростью 10. Более подробный список команд представлен далее.

В случае, если в коде программы не будет вызвана функция создания «Track Vehicle» setTrackVehicle, то при выполнении функции связанных с использованием «Track Vehicle» произойдет выброс исключения, который можно обработать при помощи конструкции try/catch, более подробно о котором написано в разделе "Исключения".

Существуют особенности, связанные с входящими значениями для функций модуля.

Для обращения к моторам A,B,C,D используются буквы "A","B","C" и "D" соответственно;

Для обращения к датчикам под номерами 1,2,3,4 используются соответствующие номера;

На параметры функций speed и percent наложены следующие ограничения:

  • speed принимает значения [-100;100];
  • percent принимает значения [0;100].

При превышении указанных ограничений вызываемая функция бросает исключение, которое можно обработать с помощью конструкции языка RCML. Более подробно об обработке исключений написано в разделе "Исключения"

Доступные функции робота приведены в таблице:

Определение

Описание

Пример

motorSetSpeed(
      motor,
      speed
  )

Задает мотору motor скорость speed

@lr->motorSetSpeed ("B",20); Задает мотору B скорость 20.

motorOff(
motor
  )

Выключает мотор motor без использования тормозов, т.е. мотор остановится не сразу.

@lr->motorOff("C"); Остановит моторC.

motorBrake(
motor
  )

Останавливает мотор motor, используя тормоза. Мгновенная остановка.

@lr->motorBrake("D"); Остановит мотор D.

motorSetDirection(
      motor,
      direction
  )

Устанавливает направление мотора motor. direction=0 задает направление мотора "назад". direction != 0 задает направление мотора "вперед"

@lr->motorSetDirection("A",0); Установит направление мотора А"назад".

motorGetDirection(
      motor
  )

Возвращает 1 если направление мотора motor установлено как "вперед", возвращает 0 если направление мотора motor установлено как "назад". Мотор остановится не сразу.

RecievedDirection = @lr->motorGetDirection("C");

motorMoveTo(
      motor,
      speed,
      position,
      brake
  )

Перемещает мотор motor в положение position со скоростью speed. brake = 0 - не использовать тормоз, brake != 0 - использовать тормоз.

@lr->motorMoveTo("B",10,200,0); Переместит мотор B в позицию 200 со скоростью 10 не используя тормоз.

motorGetTacho(
      motor
  )

Возвращает позицию мотора motor.

RecievedTacho = @lr->motorGetTacho("C");

motorResetTacho(
      motor
  )

Устанавливает текущую позицию мотора motor как нулевую.

@lr->motorResetTacho("C");

waitMotorToStop(
      motor
  )

Ждет пока остановится мотор motor.

@lr->waitMotorToStop("C");

waitMultiMotorsToStop(
      motorA,
      motorB,
      motorC,
      motorD
  )

Ждет пока остановится несколько моторов. Если motor != 0, то ждет остановки, если motor = 0, то не ждет.

@lr->waitMultiMotorsToStop(1,0,0,1); Ждет пока остановятся моторы А иD.

setTrackVehicle(
      motorLeft,
      motorRight,
      LeftReverse,
      RightReverse
  )

Логически соединяет 2 мотора motorLeft иmotorRight в Track Vehicle (гусеничный транспорт). Позволяет обращаться к этим моторам как к единому целому и открывает дополнительные функции управления Track Vehicle, имеющие префикс trackVehicle. Left и Right Reverse при значении != 0 задает моторам обратное направление.

@lr->setTrackVehicle("B","C",1,0); Логически соединяет моторы B и C в Track, при этом мотор B изменяет свое направление на обратное.

trackVehicleBackward(
      speed
  )

Track Vehicle движется назад со скоростью speed.

@lr->trackVehicleBackward(20);

trackVehicleForward(
      speed
  )

Track Vehicle движется вперед со скоростью speed.

@lr->trackVehicleForward(40);

trackVehicleOff()

Выключает моторы Track Vehicle. Моторы остановятся не сразу.

@lr->trackVehicleOff();

trackVehicleBrake()

Останавливает моторы Track Vehicle, используя тормоза.

@lr->trackVehicleBrake();

trackVehicleSpinLeft(
      speed
  )

Track Vehicle поворачивается влево вокруг своей вертикальной оси.

@lr->trackVehicleSpinLeft(10);

trackVehicleSpinRight(
      speed
  )

Track Vehicle поворачивается вправо вокруг своей вертикальной оси.

@lr->trackVehicleSpinRight(90);

trackVehicleTurnLeftForward(
      speed,
      percent
  )

Track Vehicle поворачивает влево, двигаясь вперед. Правый мотор будет иметь со скорость speed, а левый (speed - speed*percent/100). Таким образом если percent=0 то моторы будут иметь одинаковую скорость, а при percent=100 левый мотор будет иметь нулевую скорость.

@lr->trackVehicleTurnLeftForward(20, 50);

trackVehicleTurnRightForward(
      speed,
      percent
  )

Track Vehicle поворачивает влево, двигаясь вперед. Левый мотор будет иметь со скорость speed, а правый (speed - speed*percent/100). Таким образом если percent=0 то моторы будут иметь одинаковую скорость, а при percent=100 правый мотор будет иметь нулевую скорость.

@lr->trackVehicleTurnRightForward(10, 90);

trackVehicleTurnLeftReverse(
      speed,
      percent
  )

Track Vehicle поворачивает влево, двигаясь назад. Скорость правого мотора равна speed, а левого (speed - speed*percent/100)

@lr->trackVehicleTurnLeftReverse(10,20);

trackVehicleTurnRightReverse(
      speed,
      percent
  )

Track Vehicle поворачивает вправо, двигаясь назад. Скорость левого мотора равна speed, а правого (speed - speed*percent/100)

@lr->trackVehicleTurnRightReverse(50,50);

readSensor(
      sensor,
      mode
  )

Считывает показания сенсора под номером sensor в режиме mode. Для разных датчиков существует разное количество режимов.

@lr->readSensor(2,1); Считывает показания датчика подключенного к порту 2 в режиме 1.

isMotorRunning(
      motor,
      sleep
  )

Возвращает 1 если мотор motor включен и 0 если нет. Если sleep отлично от 0, то мотор будет опрошен с задержкой в 200 микросекунд.

@lr->isMotorRunning("B",1);

getMotorSpeed(
      motor,
      sleep
  )

Возвращает значение скорости мотора motor. Если sleep отлично от 0, то мотор будет опрошен с задержкой в 200 микросекунд.

@lr->getMotorSpeed("B",1);

Для модуля lego_ev3 доступно подключение датчиков 8-ми типов, индексы которых используются в командах языка RCML. Типы датчиков и их индексы представлены в таблице:

Датчик

Режим

Ультразвуковой

1 - режим определения расстояния в сантиметрах

2 - режим определения расстояния в дюймах

3 - режим прослушивания

Инфракрасный

1 - режим определения расстояния

2 - режим определения местоположения инфракрасного дистанционного пульта

3- режим определения нажатия кнопок на инфракрасном пульте

Цветовой

1 - режим определения интенсивности света

2 - режим определения цвета (см. таблицу цветов)

3- режим определения raw значения отраженного света

4 - режим определения отраженного света

Гироскопический

1 - режим определения угла в градусах

2 - режим определения угловой скорости в градусах в секунду

Датчик нажатия

1 - режим отслеживания нажатия

2 - режим вывода количества нажатий

Датчик Температуры

1 - режим измерения температуры по шкале Цельсия

2 - режим измерения температуры по шкале Фаренгейта

Датчик Звука

1 - режим измерения громкости звука в dB

2 - режим измерения громкости звука в dBA

Датчик Света

1 - режим измерения интенсивности

2 - режим измерения отраженного света

Цветовой датчик, имеет возможность вернуть код цвета. Коды возвращаемых цветом, представлены в таблице:

Цвет

Возвращаемое значение

Черный

1

Синий

2

Зеленый

3

Желтый

4

Красный

5

Белый

6

Коричневый

7

Всегда доступны следующие оси для управления блоком Ev3:

Ось

Верхняя граница

Нижняя граница

Описание

locked

1

0

Бинарная ось. Если её значение равно 1, то робот считается заблокированным и игнорирует изменение значений по любым другим осям.

speedMotorA

100

-100

Значение оси задает скорость мотора, подключенного к порту A.

speedMotorB

100

-100

Значение оси задает скорость мотора, подключенного к порту B.

speedMotorC

100

-100

Значение оси задает скорость мотора, подключенного к порту C.

speedMotorD

100

-100

Значение оси задает скорость мотора, подключенного к порту D.

moveMotorA

1000

-1000

Значение оси задает позицию, на которую повернется мотор A со скоростью 50.

moveMotorB

1000

-1000

Значение оси задает позицию, на которую повернется мотор B со скоростью 50.

moveMotorC

1000

-1000

Значение оси задает позицию, на которую повернется мотор C со скоростью 50.

moveMotorD

1000

-1000

Значение оси задает позицию, на которую повернется мотор D со скоростью 50.

В случае, использования робота Lego в режиме «Track Vehicle», робот имеет следующие оси робота, к которым можно подключиться для управления:

straight

100

-100

Значение оси задает скорость, с которой прямолинейно перемещается «Track Vehicle»

rotation

100

-100

Значение оси задает скорость, с которой «Track Vehicle» вращается вокруг своей вертикальной оси.

Робот Lego должен быть инициализирован в режим «Track Vehicle» прежде чем будет задействована ось straight или rotation, т.е. до включения режима ручного управления!

17.1.3 Быстрое подключение модуля lego_nxt к RCML

Lego Mindstorms NXT – второе поколение конструктора Lego.

Подробнее на официальном сайте конструктора: 

Модуль робота lego_nxt используется для подключения блоков Lego NXT к RCML. 

    1. Для включения модуля lego_nxt необходимо добавить запись в секцию [robot_modules] конфигурационного файла RCML свойство module и установить его равным lego_nxt в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML"
    2. Следует произвести сопряжение Bluetooth-адаптера с модулем Lego NXT.
    3. После сопряжения, следует зайти в свойства добавленного устройства. Необходимо узнать адрес COM-порта, с которым осуществляется взаимодействие.
  1. Далее следует произвести настройку модуля. А именно необходимо указать, через какой COM-порт следует взаимодействовать с модулем NXT. Нужно перейти в каталог с модулями роботов (robot_modules), а затем в каталог модуля NXT (lego_nxt).
  2. В директории модуля lego_nxt нужно создать файл config.ini со следующим содержанием:
[connections]
connection = COM6
[options]
dynamic_connection = 0

Файл настроек config.ini включает в себя следующие свойства, разнесенные на две секции [connections] и [options]:

В секции [connections] отражаются номера портов подключенных роботов, на каждого робота заводится надпись вида: 

connection = COMX, где X это номер порта, который используется в свойствах подключения.

Секция [options] содержит свойство dynamic_connection.

dynamic_connection используется для динамического подключения роботов, то есть позволяет менять состав используемых роботов прямо в момент исполнения программы. Однако каждое задействование робота занимает время на подключение к нему. Если значение dynamic_connection установлено равным 1, то Bluetooth соединение с роботом будет устанавливаться в момент запроса робота и разрываться при его освобождении, что может вызывать значительную временную задержку при задействовании робота в  RCML программе.

Если значение dynamic_connection установлено равным 0, то Bluetooth соединение с роботом будет устанавливаться в момент старта программы и разрываться при ее завершении.

По умолчанию будет присвоено значение 0.

Далее приведен пример текста программы на языке RCML. Программа обращается к роботу Lego и взаимодействует с двигателем, подключенным к блоку NXT. Текст программы выглядит следующим образом:

function main() {
	@lr = robot_lego_nxt;
	@lr->motorMoveTo("B",10,200,0);
}

Первая строка создаст переменную, к которой будет прикреплен Lego робот.

Вторая строка переместит мотор B в позицию 200 со скоростью 10 не используя тормоз.

Кроме этого Lego робот, может быть представлен для RCML, как «Track Vehicle», что позволит обращаться к двум моторам робота Lego, как к единому целому и открывает дополнительные функции управления. Функция setTrackVehicle создана специально для роботов особых конфигураций, с двумя ведущими колесами и одним поворотным колесом/упором, или конфигураций роботов на гусеничном ходу, по 1 мотору на каждое колесо или гусеницу. Такой режим автоматизирует управление моторами для маневрирования робота. Для инициализации робота в режиме «Track Vehicle» необходимо использовать в программном коде функцию setTrackVehicle.

Далее приведен пример текста программы на языке RCML в которой создаётся «Track Vehicle» и происходит управление им.

function main() {
	@lr = robot_lego_nxt; 
	@lr->setTrackVehicle("B","C",1,1);
	@lr->trackVehicleForward(10);
	system.sleep(1000);
	@lr->trackVehicleOff();
}

В результате исполнения программы робот совершит симметричное вращение обоими двигателями, подключенными к портам B и С со скоростью 10. Более подробный список команд представлен далее.

В случае, если в коде программы не будет вызвана функция создания «Track Vehicle» setTrackVehicle, то при выполнении функции связанных с использованием «Track Vehicle» произойдет выброс исключения, который можно обработать при помощи конструкции try/catch, более подробно о котором написано в разделе "Исключения".

Существуют особенности, связанные с входящими значениями для функций модуля.

Для обращения к моторам A,B,C,D используются буквы "A","B","C" и "D" соответственно;

Для обращения к датчикам под номерами 1,2,3,4 используются соответствующие номера;

На параметры функций speed и percent наложены следующие ограничения:

  • speed принимает значения [-100;100];
  • percent принимает значения [0;100].

При превышении указанных ограничений вызываемая функция бросает исключение, которое можно обработать с помощью конструкции языка RCML. Более подробно об обработке исключений написано в разделе "Исключения". 

Доступные функции робота приведены в таблице:

Определение

Описание

Пример

motorSetSpeed(
     motor,
     speed
  )

Задает мотору motor скорость speed

@lr->motorSetSpeed ("B",20); Задает мотору B скорость 20.

motorOff(
     motor
  )

Выключает мотор motor без использования тормозов, т.е. мотор остановится не сразу.

@lr->motorOff("C"); Остановит моторC.

motorBreak(
     motor
  )

Останавливает мотор motor, используя тормоза. Мгновенная остановка.

@lr->motorBreak("A"); Остановит мотор A.

motorSetDirection(
     motor,
     direction
  )

Устанавливает направление мотораmotor. direction=0 задает направление мотора "назад". direction != 0 задает направление мотора "вперед"

@lr->motorSetDirection("A",0); Установит направление мотора А"назад".

motorGetDirection(
     motor
  )

Возвращает 1 если направление мотораmotor установлено как "вперед", возвращает 0 если направление мотораmotor установлено как "назад". Мотор остановится не сразу.

RecievedDirection = @lr->motorGetDirection("C");

motorMoveTo(
     motor,
     speed,
     position,
     brake
  )

Перемещает мотор motor в положениеposition со скоростью speed. brake = 0 - не использовать тормоз, brake != 0 - использовать тормоз.

@lr->motorMoveTo("B",10,200,0); Переместит мотор B в позицию 200 со скоростью 10 не используя тормоз.

motorGetTacho(
     motor
  )

Возвращает позицию мотора motor.

RecievedTacho = @lr->motorGetTacho("C");

motorResetTacho(
     motor
  )

Устанавливает текущую позицию мотораmotor как нулевую.

@lr->motorResetTacho("C");

waitMotorToStop(
     motor
  )

Ждет пока остановится мотор motor.

@lr->waitMotorToStop("C");

waitMultiMotorsToStop(
     motorA,
     motorB,
     motorC
  )

Ждет пока остановится несколько моторов. Если motor != 0, то ждет остановки, если motor = 0, то не ждет.

@lr->waitMultiMotorsToStop(1,0,1); Ждет пока остановятся моторы А иС.

setTrackVehicle(
     motorLeft,
     motorRight,
     LeftReverse,
     RightReverse
  )

Логически соединяет 2 мотора motorLeft иmotorRight в Track Vehicle (гусеничный транспорт). Позволяет обращаться к этим моторам как к единому целому и открывает дополнительные функции управления Track Vehicle, имеющие префикс trackVehicle. Left и Right Reverse при значении != 0 задает моторам обратное направление.

@lr->setTrackVehicle("B","C",1,0); Логически соединяет моторы B и C в Track, при этом мотор B изменяет свое направление на обратное.

trackVehicleBackward(
     speed
  )

Track Vehicle движется назад со скоростьюspeed.

@lr->trackVehicleBackward(20);

trackVehicleForward(
     speed
  )

Track Vehicle движется вперед со скоростью speed.

@lr->trackVehicleForward(40);

trackVehicleOff()

Выключает моторы Track Vehicle. Моторы остановится не сразу.

@lr->trackVehicleOff();

trackVehicleBrake()

Останавливает моторы Track Vehicle, используя тормоза.

@lr->trackVehicleBrake();

trackVehicleSpinLeft(
     speed
  )

Track Vehicle поворачивается влево вокруг своей вертикальной оси.

@lr->trackVehicleSpinLeft(10);

trackVehicleSpinRight(
     speed
  )

Track Vehicle поворачивается вправо вокруг своей вертикальной оси.

@lr->trackVehicleSpinRight(90);

trackVehicleTurnLeftForward(
     speed,
     percent
  )

Track Vehicle поворачивает влево, двигаясь вперед. Правый мотор будет иметь со скорость speed, а левый (speed - speed*percent/100). Таким образом еслиpercent=0 то моторы будут иметь одинковую скорость, а при percent=100 левый мотор будет иметь нулевую скорость.

@lr->trackVehicleTurnLeftForward(20, 50);

trackVehicleTurnRightForward(
     speed,
     percent
  )

Track Vehicle поворачивает влево, двигаясь вперед. Левый мотор будет иметь со скорость speed, а правый (speed - speed*percent/100). Таким образом еслиpercent=0 то моторы будут иметь одинковую скорость, а при percent=100 правый мотор будет иметь нулевую скорость.

@lr->trackVehicleTurnRightForward(10, 90);

trackVehicleTurnLeftReverse(
     speed,
     percent
  )

Track Vehicle поворачивает влево, двигаясь назад. Скорость правого мотора равна speed, а левого (speed - speed*percent/100)

@lr->trackVehicleTurnLeftReverse(10,20);

trackVehicleTurnRightReverse(
     speed,
     percent
  )

Track Vehicle поворачивает вправо, двигаясь назад. Скорость левого мотора равна speed, а правого (speed - speed*percent/100)

@lr->trackVehicleTurnRightReverse(50,50);

isMotorRunning(
     motor,
     sleep
  )

Возвращает 1 если мотор motor включен и 0 если нет. Если sleep отлично от 0, то мотор будет опрошен с задержкой в 200 микросекунд.

@lr->isMotorRunning("B",1);

Для модуля lego_nxt доступны следующие функции опроса датчиков:

Определение

Описание

Режимы

readHiTecColor( port,mode)

Считывает показания HiTecColor сенсора на порту port в режиме mode.

1 - Возвращает значение красного цвета [0;255]

2 - Возвращает значение зеленого цвета [0;255]

3 - Возвращает значение синего цвета [0;255]

readHiTecCompass(port)

Считывает показания HiTecCompass сенсора на порту port.

Возвращает значение в градусах

readHiTecGyro( port)

Считывает показания HiTecGyro сенсора на порту port.

Возвращает угловое ускорение в градусах в секунду

readHiTecTilt( port,mode)

Считывает показания HiTecTilt сенсора на порту port в режиме mode.

1 - Возвращает целочисленное значение положения датчика по оси x

2 - Возвращает целочисленное значение положения датчика по оси y

3 - Возвращает целочисленное значение положения датчика по оси z

readNXTColor( port,mode)

Считывает показания NXTColor сенсора на порту port в режиме mode.

1 - Возвращат целочисленное значение, соответствующее таблице цветов

2 - Возвращает интенсивность красного цвета в процентах

3 - Возвращает интенсивность зеленого цвета в процентах

4 - Возвращает интенсивность синего цвета в процентах

5 - Возвращает интенсивность света в процентах

readNXTLight( port,mode)

Считывает показания NXTLight сенсора на порту port в режиме mode.

1 - Возвращает интенсивность света в виде целочисленного значения

2 - Возвращает интенсивность света в процентах

readNXTSonar( port,mode)

Считывает показания NXTSonar сенсора на порту port в режиме mode.

1 - режим определения расстояния в сантиметрах

2 - режим определения расстояния в дюймах

readNXTSound( port,mode)

Считывает показания NXTSound сенсора на порту port в режиме mode

1 - режим измерения громкости звука в dB

2 - режим измерения громкости звука в dBA

readNXTTouch( port,mode)

Считывает показания NXTTouch сенсора на порту port в режиме mode.

1 - режим отслеживания нажатия

2 - режим вывода количества нажатий

readRCXLight( port,mode)

Считывает показания RCXLight сенсора на порту port в режиме mode.

1 - режим измерения интенсивности

2 - режим измерения отраженного света

readRCXRotation(port)

Считывает показания RCXRotation сенсора на порту port.

Возвращает шаг поворота [-16;+16]

readRCXTemperature(port, mode)

Считывает показания RCXTemperature сенсора на порту port в режиме mode.

1 - режим измерения температуры по шкале Цельсия

2 - режим измерения температуры по шкале Фаренгейта

Цветовой датчик, имеет возможность вернуть код цвета. Коды возвращаемых цветом, представлены в таблице:

Цвет

Возвращаемое значение

Черный

1

Синий

2

Зеленый

3

Желтый

4

Красный

5

Белый

6

Всегда доступны следующие оси для управления блоком NXT:

Ось

Верхняя граница

Нижняя граница

Описание

locked

1

0

Бинарная ось. Если её значение равно 1, то робот считается заблокированным и игнорирует изменение значений по любым другим осям.

speedMotorA

100

-100

Значение оси задает скорость мотора, подключенного к порту A.

speedMotorB

100

-100

Значение оси задает скорость мотора, подключенного к порту B.

speedMotorC

100

-100

Значение оси задает скорость мотора, подключенного к порту C.

moveMotorA

1000

-1000

Значение оси задает позицию, на которую повернется мотор A со скоростью 50.

moveMotorB

1000

-1000

Значение оси задает позицию, на которую повернется мотор B со скоростью 50.

moveMotorC

1000

-1000

Значение оси задает позицию, на которую повернется мотор C со скоростью 50.

В случае, использования робота Lego в режиме «Track Vehicle», робот имеет следующие оси робота, к которым можно подключиться для управления:

Ось

Верхняя граница

Нижняя граница

Описание

straight

100

-100

Значение оси задает скорость, с которой прямолинейно перемещается Track Vehicle.

rotation

100

-100

Значение оси задает скорость, с которой Track Vehicle вращается вокруг своей вертикальной оси.

Робот Lego должен быть инициализирован в режим «Track Vehicle» прежде чем будет задействована ось straight или rotation, т.е. до включения режима ручного управления!

17.1.4 Быстрое подключение модуля uarm к RCML

uArm – это 4-х осевой манипулятор, миниатюрная версия промышленного робота ABB PalletPack IRB460

Изучить подробности о манипуляторе uArm можно на официальном сайте:

Модуль робота uarm используется для подключения робота uArm к RCML.

  1. Необходимо выполнить подключение робота uArm к компьютеру. Нужно перейти на сайт производителя в раздел Download Center, далее следует перейти в раздел Instructions и перейти в раздел Getting Started и далее выполнить инструкцию для подходящей модели uArm.
  2. Далее необходимо сменить программное обеспечение робота для работы с SDK С#. Инструкция быстрого старта по работе с SDK С#.
  3. Для включения модуля uarm необходимо добавить запись в секцию [robot_modules] конфигурационного файла RCML свойство module и установить его значение равным uarm в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML".
  4. Далее следует произвести настройку модуля. Необходимо указать, через какой COM-порт следует взаимодействовать с роботом. Для этого нужно перейти в каталог с модулями роботов (robot_modules), а затем в каталог модуля uarm.
  5. В директории модуля uarm нужно создать файл config.ini со следующим содержанием:
[main]
count_robots = 1
is_debug = 0
robot_port_0 = com3

Файл конфигурации модуля состоит из секции [main], которая включает в себя следующие свойства:

  • count_robots – свойство, качестве параметра принимающее количество роботов uArm (число) к которым необходимо будет подключиться.
  • is_debug – отображает в консоль дополнительную информацию о исполняемых функциях роботом uArm. Может принимать значение 0 или 1.
  • robot_port_X – содержит имя COM-порта, к которому подключен робот Х, причем отсчет роботов начинается с 0. Адрес порта должен быть указан в формате comY, где Y – порядковый номер порта, который был ранее использован в пунктах 1 и 2.

Далее приведен текст программы на языке RCML. Программа обращается к роботу uArm и включает вакуумную помпу на 5 секунд и выключает её:

function main() {
	@ur = robot_uarm;
	@ur-> pump_on();
	system.sleep(1000);
	@ur-> pump_off();
}

Доступные функции робота приведены в таблице:

Определение

Описание

Пример

move_to(X, Y, Z)

перемещает захват робота в точку с координатами X, Y, Z. Движение происходит с максимально возможной скоростью перемещения.

@Robot->move_to (10, 10, 10); перемещает захват робота в точку с координатами X=10, Y=10, Z=10

pump_on()

включает помпу захвата

@Robot->pump_on(); включает помпу захвата

pump_off()

вкылючает помпу захвата

@Robot->pump_off(); выключает помпу захвата

find_x()

возвращает значение координаты X точки, в которой находится захват робота

X = @Robot->find_x(); получает значение координаты X точки, в которой находится захват робота и сохраняет ее в переменную X

find_y()

возвращает значение координаты Y точки, в которой находится захват робота

Y = @Robot->find_y(); получает значение координаты Y точки, в которой находится захват робота и сохраняет ее в переменную Y

find_z()

возвращает значение координаты Z точки, в которой находится захват робота

Z = @Robot->find_z(); получает значение координаты Z точки, в которой находится захват робота и сохраняет ее в переменную Z

move_to_at_once(x,Y, Z)

перемещает захват робота в точку с координатами X, Y, Z. Движение происходит с максимально возможной скоростью перемещения.

@Robot->move_to_at_once (10, 10, 10); перемещает захват робота в точку с координатами X=10, Y=10, Z=10

move(x, Y, Z)

перемещает захват робота из точки с текущими координатами X_текущее,Y_текущее, Z_текущее в точку с координатами X_текущее + X,Y_текущее + Y, Z_текущее + Z. Движение происходит плавно.

@Robot->move(1, 1, 1); изменит координаты точки в которой находится захват робота на указанные значения (X_текущее + 1, Y_текущее + 1, Z_текущее + 1)

move_to_1(x, Y, Z,T)

перемещает захват робота в точку с координатами X, Y, Z с задержками между промежуточными шагами на время T. Время указывается в миллисекундах

@Robot->move_to_1(1, 1, 1, 50); переместит захват робота в точку с координатами X=1, Y=1, Z=1, с 50 миллисекундной задержкой между промежуточными перемещениями

move_to_2(x, Y, Z,T, R, Th4)

перемещает захват робота в точку с координатами X, Y, Z с задержками между промежуточными шагами на время T. Так же поворачивает захват роботоа вокруг оси на Th4 градусов

@Robot->move_to_2(1, 1, 1, 1, 1, 30); переместит захват робота в точку с координатами X=1, Y=1, Z=1, с 50 миллисекундной задержкой между промежуточными перемещениями. Так же повернет захват робота вокруг оси на 30 градусов

write_angles(Th1,Th2, Th3, Th4)

изменяет углы положения сервоприводов на указанные значенияTh1, Th2, Th3, Th4

@Robot->write_angles(10, 10, 10, 10); изменит углы положения сервоприводов на 10 градусов

rotate_servo4(Th4)

изменит угол положения сервопривода захвата робота на указанное значениеTh4

@Robot->rotate_servo4(15); изменит угол положения сервопривода захвата робота на 15 градусов

Доступны следующие оси управления роботом uArm:

Ось

Верхняя
граница

Нижняя
граница

Описание

locked

1

0

Бинарная ось. Если её значение равно 1, то робот считается заблокированным и игнорирует изменение значений по любым другим осям.

pump

1

0

Бинарная ось. Если её значение равно 1, то будет включена помпа робота. При значении равном 0 помпа будет отключена.

servo1

180

0

ось изменения угла первого сервопривода, находящегося в основании.

servo2

180

0

ось изменения угла второго сервопривода, действующий на угол между основанием и нижним плечом робота.

servo3

180

0

ось изменения угла третьего сервопривода - между плечами робота.

servo4

180

0

ось изменения угла четвертого сервопривода, изменяющего угол поворота захвата.

17.1.5 Быстрое подключение модуля smc к RCML

Модуль робота smc позволяет в RCML управлять промышленными электромеханическими захватами серии LEH производства компании SMC, посредством контроллера LECP6 этого же производителя. Каждый захват представляется в RCML как робот, которого соответственно можно задействовать и освободить. Контроллер LECP6 подключается к ПК, на котором работает RCML, через фирменный кабель из комплекта SMC Controller setting kit LEC-W2, используемый для управления захватом с ПК.

Промышленные электромеханические захваты серии LEH производства SMC

Стандартный контроллер LECP6 для управления захватами серии LEH

Данные захваты позволяют программировать длину и усилие хода губок. Более подробно о возможностях захватах серии LEH можно прочитать на официальном сайте:

 

Для управления захватом SMC LEH через RCML необходимо:

  1. Произвести установку и подключение захвата к контроллеру в соответствии с инструкциями производителя.
  2. Подключить контроллер к ПК.
  3. Добавить запись в секцию [robot_modules] конфигурационного файла RCML свойство module и установить его равным smc в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML".
  4. Далее следует произвести настройку модуля. Необходимо указать, через какой COM-порт следует взаимодействовать с контроллером захвата. Для этого нужно перейти в каталог с модулями роботов (robot_modules), а затем в каталог модуля SMC.
  5. В директории модуля smc нужно создать файл config.ini со следующим содержанием:
[main]
count_robots = 1
is_debug = 0
robot_port_0 = \\.\\COM3

Файл конфигурации модуля состоит из секции [main], которая включает в себя следующие свойства:

  • count_robots – свойство, в качестве параметра принимающее количество контроллеров SMC, к которым необходимо будет подключиться.
  • is_debug – отображает в консоль пакеты данных передаваемых контроллеру LECP6. Может принимать значение 0 или 1.
  • robot_port_X – содержит имя COM-порта, к которому подключен робот Х. Адрес порта должен быть указан в формате \\.\\COMY, где Y – порядковый номер порта. Отсчет должен начинаться с 0.

Далее приведен текст программы на языке RCML. Программа обращается к захвату SMC, передает команду развести губки на 1 см со скоростью 1 мм/с, а затем отправляет команду на возврат в позицию по умолчанию:

function main() {
@r = robot_smc;
@r-> move_to(1000, 1);
@ur->return_to_origin();
}

Доступные функции модуля приведены в таблице:

Определение

Описание

Пример

move_to(pos, spd)

устанавливает расстояние между губками захвата равное pos (в сотых долях миллиметра). Перемещение губок захвата происходит с заданной скоростью spd (мм/с)

@Robot->move_to (200, 10); устанавливает расстояние между губками захвата равное 2мм. Скорсоть движения губок захвата 10мм/с

return_to_origin()

возвращает губки захвата в положение по умолчанию (расстояние между губками 1мм)

@Robot->return_to_origin();

get_cur_position()

возвращает текущее расстояние между губками захвата (сотые доли миллиметра)

@Robot-\>get\_cur\_position();

get_cur_speed()

возвращает текущую скорость перемещения губок захвата в мм/с

X = @Robot->find_x(); получает значение координаты X точки, в которой находится захват робота и сохраняет ее в переменную X

get_cur_thrust()

возвращает значение текущей нагрузки (%)

thrust = @Robot->get_cur_thrust();

move_to2( move_mode, spd, pos, accel, decel, pushing_force, trigger_level, pushing_speed, moving_force, area_output1, area_output2, in_position)

устанавливает расстояние между губками захвата равное pos (сотые миллиметра); move_mode - тип перемещения (1 - абсолютное перемещение, 2 - относительное перемещение); spd - скорость (мм/с); accel – ускорение при начале движения (мм/с^2); decel – замедление при остановке (мм/с^2); pushing_force (0 - позиционирование, [1-100] - воздействие с заданным моментом (%); trigger_level - значение воздействия, при котором флаг INP примет 1; pushing_speed - скорость перемещения при воздействии (мм/с); moving_force - максимальное усилие при перемещении (%); area_output1, area_output2 - если текущая позиция находится между заданными значениями, флаг AREA примет 1; in_position - если текущая позиция совпадает с заданным значением, флаг INP примет 1

set_hand_control_params(spd, accel, decel)

устанавливает скорость spd в мм/с, ускорение accel в мм/с^2 и замедление decel в мм/с^2 для режима ручного управления захватом

@Robot->set_hand_control_params(20, 50, 50);

Доступные оси для режима ручного управления:

Ось

Верхняя граница

Нижняя граница

Описание

locked

1

0

Бинарная ось. Если её значение равно 1, то захват считается заблокированным и игнорирует изменение значений по любым другим осям.

servo1

1000

100

Ось, задающая расстояние между губками захвата.

17.1.6 Быстрое подключение модуля FANUC к RCML

Для управления промышленными роботами FANUC с помощью RCML, существует одноименный модуль робота – FANUC. Данный модуль совместим с контроллерами производства FANUC серий A-cabinet и B-cabinet, имеющих включенную программную опцию Modbus TCP. Соответственно модуль FANUC поддерживает всех роботов совместимых с данными контроллерами.

Подробнее о роботах FANUC можно узнать на официальном сайте компании:

С помощью данного модуля возможно управлением робота с ПК через RCMLruntime задание произвольных траекторий перемещения роботу в том числе с поддержкой управления дополнительных групп осей (поворотный стол и пр.)

Низкоуровневый функционал модуля FANUC заключается в возможности передачи контроллеру из RCML данных различных типов: биты, целые числа, вещественные числа, а также запуск программ по механизму PNS.

Коммуникация ПК с RCML и контроллера FANUC осуществляется по FTP Ethernet кабелю. Предварительно робот, контроллер и ПК c RCML должны быть настроены соответствующем образом. Информация о процедуре настройки и подготовки высылается по запросу в произвольной форме, отправленному на info@robotct.ru

Для подключения модуля FANUC необходимо выполнить следующие шаги:

  1. Произвести необходимую предварительную настройку робота и контроллера;
  2. Произвести настройку ПК с RCML для установки связи с контроллером;
  3. Подключить контроллер FANUC к ПК с RCML по FTP Ethernet кабелю, если роботов несколько, то они могут быть подключены в одну сеть с помощью соответствующего сетевого оборудования.
  4. Добавить запись в секцию [robot_modules] конфигурационного файла RCML свойство module и установить его равным fanuc в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML"
  5. Далее следует произвести настройку самого модуля FANUC, для этого в директории модуля нужно создать файл config.ini и заполнить его по указанным ниже правилам.

В конфигурационном файле обязательно должна присутствовать секция main со свойством count_robots, в котором указывается количество управляемых роботов FANUC.

Для каждого управляемого робота создается секция с именем вида robot_X, где X - порядковый номер робота, отсчет начинается с 1. Данная секция называется секцией робота. В секции робота должно быть 4 свойства:

  • robot_name – уникальное отображаемое имя робота, строка;
  • ip – IP адрес контроллера робота в сети, строка;
  • port – порт робота, число;
  • slave_id – номер робота в сети Modbus.

Ожидается, что все подключенные к RCML роботы будут иметь одинаковую конфигурацию цифровых входов и выходов, DI и DO, соответственно. Для задания конфигурации DI используется одноименная секция DI, в которой можно указать передаваемые ячейки данных и их типы. Каждая ячейка имеет отображаемое имя, используемое в программе на RCML для обращения к этой ячейке.

Поддерживаются следующие типы данных:

  • Логический. Указывается как logic_%name% = X, где %name% - имя ячейки, а X – номер входа. Данный тип задействует всего 1 вход.
  • Целочисленный. Указывается как integer_%name% = X, где %name% - имя ячейки, а X – номер входа, с которого начинается отсчет разрядов для передачи числа. Данный тип имеет размер 16 разрядов и соответственно задействует 16 входов. При этом для начала отсчета разрядов можно выбирать только те входа, номер которых при делении на 16 дает в остатке 1 (1, 17, 33, 49 и т.д.). Целочисленный тип может передавать только целые не отрицательные числа.
  • Вещественный. Указывается как real_%name% = A,B,C, где %name% - имя ячейки, а A – номер входа, для передачи знака числа, B- номер входа, с которого начинается отсчет разрядов для передачи целой части вещественного числа, С - номер входа, с которого начинается отсчет разрядов для передачи дробной части вещественного числа,. Данный имеет размер 1+16+16 = 33 разряда и задействует столько же входов. При этом привило выбора номера входа для B и C части, такие же как для целочисленного типа данных.
  • Расширенный целочисленный. Указывается как big_integer_%name% = A,B, где %name% - имя ячейки, а A - номер входа, с которого начинается отсчет разрядов для передачи первой части числа, B - номер входа, с которого начинается отсчет разрядов для передачи второй части вещественного числа,. Данный имеет размер 16+16 = 32 разряда и задействует столько же входов. При этом привило выбора номера входа для A и B части, такие же как для целочисленного типа данных. Основное назначение данного типа - передача больших целых не отрицательных чисел.

Для задания конфигурации цифровых выходов робота – DO, применимы такие же типы данных, правила их описания такие же. Единственное отличие – конфигурация цифровых выходов задается в секции с именем DO.

Модуль FANUC поддерживает механизм запуска PNS программ в роботе, однако для этого нужно предусмотреть выделение дополнительных входов/выходов со следующими именами.

Для DI:

  • logic_cycle_stop
  • logic_fault_reset
  • logic_start
  • logic_enable
  • logic_input_PNS1
  • logic_input_PNS2 
  • logic_input_PNS3
  • logic_input_PNS4
  • logic_input_PNS5
  • logic_input_PNS6
  • logic_input_PNS7
  • logic_input_PNS8
  • logic_PNS_strobe
  • logic_prod_start

Для DO:

  • logic_cmdenabled
  • logic_prg_running
  • logic_prg_paused
  • logic_motion_held
  • logic_fault
  • logic_busy
  • logic_out_PNS1
  • logic_out_PNS2
  • logic_out_PNS3
  • logic_out_PNS4
  • logic_out_PNS5
  • logic_out_PNS6
  • logic_out_PNS7
  • logic_out_PNS8
  • logic_snack

При задании всех этих входов/выходов у модуля будут доступны функции run_program и run_program_soft использующие механизм PNS.

Доступные функции модуля приведены в таблице:

Определение

Описание

run_program(number)

Запускает PNS программу под номером num в роботе и ждёт её завершения. При нормальном завершении возвращает значение по умолчанию – 0.0, при ошибке бросает исключение. Данная функция доступна, только если была проведена конфигурация входов выходов, необходимых для работы PNS механизма. В случае если конфигурация не была проведена, функция бросает исключение.

run_program_soft(num)

Запускает PNS программу под номером num в роботе и не ожидает её завершения. Завершение запущенной программы возможно только вручную через оперирование соответствующими входами/выходами, отвечающими за управление механизмом PNS. Данная функция доступна, только если была проведена конфигурация входов выходов, необходимых для работы PNS механизма. В случае если конфигурация не была проведена, функция бросает исключение.

set_logic_di(name, value)

Установка значения value для логического входа под именем name. Функция бросает исключение, если вход под данным именем не найден. На вход подается положительный сигнал если значение value отлично от нуля, в противном случае отрицательный.

get_logic_di(name)

Получение значения логического входа под именем name. Функция бросает исключение, если вход под данным именем не найден. Функция возвращает 1, если сигнал на входе положительный и 0, если отрицательный.

get_logic_do(name)

Получение значения логического выхода под именем name. Функция бросает исключение, если вход под данным именем не найден. Функция возвращает 1, если сигнал на входе положительный и 0, если отрицательный.

set_integer_di(name, value)

Установка значения value для целочисленного входа под именем name. Функция бросает исключение, если вход под данным именем не найден. Если при установке значение value вещественное, то оно округляется по математическим правилам.

get_integer_di(name)

Получение значения целочисленного входа под именем name. Функция бросает исключение, если вход под данным именем не найден.

get_integer_do(name)

Получение значения целочисленного выхода под именем name. Функция бросает исключение, если вход под данным именем не найден.

set_real_di(name, value)

Установка значения value для вещественного входа под именем name. Функция бросает исключение, если вход под данным именем не найден. В передаваемом значении value знаки, следующие после 3-го знака после запятой, будут отброшены

get_real_di(name)

Получение значения вещественного входа под именем name. Функция бросает исключение, если вход под данным именем не найден.

get_real_do(name)

Получение значения вещественного выхода под именем name. Функция бросает исключение, если вход под данным именем не найден.

set_big_integer_di(name, value)

Установка значения value для расширенного целочисленного входа под именем name. Функция бросает исключение, если вход под данным именем не найден. Если при установке значение value вещественное, то оно округляется по математическим правилам.

get_big_integer_di(name)

Получение значения расширенного целочисленного входа под именем name. Функция бросает исключение, если вход под данным именем не найден.

get_big_integer_do(name)

Получение значения расширенного целочисленного выхода под именем name. Функция бросает исключение, если вход под данным именем не найден.

Модуль робота FANUC не имеет осей доступных оси для режима ручного управления.

17.2 Пример подключения модулей функций

17.2.1 Быстрое подключение модуля math к RCML

Функциональный модуль math используется для доступа к математическим функциями, аналогичным библиотеке math.h в С++.

    1. Для включения модуля math необходимо добавить запись в разделе [function_modules] конфигурационного файла RCML в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML". Дополнительных настроек модуль не требует.
    2. Теперь, в Вашем распоряжении, есть следующие функции:

Определение

Описание

Выброс исключения, если

pow(a, b)

Возведение a в степень b.

 

sqrt(a)

Возвращает квадратный корень из a. a не может быть меньше 0.

a < 0

abs(a)

Возвращает модуль числа a.

 

rand(a,b)

Возвращает случайное целое число в пределах [b;a+b). a не может быть меньше или равно 0.

a ≤ 0

sin(a)

Функции sin, cos, tan принимают значения в радианах.

Возвращает cинус a.

 

cos(a)

Возвращает коcинус a.

 

tan(a)

Возвращает тангенс a.

 

asin(a)

Возвращает аркcинус a. Из-за свойств функции аргумент a должен быть в пределах [-1;1].

Функции asin, acos, atan возвращают значения в радианах.

a ∉ [-1;1]

acos(a)

Возвращает арккоcинус a. Из-за свойств функции аргумент a должен быть в пределах [-1;1].

a ∉ [-1;1]

atan(a)

Возвращает арктангенс a.

 

exp(a)

Возвращает e в степени a.

 

log(a)

Возвращает натуральный логарифм числа a. Из-за свойств функции аргумент a должен быть больше 0.

a ≤ 0

log10(a)

Возвращает десятичный логарифм числа a. Из-за свойств функции аргумент a должен быть больше 0.

a ≤ 0

    1. В соответствии с разделом "Вызов функций" синтаксис программы с использованием модуля math выглядит следующим образом: 
function main() {
	r = 9;
	r = math.sqrt(r);
	system.echo(r);
}

Результатом работы этой программы является число 3.0000

  1. Следующий пример демонстрирует выброс исключения в случае нарушения входных данных.
function main() {
	try {
		r=math.log(0);
	} catch {
		system.echo("Throw exception log(0) undefined");
	}
}

Более подробно об использовании исключений описано в разделе "Исключения"

17.3 Пример подключения модулей управления

17.3.1 Быстрое подключение тестового модуля управления test к RCML

Тестовый модуль управления test используется для имитации получения значений осей от устройств управления.

Для включения модуля test необходимо добавить свойство module и присвоить ему значение test в секции [control_modules] конфигурационного файла RCML в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML". Дополнительной конфигурации модуль тестового управления не требует.

Далее приведен пример использования модуля тестового управления при взаимодействии с тестовым роботом:

function main() {
	@lr = robot_test; 
	system.hand_control(@lr,"test","X","X");
}

При выполнении данной программы в течении 10 секунд, раз в секунду посылается случайное значение по оси Х. Для функционирования представленной программы должен быть подключен модуль тестового робота, более подробно о подключении написано в разделе "Быстрое подключение модуля робота test к RCML"

Тестовый модуль управления имеет следующие доступные оси:

Наименование

Верхняя граница

Нижняя граница

Примечание

X

100

-100

 

Y

1

0

Бинарная

Z

100

0

 

Значения осей, передаваемые каждую секунду времени:

Наименование

1

2

3

4

5

6

7

8

9

10

X

100

-30.1

-2.58

48.9

99.01

-100

12.0

-36.9

0.25

0

Y

0

0

0

1

1

0.5

0.25

0.1

0.75

0.35

Z

4.56

0

78.9

100

50

48.8

66.7

32.4

40

20

17.3.2 Быстрое подключение модуля keyboard к RCML

Модуль управления keyboard используется для ручного управления роботом при помощи клавиатуры.

  1. Для включения модуля keyboard необходимо добавить в секцию [control_modules] конфигурационного файла RCML свойство module и установить его значение равным keyboard в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML".
  2. В папке модуля keyboard, находящего в директории control_modules необходимо создать файл конфигурации модуля config.ini
  3. Файл конфигурации модуля keyboard описывает, какие оси доступны программисту, для осуществления взаимодействия с роботом в режиме ручного управления. Для добавления новой оси, следует придерживаться следующего правила её описания:

3.1. При добавлении новой оси, необходимо в секцию [mapped_axis] добавить свойство имени оси и присвоить ему значение кнопки клавиатуры в HEX формате, при этом количество значений кнопок клавиатуры для одной оси может быть несколько. В общем случае запись в секцию [mapped_axis] будет выглядеть следующим образом:

имя_оси = значение_кнопки_клавиатуры_в_HEX_формате

3.2. Необходимо установить максимальное и минимальное значение, которое может принимать ось. Для этого следует с новой строки добавить секцию в конфигурационного файла config.ini, одноименную с именем оси, и задать свойства upper_value и lower_value передать значения максимума и минимума оси. В общем виде секция выглядит следующим образом:

[имя_оси]
upper_value = максимальное_значение_оси
lower_value = минимальное_значение_оси

3.3. Далее следует определить, какое значение будет иметь ось в случае нажатия кнопки на клавиатуре, которая ранее была прикреплена к ней. Определение значений происходит посредством создания секции, название которой состоит из имени оси и значения кнопки клавиатуры в Hex формате, разделенные между собой нижним подчеркиванием. Для задания значения по умолчанию (в не нажатом) и нажатом состоянии используются свойства unpressed_value и pressed_value, в которые передаются значения. Общий вид секции в таком случае выглядит следующим образом:

[имя_оси_значение_кнопки_клавиатуры_в_HEX_формате]
pressed_value = значение_оси_при_нажатой_клавише
unpressed_value = значение_оси_при_отжатой_клавише 

Для наглядности приведен пример конфигурации модуля keyboard с комментариями:

;Секция для работы в Linux
[options]
input_path = /dev/input/event2 ;Путь до файла потока ввода

;Обязательная секция
[mapped_axis]
;название_оси = код_клавиши (в HEX формате)
go = 0x26 ;стрелка_вверх
go = 0x28 ;стрелка_вниз

;Описание оси go, всегда должно иметь оба ключа
[go]
upper_value = 1 ;Верхняя граница значений оси
lower_value = -1 ;Нижняя граница значений оси

;Описание поведения оси go для клавиши *стрелка_вверх* (0x26)
[go_0x26]
pressed_value = 1 ;При нажатии клавиши *стрелка_вверх* значение оси задать равным 1
unpressed_value = 0 ;При отпускании клавиши *стрелка_вверх* значение оси задать равным 0

;Описание поведения оси go для клавиши *стрелка_вниз* (0x28)
[go_0x28]
pressed_value = -1 ;При нажатии клавиши *стрелка_вниз* значение оси задать равным -1
unpressed_value = 0 ;При отпускании клавиши *стрелка_вниз* значение оси задать равным 0

Пример описания конфигурации модуля включает в себя одну ось go, которая вернёт максимальное значение 1 при нажатии стрелки вверх и 0 при её отпускании или -1 при нажатии стрелки вниз и 0 при её отпускании. Более подробно об осях и ручном управлении написано в разделе "Общие сведения".

В качестве примера, приведен расширенный файл конфигурации модуля keyboard в котором инициализированы следующие оси:

  • [go] – в качестве кнопок управлению используются стрелки вверх-вниз
  • [rotate] – ось управляется стрелками влево-вправо
  • [locked] – используется для блокировки робота, нажатием кнопки «А» на клавиатуре.

Далее приведен листинг файла конфигурации модуля keyboard с тремя осями:

[mapped_axis]
go = 0x26
go = 0x28
rotate = 0x25
rotate = 0x27
locked = 0x41

[go]
upper_value = 1
lower_value = -1

[rotate]
upper_value = 1
lower_value = -1

[locked]
upper_value = 1
lower_value = 0

[locked_0x41]
pressed_value = 1
unpressed_value = 0

[go_0x26]
pressed_value = 1
unpressed_value = 0
	
[go_0x28]
pressed_value = -1
unpressed_value = 0

[rotate_0x25]
pressed_value = 1
unpressed_value = 0

[rotate_0x27]
pressed_value = -1
unpressed_value = 0

Далее приведен пример текста программы на языке RCML. Программа обращается к тестовому роботу, который был подключен в разделе "Быстрый старт" и выглядит следующим образом:

function main() {
	@tr = robot_test; 
	system.hand_control(@tr,"keyboard","X","go");
}

Первой строкой программы создаётся переменная, которая прикрепляется к тестовому роботу, о том, что такое тестовый робот и как его подключить, написано в разделе "Быстрое подключение модуля робота test к RCML".

Вторая строка переводит тестового робота в ручной режим управления. Как было описано ранее ось go, принимает значение в зависимости от нажатия стрелок вверх и вниз и имеет максимальное значение 1 и минимальное значение -1, которое передаёт их ось робота X. Однако, во время выполнения программы значение оси управляющего устройства не будет равно значению оси робота. Автоматически происходит процесс масштабирования оси, то есть максимальное значение клавиши, преобразовывается в максимальное значение оси робота. Аналогичная ситуация происходит и во время нажатия стрелки вниз. Модуль управления keyboard получает минимальное значение оси клавиатуры и преобразует в минимальное значение оси робота. Таким образом, при нажатии стрелки вверх, тестовый робот сообщит, что он перейдет в максимальное положение 100, а при нажатии стрелки вниз в -100.

У тестового робота существует ещё две оси Y,Z. Используя файл конфигурации модуля keyboard описанного на шаге 3, добавим ещё одну ось управления роботом. Пусть по мимо существующей передачи значений в ось Z тестового робота, будет приходить значение оси rotate. Программный код в этом случае будет выглядеть следующим образом:

function main() {
	@tr = robot_test; 
	system.hand_control(@tr,"keyboard","X","go","Y","rotate");
}

Во время выполнения программы, нажатие на стрелки вверх или вниз вызовет сообщения от тестового робота, о том, что была получена команда на смену значения по оси X, и по оси Y, при нажатии клавиш влево-вправо. Причем принимаемые роботом значения будут максимально допустимые для этих осей.

Больше информации о ручном управлении находиться в разделе 4 «Режим ручного управления».

17.3.3 Быстрое подключение модуля gamepad к RCML

Модуль управления gamepad обеспечивает ручное управление роботом при помощи геймпада.

Количество используемых осей зависит от содержимого файла конфигурации модуля config.ini. Максимальное количество осей, которые могут быть определены в файле конфигурации 18, из них:

  • 11 бинарных осей, соответствующих кнопкам.
  • 4 оси для стиков.
  • 2 оси для крестовины (D-pad).
  • 1 ось с названием "Exit" назначает на кнопку функцию завершения режима ручного управления.
  1. Для включения модуля gamepad необходимо добавить в секцию [control_modules] конфигурационного файла RCML свойство module со значением gamepad в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML".
  2. Далее следует перейти в каталог модулей RCML, в котором располагаются модули управления (control_modules), далее в каталог gamepad.
  3. Нужно создать пустой файл config.ini в каталоге gamepad. Далее в этот файл будут помещены настройки конфигурации джойстика.
  4. Далее необходимо настроить конфигурационный файл модуля config.ini. Предлагается использовать одну из двух готовых конфигураций модуля, которые подходят для большинства геймпадов:

4.1. Универсальный файл конфигурации модуля для взаимодействия с геймпадом №1:

[axis]
Exit = 9
B1 = 1
B2 = 2
B3 = 3
B4 = 4
L1 = 7
L2 = 5
R1 = 8
R2 = 6
start = 10
T1 = 11
T2 = 12
RTUD = 13
RTLR = 16
LTUD = 15
LTLR = 14
arrowsUD = 17
arrowsLR = 18

[B1]
upper_value = 1
lower_value = 0
	
[B2]
upper_value = 1
lower_value = 0
	
[B3]
upper_value = 1
lower_value = 0
	
[B4]
upper_value = 1
lower_value = 0
	
[L1]
upper_value = 1
lower_value = 0
	
[L2]
upper_value = 1
lower_value = 0
	
[R1]
upper_value = 1
lower_value = 0
	
[R2]
upper_value = 1
lower_value = 0
	
[start]
upper_value = 1
lower_value = 0
	
[T1]
upper_value = 1
lower_value = 0
	
[T2]
upper_value = 1
lower_value = 0
	
[RTUD]
upper_value = 0
lower_value = 65535
	
[RTLR]
upper_value = 0
lower_value = 65535
	
[LTUD]
upper_value = 0
lower_value = 65535

[LTLR]
upper_value = 0
lower_value = 65535
	
[arrowsUD]
upper_value = 1
lower_value = -1
	
[arrowsLR]
upper_value = 1
lower_value = -1
4.2. Универсальный файл конфигурации модуля для взаимодействия с геймпадом № 2:
[axis]
Exit = 9
B1 = 4
B2 = 2
B3 = 1
B4 = 3
L1 = 5
L2 = 7
R1 = 6
R2 = 8
start = 10
T1 = 11
T2 = 12
RTUD = 16
RTLR = 13
LTUD = 15
LTLR = 14
arrowsUD = 17
arrowsLR = 18
	
[B1]
upper_value = 1
lower_value = 0
	
[B2]
upper_value = 1
lower_value = 0
	
[B3]
upper_value = 1
lower_value = 0
	
[B4]
upper_value = 1
lower_value = 0

[L1]
upper_value = 1
lower_value = 0

[L2]
upper_value = 1
lower_value = 0

[R1]
upper_value = 1
lower_value = 0
	
[R2]
upper_value = 1
lower_value = 0
	
[start]
upper_value = 1
lower_value = 0

[T1]
upper_value = 1
lower_value = 0

[T2]
upper_value = 1
lower_value = 0

[RTUD]
upper_value = 0
lower_value = 65535

[RTLR]
upper_value = 0
lower_value = 65535
	
[LTUD]
upper_value = 0
lower_value = 65535

[LTLR]
upper_value = 0
lower_value = 65535

[arrowsUD]
upper_value = 1
lower_value = -1
	
[stick_zero_positions]
axis_1 = 31487
axis_2 = 31487
axis_3 = 31487
axis_4 = 31487
arrows = 4294967295

[options]
input_path = /dev/input/js1

[arrowsLR]
upper_value = 1
lower_value = -1

В случае использования файлов готовых конфигураций модуля, шаги 5-8 следует пропустить. Если файлы конфигурации не обеспечивают требуемого уровня управления, то следует дополнительно выполнить пропущенные шаги.

Рекомендуется, прежде чем приступить к управлению реальным физическим роботом, проверить конфигурацию геймпада на тестовом роботе, о том как подключить тестового робота к RCML написано в разделе "Быстрое подключение модуля робота test к RCML".

5. Необходимо убедиться в том, что геймпад подключен к компьютеру. В противном случае, при дальнейшем запуске 'calibrator.exe', будет сформирована ошибка ‘cant CreateDevice

6. Для заполнения конфигурационного файла нужно запустить файл 'calibrator.exe'
Это консольное приложение запустит мастера калибровки, инструкциям которого необходимо следовать для наполнения файла конфигурации config.ini.
Для пропуска назначения кнопки достаточно подождать время, заданное в качестве параметра. (по умолчанию – 5 секунд)

7. Если нажатие нужной кнопки было пропущено или нажата не та клавиша, то следует закрыть окно, перезапустить 'calibrator.exe' и выполнить все инструкции более внимательно.

8. Таким образом, будет создана конфигурация модуля gamepad. Если открыть этот файл, то он будет содержать названия осей и их пороговые значения.

9. Далее приведена таблица с расшифровкой каждой доступной оси геймпада:

Наименование

Верхняя граница

Нижняя граница

Примечание

B1

1

0

Бинарная ось. Соответствует любой кнопке из группы кнопок ABXY геймпада x-box.

B2

1

0

Бинарная ось. Соответствует любой кнопке из группы кнопок ABXY геймпада x-box.

B3

1

0

Бинарная ось. Соответствует любой кнопке из группы кнопок ABXY геймпада x-box.

B4

1

0

Бинарная ось. Соответствует любой кнопке из группы кнопок ABXY геймпада x-box.

L1

1

0

Бинарная ось. Соответсвует кнопке с таким же названием геймпада x-box

L2

1

0

Бинарная ось. Соответсвует кнопке с таким же названием геймпада x-box

R1

1

0

Бинарная ось. Соответсвует кнопке с таким же названием геймпада x-box

R2

1

0

Бинарная ось. Соответсвует кнопке с таким же названием геймпада x-box

start

1

0

Бинарная ось. Соответсвует кнопке с таким же названием геймпада x-box

T1

1

0

Бинарная ось. Соответсвует кнопке с таким же названием геймпада x-box

T2

1

0

Бинарная ось. Соответсвует кнопке с таким же названием геймпада x-box

RTUD

Назначается

Назначается

Дискретная ось. Соответствует правому стику.

RTLR

Назначается

Назначается

Дискретная ось. Соответствует правому стику.

LTUD

Назначается

Назначается

Дискретная ось. Соответствует левому стику.

LTLR

Назначается

Назначается

Дискретная ось. Соответствует левому стику.

arrowsUD

1

-1

Дискретная ось. Соответствует крестовине(D-pad) геймпада.

arrowsLR

1

-1

Дискретная ось. Соответствует крестовине(D-pad) геймпада.

Далее приведен пример текста программы на языке RCML. Программа обращается к тестовому роботу, который был подключен при выполнении раздела "Быстрый старт" и выглядит следующим образом:

function main() {
	@tr = robot_test; 
	system.hand_control(@tr,"gamepad","X","RTUD");
}

Первой строкой программы создаётся переменная, к которой прикрепляется тестовый робот.

Вторая строка переводит тестового робота в ручной режим управления от геймпада.

Во время выполнения программы, использование правого стика по направлению вверх-вниз, передаст значение оси X в тестового робота. При каждом изменении положения стика, в окне отразится сообщение о том, что тестовый робот, получил смену значения по оси X.

Больше информации о ручном управлении находиться в разделе «Режим ручного управления».

17.3.4 Быстрое подключение Myo к RCML

Myo – это браслет, позволяющий при помощи различных жестов управлять компьютером, смартфоном или планшетом.

Более подробно о браслете Myo можно прочитать на официальном сайте:

Модуль управления myo используется для ручного управления роботом при помощи устройства Myo которое отслеживает жесты и положение руки в пространстве.

  1. Для начала Вам следует выполнить установить и настроить Myo на Вашем компьютере, как это показано в Setting up the Myo armband with your Windows PC.
  2. Далее следует установить следующие настройки для Myo Connect

2.1. Необходимо установить настройки General в соответствии с изображением.

2.2. Следует настроить Presentation Mode как показано на рисунке.

2.3. Кроме этого следует отключить Connector и Presentation Mode в соответствии с рисунком.

2.4. Необходимо также настроить Myo Keyboard Mapper как показано на изображении.

  • Для включения модуля myo необходимо добавить в секцию [control_modules] конфигурационного файла RCML свойство module и установить его значение равным myo в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML". Дополнительно модуль в конфигурировании не нуждается и будет подключен по умолчанию к первому браслету в системе.
function main() {
	@r = robot_test;
	system.hand_control(@r,"myo","X","fist");
}

Первой строчкой программы, создаётся переменная, которая прикрепляется к тестовому роботу, о том, как подключить тестового робота, написано в разделе "Быстрое подключение модуля робота test к RCML".

Вторая строчка программы, указывает что управление роботов будет происходить в режиме ручного управления. То есть в ось X тестового робота @r передаётся значение оси fist устройства управления myo. Более подробно о том, что означает функция ручного управления написано в руководстве по RCML в разделе "Режим ручного управления".

Во время выполнения программы, необходимо сделать жесть fist (сжать кулак), жест будет распознан Myo и через модуль управления myo тестовому роботу, будет передано новое значение оси Х. Поскольку 1 это максимальное значение оси fist для Myo, а для тестового робота максимальное значение оси Х это 100, то верхняя граница значения оси fist будет преобразована до верхней границы оси X, тем самым робот изменит значение оси Х на максимально возможное – 100.

Браслет Myo умеет распознавать следующие жесты:

  • fist;
  • fingers spread;
  • double tap;
  • wave out;
  • wave in.
  • rest (отсутствие жеста, расслабленная рука)

Все из вышеперечисленных жестов доступны для программиста по умолчанию.

Кроме этого, программисту доступны следующие оси в модуле:

Наименование

Верхняя граница

Нижняя граница

Примечание

locked

1

0

Бинарная ось. Отражает статус браслета Myo: блокирован - 1, разблокирован - 0.

fist

1

0

Бинарная ось. Если наблюдается жест fist - 1, в противном случае - 0.

left_or_right

1

-1

Дискретная ось. Удобна для задания направления перемещения или поворота. Основана на жестах wave out и wave in. Автоматически определяет направление кисти в данных жестах направо или налево (независимо от того на какую руку надет браслет) и принимает следующие значения: -1 - налево, 0 - нет жеста, 1 - направо.

fingers_spread

1

0

Бинарная ось. Если наблюдается жест fingers spread - 1, в противном случае - 0.

double_tap

1

0

Бинарная ось. Если наблюдается жест double tap - 1, в противном случае - 0.

fist_pitch_angle

18

0

Непрерывная ось. Отмечает угол pitch (тангаж) браслета относительно земли, при жесте fist.

fist_roll_angle

18

0

Непрерывная ось. Отмечает угол roll (крен) браслета относительно земли, при жесте fist.

fist_yaw_angle

18

0

Непрерывная ось. Отмечает угол yaw (рысканье) браслета относительно земли, при жесте fist.

fingers_spread_pitch_angle

18

0

Непрерывная ось. Отмечает угол pitch (тангаж) браслета относительно земли, при жесте fingers spread.

fingers_spread_roll_angle

18

0

Непрерывная ось. Отмечает угол roll (крен) браслета относительно земли, при жесте fingers spread.

fingers_spread_yaw_angle

18

0

Непрерывная ось. Отмечает угол yaw (рысканье) браслета относительно земли, при жесте fingers spread.

Примечания к таблице:

  1. Значения всех осей передаются 20 раз в секунду.
  2. Значение осей с суффиксом angle, изменяется и передается только при наблюдении соответствующего жеста.
  3. Если браслет блокирован, то значения всех осей жестов, кроме оси locked и осей с суффиксом angle, будут равны 0.
  4. Браслет блокируется автоматически, если некоторое малое время (1-2 сек) по датчикам наблюдается не известный браслету жест или наблюдается жест rest, а также если обнаружен сдвиг браслета на руке или снятие браслета с руки.
  5. Разблокировка браслета происходит жестом double tap, как и во многих Myo-совместимых приложениях.
  6. Рекомендуется проявлять осторожность при использовании для управления роботом одновременно оси fist или fingers_spread, и осей содержащих одноименные префиксы fist или fingers_spread соответственно, т.к. оси жестов принимают значение 1 при попытке изменения значения осей, активных при соответствующем жесте, поскольку для этого требуется появление этого жеста.

Кроме тестового робота, к системе RCML можно подключить другого робота, совместимого с RCML.

17.4 Пример подключения модуля выбора робота

17.4.1 Быстрое подключение модуля avg к RCML

Модуль выбора робота avg реализует простейшую логику выбора наиболее быстрого робота на основе статистических данных RCML.

Модуль сначала инициирует наполнение базы данных статистикой, так чтобы каждый робот из набора свободных роботов выполнил хотя бы 1 раз требуемую функцию.

Затем всегда выбирает того робота или робота того модуля, у которого наименьшее среднеарифметическое время выполнения требуемой функции по его (робота) числу попыток выполнения этой функции.

Включение модуля avg стандартно - нужно добавить в секцию [choice_modules] конфигурационного файла RCML свойство module и установить его равным avg в соответствии с разделом "Установка и настройка компилятора и интерпретатора RCML".

Дополнительной конфигурации модуля avg не требуется. Однако у RCML должен быть включен режим записи статистической информации, в противном случае модуль запретит запуск RCML.

 

Адрес:

Россия, Пермь
ул. Монастырская, 12,
лит. А, офис 600

Телефон:

+7 (342) 214 01 84

E-mail:

info@robotct.ru