RCML (англ. Robot Control Meta Language, произносится [ар-си-эм-эль] — компилируемый статически типизированный язык программирования высокого уровня. Разработан для получения одинакового результата независимо от исполнения робота[1]. Позволяет создавать условия для совместной работы нескольких роботов. Используется для описания действий робота или группы роботов[2]. Включает ряд визуальных аспектов представления кода относительно классов и объектов из языков программирования, реализующих парадигму объектно-ориентированного программирования[3].
RCML (англ. Robot Control Meta Language) Метаязык для роботов | |
---|---|
Класс языка | процедурный |
Тип исполнения | компилируемый |
Появился в | 2014 |
Автор | Robot Control Technologies |
Расширение файлов |
.rcml |
Выпуск | 1.0.6 (18.12.2015) |
Система типов | статическая слабая |
Повлиял на | Robot Build Language |
Сайт | Официальный сайт разработчика |
Введение в RCML
правитьЦели RCML
править- Получение одинакового результата, независимо от исполнения робота.
На основе предоставляемых роботом низкоуровневых функций, могут быть созданы более высокоуровневые функции, необходимые для реализации конкретной задачи в рамках аппаратных и программных возможностей используемого робота без какой-либо его модификации. - Создание условий для совместной работы нескольких роботов.
RCML позволяет задействовать несколько роботов для выполнения задачи, при этом следует описать, как должен действовать тот или иной робот по отношению к действиям другого робота.
Это даёт ряд возможностей для кооперации роботов:- Отправка роботам команд в синхронном режиме.
- Асинхронное параллельное выполнение роботами задач.
- Взаимозависимость действий роботов в группе.
- Значительное упрощение программирования робота, снижение порога входа в эту область.
На основе низкоуровневого функционала робота, может быть создан высокоуровневый функционал. В дальнейшем на базе высокоуровнего API робота может быть написана программа, реализующая требуемый технологический процесс. - Оптимальный выбор робота для решения конкретной задачи.
RCML предусматривает работу с группой однотипных роботов и позволяет установить алгоритм выбора наиболее подходящего робота-исполнителя из группы. - Переключение робота между несколькими одновременными задачами.
Во время исполнения программы при задействовании конкретного робота из группы, можно его высвободить, если робот больше не нужен. Освобождённый робот может быть задействован в другой программе, реализующей иную задачу.
Связанные области
править- Производство и промышленность
RCML позволяет нивелировать зависимость результата от конкретного робота и учитывать только функциональные возможности устройства. Используя только функционал робота, программисты могут писать универсальные программы, замена исполнительных устройств в которых не влияет на конечный результат работы. - Инжиниринговые компании
Используя эффект роботонезависимости результата, инжиниринговые компании могут разрабатывать программы, реализующие тот или иной технологический процесс без привязки к конкретному роботу, тем самым снижая риски, связанные с зависимостью от конкретных аппаратных решений, и удешевляя миграцию продуктов компаний на новых роботов, имеющих необходимый функционал. - Разработчики программного обеспечения
Разработчики ПО могут создавать новые, более сложные и высокоуровневые функциональные возможности роботов, используя низкоуровневые функции, описанные разработчиками роботов. - Научно-исследовательские институты и лаборатории
RCML может быть интегрирован с функционалом сторонних систем, что даёт возможность быстрой адаптации этих систем на всех исполнительных устройствах, имеющих необходимые функциональные возможности. - Разработчики и производители роботов
Интеграция новых роботов с RCML является одним из возможных путей расширения рынка сбыта, открывая возможность применения роботов в кругу ранее нерешённых задач. - Робототехнические сообщества
Через RCML они могут быть объединены существующие робототехнические решения и налажено взаимодействие с прочими робототехническими системами.
Синтаксис RCML
правитьСинтаксис RCML близок к языкам программирования C, Java и JavaScript. Сходство синтаксиса необходимо для обеспечения лёгкого перехода для программистов с других языков[4].
Особенности RCML
правитьRCML ориентирован на робототехнику и имеет довольно скудную составляющую как язык программирования, так как не предназначается для создания прикладного ПО общего назначения и нацелен на взаимодействие с робототехникой, позволяя достигать в этом отношении новых результатов.
Понятие робота в RCML
правитьРобот в RCML представляется как некий исполнительный ресурс, который может быть задействован для выполнения определённой задачи (функции), а затем освобождён для повторного задействования, но, например, в уже другой задаче.
Модуль робота предоставляет среде RCML описание класса робота, закреплённого за ним, предполагается, что локально в объектном мире, где используется RCML, может быть, как один, так и несколько роботов одного класса, закреплённых за одним модулем робота. Причём в среде RCML в рамках модуля робота присутствует два ключевых типа объектов, в соответствии с рисунком:
- модуль робота исполняет функции контроллера роботов вверенного ему класса, то есть выполняет функции выбора свободного робота для задействования и освобождения робота после работы;
- представление робота – отражение конкретного физического робота в виртуальной среде RCML, через него транслируются команды физическому роботу.
Следует отметить, что может быть подключено много классов роботов одновременно, то есть много модулей роботов, и каждый из них может предоставлять доступ сразу к нескольким роботам своего класса. Роботы в рамках одного класса должны быть одинаковы полностью, как в физическом представлении, так и в функциональном.
Модули роботов
правитьМодули роботов занимают одно из ключевых положений в RCML, поскольку именно через них осуществляется связь и передача команд физическому роботу.
Модуль робота отвечает за передачу команд от интерпретатора RCML одному или нескольким роботам одного класса (или типа), которые объединены под этим модулем. Рекомендуется для каждого класса или типа робота использовать отдельный модуль. Интерпретатор RCML через задекларированный API устанавливает связь с модулем робота, который в свою очередь устанавливает связь с каждым закреплённым за ним роботом. Таким образом, через модуль робота скрывается реализация связи и управления роботом от интерпретатора, что позволяет подключать к нему самых разных роботов.
Модули функций
правитьЧерез модули функций возможно добавление в RCML новых функций, которые не целесообразно или невозможно реализовывать на данном языке, например, какие-либо сложные вычисления. Таким образом, через отдельный API модули функции позволяют реализовать связь RCML с программным обеспечением других производителей.
Модули управления
правитьМодули управления служат для связи различных управляющих устройств со средой RCML с целью использования данных устройств в ручном управлении роботами, чьи модули предоставляют такую возможность. Данный тип модулей подобен модулям роботов в том плане, что через заданный API происходит разрыв зависимостей между управляющим устройством и роботом. Таким образом, реализуется возможность управления одним и тем же роботом разными устройствами, а также возможность применения одного и того же устройства управления для разных роботов. Разумеется, при этом достигается тот же эффект сокрытия реализации связи устройства управления от среды RCML и достигается возможность подключения самых разных устройств управления.
Использование робота в программе
правитьЧтобы задействовать робота в программе, необходимо указать его класс и функцию, которую он должен выполнить. Именование класса робота совпадает с именованием модуля робота в файле config.ini, но класс робота в RCML программе должен указываться через ключевое слово robot и знак подчёркивания.
Например, нужно вызвать робота из модуля test, тогда указание его класса будет иметь вид:
robot_test
Встретив наименование класса робота в тексте программы, RCML пошлёт запрос к соответствующему модулю робота и остановит выполнение программы, пока не будет найден свободный робот требуемого класса.
Вызов функции робота
правитьФункции роботов программируются разработчиком робота вместе с модулем робота и описываются в документации к модулю робота.
Вызов функции визуально похож на вызов метода объекта в С-подобных языках программирования. Следует указание класса робота, затем через знак указателя ->
обозначается требуемая функция, затем в круглых скобках (
)
перечисляется список аргументов этой функции.
Синтаксис вызова функции робота:
robot_класс_робота->функция_робота(аргументы);
Например, из робота класса test нужно вызвать функцию do_something с одним аргументом 1000:
robot_test->do_something(1000);
Встретив подобную конструкцию, интерпретатор зарезервирует робота указанного класса, дождется, когда будет задействован реальный физический робот, и затем передаст команду представлению робота об исполнении указанной функции с указанными параметрами. После исполнения функции робот будет автоматически освобожден и переведен в статус свободного.
Следует отметить, что при таком указании вызова функции робота интерпретатор дождётся подтверждения выполнения функции от представления робота и только затем продолжит выполнение остальной программы.
Работа с конкретным экземпляром робота
правитьЧасто бывает необходимо вызвать не одну функцию у робота, а сразу несколько, и их должен выполнить один робот как заданную последовательность действий. Если вызвать необходимую последовательность функций, то при наличии нескольких роботов одного класса вполне вероятно, что заданные функции будут выполняться разными роботами. В случае если же робот заданного класса всего один в наличии, то для каждой функции он будет каждый раз задействован и освобождён.
Наиболее эффективно и рационально задействовать робота единожды и передавать ему команды так, как это необходимо, а затем его освободить, таким образом реализовав сеанс работы робота. Для этого требуется задействовать робота нужного класса и запомнить связь с задействованным конкретным роботом. Это можно сделать, сохраняя робота в специальный тип переменных, перед идентификатором которых должен быть поставлен символ @
. Например, задействование робота класса test
и сохранение связи с конкретным полученным экземпляром в переменной @r
:
@r = robot_test;
Чтобы вызвать выполнение функции у данного задействованного робота, нужно вызывать функцию, обращаясь к данной переменной, а не к классу робота. Например, вызов у используемого робота той же самой функции do_something
с параметрами:
@r->do_something(1000);
После выполнения функции робот так же останется задействованным, и можно вызывать следующую функцию у данного экземпляра.
Высвобождение задействованного робота
правитьРобота, сохранённого в тип переменной @
, можно освободить, используя специальный оператор delete
, когда это потребуется. С данным оператором должна указываться специальная переменная, хранящая указатель на освобождаемого робота. Пример освобождения робота, указатель на которого был ранее присвоен в переменную @r
:
delete @r;
Все роботы, задействованные и не освобождённые через оператор delete
, будут освобождены только при завершении выполнения функции, в которой они были задействованы. Данное утверждение не относится к функциям робота, написанным на RCML, т.к. в эти функции выполняются в контексте экземпляра робота, и в них нельзя задействовать экземпляр робота.
Автоматический выбор робота
правитьОдна из возможностей RCML — это автоматический подбор робота под задачу. Чтобы использовать данную возможность, нужно указывать только ключевое слово robot вместо конкретного класса робота в тех местах, где требуется указание класса робота: вызовы функций робота или присвоение робота в переменную. Например:
robot->do_something(1000);
@r = robot;
@r->do_something();
Использование только ключевого слова robot
вместо полного имени класса робота далее будет называться абстрактным роботом.
В случае использования специальной переменной @
для связи с абстрактным роботом RCML проанализирует каждый вызов функции относительно данной переменной и составит список кандидатов только из тех типов роботов, которые имеют все вызываемые функции относительно данной переменной.
Указание режимов выполнения функций
правитьИсполнение функций, написанных на 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 main() {
@rt_1=robot_test;
@rt_2=robot_test;
@rt_1->do_something(1000);
@rt_2->print("Hello world!\n", 0);
}
В результате выполнения программы тестовый робот @rt_1
выполнит функцию do_something
и только после этого будет задействован второй робот @rt_2
, который выведет на экран строку Hello world!
.
Однако, если использовать флаг без ожидания ~
и передать его функции выполняемой первым роботом @rt_1
.
function main() {
@rt_1=robot_test;
@rt_2=robot_test;
~@rt_1->do_something(1000);
@rt_2->print("Hello world!\n", 0);
}
Выполнение программы будет происходить следующим образом. После того как передана команда @rt_1
, происходит дальнейшее выполнение программы. Тестовый робот, тем временем, @rt_2
выведет на экран Hello world!
и уже после этого @rt_1
завершит выполнение функции.
Исключения
правитьRCML позволяет обрабатывать исключительные ситуации, аналогично языкам программирования C, Java и JavaScript.
Однако в RCML, оператор try
может принимать параметры, указывающие, как именно ему работать. Первый параметр - это строковая константа с указанием режима работы, в зависимости от указанного режима может указываться второй параметр вещественного типа данных.
Всего у оператора try
три режима работы:
"error_default"
- режим работы по умолчанию, как обычный операторtry
. В этом случае второй параметр оператораtry
не указывается. Если параметры оператораtry
опускаются как в вышеприведённом примере, то операторtry
работает именно в этом режиме."error_time_limit"
– режим работы с отсчётом лимита времени, за который должен быть выполнен блок кода оператораtry
. В данном случае указывается второй параметр, который задаёт количество миллисекунд, являющийся лимитом на выполнение блока кода оператораtry
. В случае если данный блок не будет выполнен за указанное время, будет брошено исключение. В случае если исключение будет брошено раньше, отсчёт времени будет прекращён, а само исключение будет обработано в обычном режиме."error_try_count"
– режим работы с отсчётом количества попыток, данных для выполнения блока оператораtry
. В данном режиме второй параметр принимает количество допустимых попыток исполнения данного блока. При каждом брошенном исключении в блоке оператораtry
счётчик количества попыток будет уменьшаться на 1, и если он достигнет нуля, то будет произведена обычная обработка исключения.
Несмотря на то, что оператор try
может принимать параметры, он не является функцией и не возвращает значение.
Пример использования указанных режимов для обработки успешности выполнения роботом своей функции с выдачей ему трёх попыток с лимитом времени по 2 секунды на каждую:
function main() {
try("error_try_count", 3) {
try(“error_time_limit”, 2000) {
robot->do_something();
} catch { //если время вышло
throw; //то бросаем исключение, чтобы исчерпать попытку
}
} catch {
//этот блок выполнится, когда все попытки будут исчерпаны,
//а результат так и не будет получен
}
}
Через оператор throw
с исключением можно передать значение исключения.
Режим ручного управления
правитьСреда RCML может предоставить возможность ручного управления конкретным экземпляром робота посредством конкретного управляющего устройства при вызове системной функции hand_control
с соответствующими параметрами.
Основной принцип действия среды RCML при переходе в режим ручного управления заключается в связывании осей робота, по которым он может так или иначе передвигаться, с осями управляющего устройства, по которым данное устройство может фиксировать изменения.
На рисунке есть гусеничный робот (изображён слева), который может переходить в своё новое абсолютное положение на плоскости посредством ряда изменений своего положения по двум осям: оси передвижения R
(вперёд или назад) и оси вращения A
(влево или право). И есть простое управляющее устройство по типу джойстика (изображено справа), которое может отклоняться в плоскости от своего начального положения по двум осям X
и Y
. Соответственно, через RCML возможно связать оси джойстика и робота так, чтобы отклонение джойстика приводило к движению робота. Например, отклонение джойстика по оси Y
в положительную сторону приводило к движению вперёд, а отклонение джойстика по оси X
в отрицательную сторону приводило к повороту робота влево. Предположим, что данный робот представлен в среде RCML модулем робота parrot
, а джойстик, соответственно, модулем управления joy
, тогда RCML код для их связи в режиме ручного управления для получения эффекта, приведённого в примере, будет следующим:
@r = robot_tarakan;
hand_control(@r, “joy”, “R”, “Y”, “A”, “X”);
Пакетная передача команд роботам
правитьУ представления робота в среде RCML есть очередь команд, которая наполняется командами путём вызова функций робота из кода на RCML. При поступлении команды в пустую очередь, команда будет передана роботу на исполнение. Пока исполняется первая команда, все вновь поступившие команды становятся в очередь. Робот выполняет функцию в материальном мире обычно медленнее, чем RCML интерпретатор успевает выполнить очередной код на RCML и дойти до следующего вызова функции робота, т.е. обычно действия робота "медлительнее" действий вычислительного процессора.
Однако бывает иная ситуация, когда роботу необходимо выполнить серию быстрых перемещений без остановки, а расчёт параметров этих перемещений занимает больше времени, чем выполняется перемещение. Тогда эффективнее заранее рассчитать параметры перемещений и передать роботу сразу пакет команд с рассчитанными параметрами, чтобы робот не замедлялся в ожидании очередной команды. Бывают ситуации, что сам механизм вызова функций работает медленнее, чем робот исполняет команды, и возникает задержка в быстрой серии перемещений.
Чтобы скомпенсировать этот эффект, был введён механизм пакетной передачи команд роботу. Команды, получаемые посредством вызова функций робота, можно скомпоновать в единый пакет и передать целиком представлению робота. Чтобы отправить команду в пакет, нужно поставить перед вызовом функции символ >
. Чтобы отправить пакет на выполнение, нужно вызвать системную функцию send_package()
.
//отправка команды в пакет
>robot_test->do_something(1000);
//отправка пакета на выполнение
system.send_package();
В данном примере сначала будет послан запрос на свободного робота класса test
, и только когда робот будет найден, функция будет передана в пакет, и затем пакет будет отправлен. Как и в вызове функций робота, при пакетной передаче команд роботы исполнители резервируются заранее. После вызова функции send_package
возможно формирование нового пакета, в том числе и не дожидаясь исполнения предыдущего пакета при помощи использования флага ~
выполнения функции.
Возможно составление пакета сразу для двух роботов, команды из этого пакета будут переданы сразу двум представлениям роботов, дополнительно можно комбинировать типы вызовов функций.
>robot_test->do_something(1000);
>robot_test->do_something(1000);
system.send_package();
Согласно данному примеру, будут задействованы два робота одновременно, а не один и тот же два раза подряд. В таком случае, выполнение первых команд в очереди каждого представления робота начнётся одновременно. Данный механизм позволяет синхронизировать начало выполнения разными роботами своих команд.
Примеры на RCML
правитьПростейшая программа на RCML
правитьПростейшая программа на RCML имеет следующий вид:
function main() {
return;
}
Программа сразу после запуска завершит работу.
Программа "Hello,_world!
правитьВывод в консоль строки "Hello world!", через модуль тестового робота.
function main() {
robot_test->print("Hello world!\n", 0);
}
Пример программы работающей с пулом роботов
правитьКак отмечалось ранее RCML ориентирован на работу с пулом (множеством) роботов, из которого выделяются исполнители для решения динамически возникающих задач.
Пусть есть пул роботов, некоторые роботы из этого пула способны выполнить необходимую технологическую функцию do_something()
. Необходимость выполнения данной функции определяет некий внешний сенсор, тогда программа для динамического распределения задач выполнения данной функции будет иметь вид:
function main() {
loop {
have_new_task = get_data_from_sensor();
if (have_new_task) {
~robot->do_something();
}
system.sleep(300);
}
}
В данной программе в цикле с интервалом 300 мс, опрашивается внешний сенсор посредством функции get_data_from_sensor()
, строка 3. В случае если возникла необходимость выполнения функции, то будет задействован первый свободный робот из пула, способный выполнить функцию do_something()
, строка 5. При этом программа не будет ожидать выполнения функции роботом, т.к. установлен флаг выполнения функции без ожидания ~
. Это позволит программе не замедлиться в период выполнения роботом своей функции и продолжить опрашивать сенсор с заданным интервалом.
В случае если через очередные 300 мс, снова потребуется выполнение функции, а первый задействованный робот ещё не закончил работу, то RCML задействует второго робота из пула, и т.д. После выполнения заданной функции роботы будут автоматически освобождены и возвращены в общий пул. В случае если все роботы будут задействованы, программа будет ожидать освобождения робота.
Данный приём позволяет динамически распределять среди роботов задачи из очереди и задействовать сразу нескольких роботов.
Пример программы для работы с пулом разнотипных роботов
правитьПусть имеется задача перемещения деталей весом от 1 до 15 кг, детали поступают последовательно, однако их необходимо перемещать по возможности наиболее быстро. Имеется пул разнотипных роботов, среди которых роботы класса robot_heavy
большей грузоподъёмности (до 10 кг) и robot_light
меньшей грузоподъёмности (до 5 кг). При этом robot_heavy
перемещает деталь за 10 секунд, а robot_light
за 5 секунд. Таким образом, выполняемые роботами задачи параметризованы, и на основе имеющегося параметра (веса детали) необходимо принимать наиболее рациональное решение какой тип робота задействовать, чтобы обеспечить минимальный простой и максимальную производительность участка. С целью показать применение пакетов команд в рамках данного примера допустим, что деталь весом более 10 кг могут нести два робота одновременно.
function main() {
loop {
detail_weight = get_weight_from_sensor(); //Получение веса детали
if (detail_weight < 5) { //Если вес до 5 кг
~robot->move_detail(); //Можно задействовать любого робота
}
if ((detail_weight >= 5) && (detail_weight < 10)) { //Если вес от 5 до 10 кг
~robot_heavy->move_detail(); //Можно задействовать только более грузоподъемного робота
}
if (detail_weight >= 10) { //Если вес от 10 кг
>robot_heavy->move_detail(); //Один робот обязательно должен быть более грузоподъемный
>robot->move_detail(); //Второй робот может быть любым
~system.send_package(); //Отправка пакета команд для роботов на выполнение
}
system.sleep(300);
}
}
В случае если вес детали менее 5 кг, то деталь может нести робот любого класса, строка 5. Однако, RCML сначала опросит всех роботов класса robot_light
и если среди них не окажется свободного, то будет произведён опрос роботов класса robot_heavy
(Приоритет опроса классов роботов задаётся в конфигурации интерпретатора RCML). Первый свободный робот будет задействован для перемещения, по аналогии с предыдущим примером, без ожидания основной программы выполнения роботом своей функции - перемещения детали. Таким образом RCML попытается задействовать сначала робота наиболее подходящего класса robot_light
, а если свободного робота такого класса нет, то будет задействован робот менее подходящего класса robot_heavy
, чтобы не допустить простоя.
Однако в случае, если вес детали от 5 до 10 кг, то можно задействовать только более грузоподъемного робота, строка 7.
В случае если вес детали от 10 кг, то надо задействовать двух роботов, среди которых один должен быть более грузоподъёмным, а второй любым. Стоит отметить, что в данном случае команда на перемещение детали передаётся двум роботам одновременно, посредством механизма составления пакетов команд (строки 11-15).
Следует отметить, что данный пример предполагает, что детали поступают строго последовательно, т.е. следующая деталь поступает только тогда, когда робот забрал предыдущую и переносит её некоторое время. Таким образом, очередь заданий для роботов также последовательна и в случае, если поступает несколько тяжёлых деталей, а затем лёгкая, то лёгкая деталь будет перемещена, только когда все тяжёлые детали будут перемещены, из-за этого возможен простой роботов класса robot_light
.
Пример программы с непоследовательным выбором роботами задач из очереди
правитьУсложним предыдущий пример. Пусть детали поступают в некий контейнер беспорядочно, система технического зрения наблюдает контейнер и распознает детали в нём, получая координаты и тип детали, а по типу определяет её вес. При распознавании очередной детали нужно поставить задачу роботам на перемещение детали. При распознавании деталей некая функция get_new_detail_index()
будет возвращать уникальный индекс распознанной детали, по которому впоследствии можно получить координаты и вес детали, необходимые для принятия решения по задействованию роботов и перемещению, соответственно.
function executeMoveTask(detail_index) {
detail_weight = get_weight_by_index(detail_index); //Получение веса детали
detail_coords = get_coords_by_index(detail_index);
if (detail_weight < 5) { //Если вес до 5 кг
~robot->move_detail(detail_coords); //Можно задействовать любого робота
}
if ((detail_weight >= 5) && (detail_weight < 10)) { //Если вес от 5 до 10 кг
~robot_heavy->move_detail(detail_coords); //Можно задействовать только более грузоподъемного робота
}
if (detail_weight >= 10) { //Если вес от 10 кг
>robot_heavy->move_detail(detail_coords); //Один робот обязательно должен быть более грузоподъемный
>robot->move_detail(detail_coords); //Второй робот может быть любым
~system.send_package(); //Отправка пакета команд для роботов на выполнение
}
}
function main() {
loop {
new_detail_index = get_new_detail_index(); //Получение очередного индекса детали
if (new_detail_index) { //Новая деталь поступила
~executeMoveTask(new_detail_index); //Выполняем задачу по перемещению
}
system.sleep(300);
}
}
В данном примере при поступлении новой детали в контейнер, будет получен её уникальный индекс (строка 19), который будет передан в функцию executeMoveTask
(строка 21), в которой выполняется задействование роботов, т.е. по сути формирование запросов к пулу роботов. Особо следует отметить, что данная функция вызывается с флагом без ожидания ~
.
В сумме это даёт следующий эффект: если в контейнер поступило некоторое большое количество тяжёлых деталей весом до 10 кг, и из пула свободных роботов были задействованы все грузоподъёмные роботы robot_heavy
, а затем в контейнер поступило некоторое количество легкий деталей весом до 5 кг, то RCML сможет задействовать ранее простаивающих роботов класса robot_light
до того как роботы класса robot_heavy
переместят все тяжёлые детали. Переместив задействование робота в отдельную функцию выполняемую без ожидания по сути мы получили возможность формировать различные очереди задач для различных классов роботов. Таким образом, простой роботов при наличии подходящих для них задач, будет сведён к минимуму, что было невозможно в предыдущем примере при строгой очерёдности поступления задач.
Пример создания RCML программы, универсальной для разных классов роботов
правитьRCML даёт возможность программисту явно указать, что некоторые роботы могут выполнять одну и ту же функцию одинаково и тем самым они могут считаться взаимозаменяемыми при выполнении данной функции, хотя при этом роботы имеют различный API предоставляемый для программиста на уровне RCML.
В вышеприведённых примерах встречаются строки вида robot->move_detail()
, с использованием ключевого слова robot
. Данное ключевое слово сообщает RCML, что для выполнения данной функции можно задействовать любого робота из пула обладающего запрашиваемой функцией move_detail()
.
Пусть у классов роботов robot_heavy
и robot_light
имеется набор функций для управления захватом и перемещением захвата, однако функции в этих набор имеют разные имена и отличающиеся параметры.
Следующий пример показывает как унифицировать API роботов в рамках конкретной программы, чтобы разные классы роботов могли выполнять одну и ту же функцию.
function robot_heavy::move_to(x, y, z, w, p, r) {
//Далее следует код для перемещения в заданную точку,
//путём обращения к функциям специфичным для роботов класса robot_heavy
robot->set_real_di("x",x);
robot->set_real_di("y",y);
robot->set_real_di("z",z);
robot->set_real_di("w",w);
robot->set_real_di("p",p);
robot->set_real_di("r",r);
robot->go_position();
}
function robot_heavy::gripper(s) {
//Специфичный, для robot_heavy, код управления захватом
if (s) {
robot->set_gripper_pos(124,25);
} else {
robot->set_gripper_pos(350,50);
}
}
function robot_light::move_to(x, y, z, w, p, r) {
//Специфичный, для robot_light, код перемещения захвата
robot->move_to(x,y,z);
robot->set_angle(w,p,r);
}
function robot_light::gripper(s) {
//Специфичный, для robot_light, код управления захватом
if (s) {
robot->pump_on();
} else {
robot->pump_off();
}
}
function main() {
//Универсальный код для перемещения детали роботом любого класса
robot->move_to(46,76,73,235,-34,23); //Переместиться к заготовке
robot->gripper(1); //Захватить деталь
robot->move_to(235,34,47,262,673,74); //Переместить деталь к позиции 1
system.sleep(15000); //Ожидать время измерения детали на позиции 1
if (some_check()) {
//Переместить захват робота к контейнеру с качественными деталями
robot->move_to(35,63,23,25,-48,245);
robot->gripper(0); //Освободить деталь
} else {
//Переместить захват робота к контейнеру с браком
robot->move_to(568,778,346,-54,2,34);
robot->gripper(0); //Освободить деталь
}
}
В данном случае алгоритм перемещения и проверки сможет выполнять как класс роботов robot_heavy
, так и класс роботов robot_light
, хотя они имеют разный API предоставляемый на уровне RCML.
См. также
правитьПримечания
править- ↑ "Интервью с разработчиками RCML", портал Properm, 2015 . Дата обращения: 26 февраля 2016. Архивировано 3 марта 2016 года.
- ↑ "RCML Описание технологии", Премия Роснаука, 2015 . Дата обращения: 26 февраля 2016. Архивировано из оригинала 5 марта 2016 года.
- ↑ "Из интервью разработчиков", Электронное издание «Наука и технологии России», 2015 . Дата обращения: 26 февраля 2016. Архивировано 3 марта 2016 года.
- ↑ "Основы построения программ на RCML" . Дата обращения: 26 февраля 2016. Архивировано из оригинала 3 марта 2016 года.
Литература
править- Д.К. Сутормин, М.В. Тюлькин. = Robot Control Meta Language. Метаязык для роботов, 2-е издание. — Пермь: Астер Диджитал, 2015. — 108 с. — ISBN 978-5-9905-655-0-0 (рус.) ISBN 978-5-9905-655-3-1 (англ.).
- Дейкстра Э. Дисциплина программирования = A discipline of programming. — 1-е изд. — М.: Мир, 1978. — 275 с.
- Александр Степанов, Пол Мак-Джонс. Начала программирования = Elements of Programming. — М.: Вильямс, 2011. — С. 272. — ISBN 978-5-8459-1708-9.
- Макаров И. М., Топчеев Ю. И. Робототехника: История и перспективы. — М.: Наука; Изд-во МАИ, 2003. — 349 с. — (Информатика: неограниченные возможности и возможные ограничения). — ISBN 5-02-013159-8.
- Роберт У. Себеста. Основные концепции языков программирования / Пер. с англ. — 5-е изд. — М.: Вильямс, 2001. — 672 с. — ISBN 5-8459-0192-8 (рус.) ISBN 0-201-75295-6 (англ.).
- Иан Соммервилл. Инженерия программного обеспечения / Пер. с англ. — 6-е издание. — М.: Вильямс, 2002. — 624 с.
- Иан Грэхем. Объектно-ориентированные методы. Принципы и практика / Пер. с англ. — 3-е изд. — М.: Вильямс, 2004. — 880 с.
Ссылки
править- RCML Официальный сайт разработчика RCML
- Официальное руководство по RCML
- Что такое RCML? Видеоролик на Youtube Архивная копия от 13 февраля 2016 на Wayback Machine