URBI — введение в urbiScript — часть 5


1. введение в urbiScript — часть 1
2. введение в urbiScript — часть 2
3. введение в urbiScript — часть 3
4. введение в urbiScript — часть 4
5. введение в urbiScript — часть 5

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

Последовательное программирование не удобно при работе с высоко-интерактивными агентами (роботами). Для этого требуется реагировать на внешние случайные события, а не линейно выполнять заданный код.
urbiScript полностью отвечает этому требованию, т.к. поддерживает программирование на основе событий (event-based programming).

25. Конструкции контроля событий

25.1 at

Первая конструкция событийного программирования — это ключевое слово at.

at(выражение)
	код
onleave
	код2

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

var x = 0;
[00000000] 0
at (x > 5)
	echo("ping");
x = 5;
[00000000] 5
// это запустит(trigger) событие
x = 6;
[00000000] 6
[00000000] *** ping
// код не запускается(trigger), т.к. выражение уже истинно.
x = 7;
[00000000] 7
// выражение станет ложным
x = 3;
[00000000] 3
x = 10;
[00000000] 10
[00000000] *** ping

Блок onleave может определять код для выполнения, кода выражение становится ложным.

var x = false;
[00000000] false
at (x)
	echo("x")
onleave
	echo("!x");
x = true;
[00000000] true
[00000000] *** x
x = false;
[00000000] false
[00000000] *** !x

25.2 whenever

Ключевое слово whenever аналогично at, однако выполнение кода систематически перезапускается в случае если условие/выражение остаётся истинным.

var x = false;
[00000000] false
whenever (x)
{
	echo("ping");
	sleep(1s);
};
x = true;
[00000000] true
sleep(3s);
// код whenever выполняется снова и снова
[00000000] *** ping
[00001000] *** ping
[00002000] *** ping
x = false;
[00002000] false
// код whenever не выполняется

Как at имеет onleave, так и whenever имеет else: код будет выполняться снова и снова пока выражение/условие остаётся ложным.

var x = false;
[00002000] false
whenever (x)
{
	echo("ping");
	sleep(1s);
}
else
{
	echo("pong");
	sleep(1s);
};
sleep (3s);
[00000000] *** pong
[00001000] *** pong
[00002000] *** pong
x = true;
[00003000] true
sleep (3s);
[00003000] *** ping
[00004000] *** ping
[00005000] *** ping
x = false;
[00006000] false
sleep (2s);
[00006000] *** pong
[00007000] *** pong

25.3 every

Ключевое слово every позволяет запустить повторение выполнения кода через заданный период времени.

// печатает сообщение каждую секунду
timeout (2.1s)
	every (1s)
		echo("Are you still there?");
[00000000] *** Are you still there?
[00001000] *** Are you still there?
[00002000] *** Are you still there?

25.4 waituntil

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

var e = Event.new;
{
	waituntil (e?);
	echo ("caught e");
},
e!;
[00021054] *** caught e

26. События

urbiScript позволяет определять события, которые должны обрабатываться с помощью конструкций at и whenever.
Событие может быть создано с использованием прототипа Event. Запуск события можно выполнить с помощью команды (!).

var myEvent = Event.new;
[00000000] Event_0x0
at (myEvent?)
	echo("ping");
myEvent!;
[00000000] *** ping
// события хорошо работают параллельно
myEvent! & myEvent!;
[00000000] *** ping
[00000000] *** ping

С событиями at и whenever работают, как и было показано ранее. Т.е. at отрабатывает один раз при изменении/переключении условия/выражения. А код whenever выполняется снова и снова.

var myEvent = Event.new;
[00000000] Event_0x0
whenever (myEvent?)
{
	echo("ping (whenever)")|
	sleep(200ms)
};
at (myEvent?)
{
	echo("ping (at)")|
	sleep(200ms)
};
// запустим myEvent на 0.3 секунды
myEvent! ~ 300ms;
[00000000] *** ping (whenever)
[00000100] *** ping (whenever)
[00000000] *** ping (at)

27. Исключения

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

throw 42;
[00000000:error] !!! 42
function inner() { throw "exn" } |
function outer() { inner() }|
// Exceptions propagate to parent call up to the top-level
outer();
[00000000:error] !!! exn
[00000000:error] !!! called from: 3.20-26: inner
[00000000:error] !!! called from: 4.1-7: outer 

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

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

function test(e)
{
	try
	{ throw e; }
	catch (0)
	{ echo("zero") }
	catch ([var x, var y])
	{ echo(x + y) }
} | {};
test(0);
[00002126] *** zero
test([22, 20]);
[00002131] *** 42
test(51);
[00002143:error] !!! 51
[00002143:error] !!! called from: 12.1-8: test

27.2 Просмотр исключений
Исключение — это объект Exception, у которого можно посмотреть свойства.

try
{
	Math.cos(3,1415);
}
catch (var e)
{
	echo ("Exception type: %s" % e.type);
	if (e.isA(Exception.Arity))
	{
		echo("Routine: %s" % e.routine);
		echo("Number of effective arguments: %s" % e.effective);
	};
};

28. Проверки с помощью assert

функция assert позволяет осуществлять проверки в коде. Эта функция очень полезна для отладки и отлова ошибок во время написания программы.
Однако использование этой функции в конечной версии программы нежелательно, т.к. сильно влияет на производительность.
Поэтому assert-ы можно отключить через System.ndebug.
Если переменную System.ndebug установить в true, то assert-ы выполняться не будут.

function one() { echo("called!"); 1 }|;
assert(!System.ndebug);
assert(one);
[00000617] *** called!
System.ndebug = true|;
assert(one);
System.ndebug = false|;
assert(one);
[00000622] *** called!

assert можно вызывать как обычную функцию, либо применительно к целой области

assert(1 == 1 + 1);
[00000002:error] !!! failed assertion: 1 == 1.'+'(1) (1 != 2)
assert
{ 
	1==1;
	2==2;
};
assert
{
	1==1; 
	2==3;
};
[00000000:error] !!! 30.1588-1591: failed assertion: 2 == 3 (2 != 3)
[00000000:error] !!! called from: 30.1588-1591: assertCall

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение