## Создание программ в TRIK Studio

### Работа с диаграммами

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

Если проект уже открыт, создать новый можно с помощью меню или панели инструментов "Файл":

Главная диаграмма создаётся при создании проекта, диаграммы с подпрограммами создаются автоматически при помещении блока "Подпрограмма" на сцену, при этом отображение подпрограммы происходит при двойном клике на блок "Подпрограмма" на сцене. Обычно в этом нет нужды, но просмотреть все созданные подпрограммы или удалить их можно с помощью окна "Блоки", которое по умолчанию не показывается, но его можно включить через меню "Вид" -> "Панели":

### Создание блоков

Блоки в TRIK Studio создаются перетаскиванием соответствующих иконок из палитры элементов на диаграмму, либо жестом мышью. Чтобы создать блок жестом, надо с зажатой правой кнопкой начертить на сцене условное изображение блока, после чего блок появится в центре нарисованного изображения. Доступные условные изображения можно просмотреть в окне "Жесты мышью", открывающемся через пункт меню "Инструменты" -> "Жесты мышью", либо во всплывающей подсказке, появляющейся при наведении курсора мыши на блок в палитре. Жесты можно рисовать несколькими штрихами, ввод жеста заканчивается, если штрихи некоторое время не рисовали (это время настраивается в окне настроек, вкладка "Поведение"). Список доступных блоков зависит от выбранного конструктора и от модели робота (реальный робот или двумерная модель). При этом недоступные для данного конструктора блоки не показываются вообще, а недоступные для данной модели в рамках одного конструктора блоки показываются в палитре серым и недоступны для перетаскивания на сцену. Есть блоки, общие для всех конструкторов, программа, использующая только такие блоки, будет исполняться на любом конструкторе без каких-либо правок. Список таких блоков приведён ниже:

Название элемента | Пиктограмма | Описание
Начало |  | Начальная точка выполнения программы. На каждой диаграмме такой блок должен быть только один, в него не должно быть входящих связей, исходящая связь из этого элемента должна быть только одна. Процесс интерпретации диаграммы начинается именно с этого блока.
Конец |  | Конец программы. Если программа состоит из нескольких параллельных участков выполнения, достижение этого блока завершает соответствующий участок выполнения. У данного блока не может быть исходящих связей.
Функция |  | Посчитать значение заданного выражения. Также в данном блоке допускается определение переменных. Подробнее про синтаксис допустимых выражений параметра "Функция" см. в разделе Синтаксис выражений.
Условие |  | Разделить выполнение программы в соответствии с заданным условием. Значением параметра "Условие" является некое логическое выражение (подробнее см. раздел Синтаксис выражений), на основе значения которого будет осуществлен выбор дальнейшего пути выполнения диаграммы. У данного блока должны быть две исходящие связи, у хотя бы одной из которых должно быть задано значение параметра "Условие": "истина" или "ложь".
Конец условия |  | Обозначает слияние двух веток условного оператора. Никаких действий не выполняет, но полезен для обеспечения структурности программы: если придерживаться правила, что все ветки операторов "Условие" или "Выбор" сходятся на таком блоке, это существенно повысит шансы на то, что генератор сможет породить код на текстовом языке без операторов goto.
Выбор |  | Условие с несколькими альтернативами. В параметре "Выражение" можно указать произвольное выражение (подробнее см. раздел Синтаксис выражений), на основе значения которого будет осуществлен выбор дальнейшего пути выполнения диаграммы. У данного блока должны быть несколько исходящих связей, каждая из которых (кроме одной) должна быть помечена элементарным значением (строка, число и др.), которое может принимать выражение (значение просто пишется в свойство "Условие" у связи). Одна из связей должна быть не помечена, по ней осуществляется переход, если выражение не равно ни одному из перечисленных значений.
Цикл |  | Блок, организующий выполнение последовательности блоков несколько раз. Число повторений задается значением параметра "Итераций". Блок должен иметь две исходящие связи, одна из которых должна быть помечена значением "тело цикла" (то есть значение параметра "Условие" должно быть "тело цикла"). Другая связь, исходящая из блока "Цикл", должна оставаться непомеченной: по ней будет осуществляться переход, когда программа пройдет через блок "Цикл" указанное число раз. Бесконечные циклы и циклы вида while/do while организуются без использования этого блока, зацикливанием потока управления с помощью связей, выход из такого цикла осуществляется с помощью блока "Условие".
Подпрограмма |  | Вызов подпрограммы. Подпрограммы используются для того, чтобы вынести повторяющиеся фрагменты программы на отдельную диаграмму, а потом вызывать фрагмент программы с этой диаграммы в нескольких местах основной программы или других подпрограмм. При добавлении этого блока на диаграмму будет предложено ввести имя подпрограммы, после чего двойным кликом на блоке можно будет перейти на диаграмму, соответствующую данной подпрограмме. Кроме того, появится дополнительная палитра со всеми подпрограммами, подпрограммы из неё можно перетаскивать на сцену и использовать как обычные блоки.
Параллельные задачи |  | Разделить выполнение программы на несколько потоков, которые с точки зрения программиста будут выполняться параллельно. Так, например, можно одновременно ждать срабатывания сенсора и истечения временного интервала. Блок должен иметь хотя бы две исходящие связи. Чтобы иметь возможность далее ссылаться на параллельные задачи, порождённые этим блоком (например, в блоке "Завершить задачу" или в блоке "Слияние задач") надо дать задачам имена. Это делается на исходящих связях, в свойстве "Условие". Именем задачи может быть любая строка, но одним из имён должно быть имя задачи, которая входит в этот блок. Имя главной программы – main.
Слияние задач |  | Блок слияния параллельных задач. Блокирует исполнение программы до тех пор, пока исполнение всех параллельных задач, входящих в этот блок, не достигнет этого блока. Должен иметь не менее двух входящих связей, на исходящей связи (в свойстве "Условие") должен быть идентификатор задачи, которая продолжится после того, как блок отработает.
Завершить задачу |  | Завершает задачу с указанным в свойстве "Задача" идентификатором. Должен применяться из другой задачи.
Инициализация переменной |  | Объявить новую переменную и задать ей значение. В свойстве "Переменная" указывается имя переменной, в свойстве "Значение" указывается выражение, определяющее начальное значение переменной. Того же можно добиться с помощью блока "Функция", но этот блок делает программу понятнее.
Случайное число |  | Присвоить указанной переменной случайное целое число из заданного с помощью свойств "От" и "До" промежутка.
Комментарий |  | Возможность добавить на диаграмму произвольный текст в качестве комментария. Используется для того, чтобы пояснить какой-то конкретный блок или участок диаграммы, может быть связан с блоком, который он поясняет. При выполнении программы не учитывается.
Таймер |  | Ждать заданное количество времени, в миллисекундах.
Опустить маркер |  | Начать рисование маркером заданного цвета на полу. При движении робота в двумерной модели за ним будет оставаться цветная линия. Блок доступен только в режиме двумерной модели.
Поднять маркер |  | Закончить рисование маркером. Блок доступен только в режиме двухмерной модели.

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

- ТРИК
- Lego NXT
- Lego EV3

### Создание связей

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

Связи в TRIK Studio можно создавать несколькими способами. Первый подход: для того, чтобы создать связь между блоками A и B, надо навести курсор на блок A, нажать правую кнопку мыши и, не отпуская ее, провести линию до элемента B (форма линии может быть произвольной, важно, чтобы она начиналась строго на элементе A и заканчивалась на элементе B). При этом на сцене это будет отражено следующим образом (элемент A в нашем случае — это блок "Начало", B — блок "Конец"):

При отпускании правой кнопки мыши элементы A и B окажутся соединенными связью:

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

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

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

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

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

При этом, если точку излома связи разместить так, что она и две ближайшие к ней будут располагаться примерно на одной прямой (см. рисунок ниже), то это приведет к уничтожению этой точки излома и сглаживанию ломаной в этом месте:

Фиолетовым подсвечивается старое расположение линии, вернуться к которому можно, нажав правую кнопку мыши (при зажатой левой).

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

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

### Синтаксис выражений

Для объявления переменных и задания им определенных значений используется блок "Инициализация переменной", для записи математических вычислений – блок "Функция". Также математические выражения (в том числе и изменяющие значения переменных) могут встречаться почти везде, где можно указать какое-либо значение. Блоки и их свойства, не допускающие использования математических выражений, указаны в документации по блокам. Все переменные являются в программе глобальными (т.е. их значения могут использоваться в любом блоке в программе).

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

Используемый внутри блоков язык создан на базе Lua 5.3 и во многом следует его синтаксису. Тем не менее, имеются существенные отличия, поэтому полное описание используемого в TRIK Studio языка приводится здесь.

#### Типы

В отличие от Lua, язык TRIK Studio статически типизирован, то есть тип каждого выражения и каждой переменной должен быть известен во время компиляции. При этом язык не требует (и даже не позволяет!) явно писать типы переменных, используется автоматический вывод типов по использованию переменных. Например, по выражению "a = 1" среда "поймёт", что тип a – целое. Базовые типы языка таковы:

- Булевый (логический) тип, принимает значения true (истина) и false (ложь)
- Вещественное число, использующее 64-битное представление binary64 стандарта IEEE 754 (позволяет хранить значения до 1.7E+308)
- Целое число, использующее 32-битное знаковое представление (позволяет хранить значения от -2,147,483,648 до 2,147,483,647)
- Строка, позволяет хранить символьные строки произвольной длины в кодировке UTF-8
- Нулевой тип, имеющий только одно значение nil и означающий отсутствие "настоящего" значения
- Тип "Таблица" (или массив), позволяющий хранить произвольное количество значений произвольного (но для каждого значения в одной таблице одинакового) типа, в том числе и другие таблицы, и обращаться к значениям по индексу.

#### Лексемы языка

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

В языке есть следующие ключевые слова:

    and false nil not or true

И следующие операторы:

    + - * / % ^ # & ~ | << >> // == ~= <= >= < > = ( ) { } [ ] ; : , . .. && ||

Строковые литералы пишутся либо в одинарных, либо в двойных кавычках, например:

    a = 'alo123'
    a = "alo123"

Целые числа пишутся либо в десятичной, либо в восьмеричной, либо в шестнадцатеричной системе. Шестнадцатеричные числа начинаются с префикса 0x, восьмеричные --- с префикса 0, например:

     3   345 --- десятичные числа
     0xff   0xBEBADA --- шестнадцатеричные числа
     07654321 --- восьмеричное число

Вещественные числа пишутся либо в "обычной", либо в "научной" форме, например:

    3.0 3.1416 314.16e-2 0.31416E1 34e1

Комментарии начинаются с "--" и продолжаются до конца строки, например:

    a = 1; -- тут комментарий

#### Операторы

Язык создавался для описания математических выражений в визуальной программе, поэтому из него были убраны все алгоритмические конструкции, подобные if и for. В языке доступны три вида операторов: оператор присваивания, оператор возврата значения и пустой оператор. Пустой оператор записывается как ";", оператор возврата значения записывается как обычное выражение и должен находиться в конце блока операторов, оператор присваивания имеет вид "переменная1, переменная2, ..., переменнаяN = выражение1, выражение2, ..., выражениеN", в самом простом виде "переменная = выражение". Пример блока операторов с двумя операторами присваивания и оператором возврата значения:

    a, b = 1, 2;
    c = 3;
    a + b + c

#### Выражения

В арифметических выражениях доступны следующие операции.

Бинарные:

- + – сложение, применимо к вещественным и целым значениям, результат целый, если оба аргумента целые, иначе вещественный
- - – вычитание, применимо к вещественным и целым значениям, результат целый, если оба аргумента целые, иначе вещественный
- * – умножение, применимо к вещественным и целым значениям, результат целый, если оба аргумента целые, иначе вещественный
- / – деление, применимо к вещественным и целым значениям, результат вещественный
- // – целочисленное деление, применимо к целым значениям, результат целый
- ^ – возведение в степень, применимо к вещественным и целым значениям, результат вещественный
- % – остаток от деления, применим к целым значениям, результат целый
- & – побитовое "и", применим к целым значениям, результат целый
- | – побитовое "или", применим к целым значениям, результат целый
- >> – побитовый сдвиг вправо, применим к целым значениям, результат целый
- << – побитовый сдвиг влево, применим к целым значениям, результат целый
- .. – конкатенация, применим к строковым значениям, результат – строка
- <, <=, >, >= – операции сравнения, применимы к целым и вещественным значениям, результат булевый
- == – операция проверки равенства, применима к значениям любых типов, результат булевый
- ~=, != – операция проверки неравенства, применима к значениям любых типов, результат булевый. '~=' и '!=' являются альтернативными способами записи операции и не различаются по смыслу.
- and или && – логическое "и", применим к целым, вещественным и булевым значениям, результат булевый. Альтернативные способы записи операции по смыслу не различаются.
- or или || – логическое "или", применим к целым, вещественным и булевым значениям, результат булевый. Альтернативные способы записи операции по смыслу не различаются.

Унарные:

- - – арифметический унарный минус, применим к целым и вещественным значениям, результат целый или вещественный (в зависимости от типа аргумента)
- ~ – побитовое "не", применим к целым значениям, результат целый
- not – логическое "не", применимо к булевым, целым, вещественным и строковым значениям, результат булевый (0 или пустая строка считается false, всё остальное – true)
- # – оператор взятия длины, применим к строковым значениям, результат целый

#### Таблицы

Таблицы можно создавать явно, используя табличные выражения, так (варианты записи равносильны):

    a = {1; 2; 3; 4};
    a = {1, 2, 3, 4};

или так, с явным указанием индексов:

    a = {[0] = 1, [10] = 2, [20] = 3};

Можно использовать таблицы, не создавая их, например, так:

    a[1] = 1;
    a[2] = 2;

При этом "пустые места" в таблице (индексы, которым не было явного присваивания) будут заполнены значениями по умолчанию (0 для целых и вещественных, false для булевых и пустыми строками для строковых таблиц).

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

    a = 1;
    b = 2;
    a, b

вернёт таблицу из чисел "1" и "2". Сделано это для того, чтобы интерпретировать перечисления значений (например, порты моторов в блоке "Моторы вперёд") как таблицы, поэтому везде, где используется запись значений через запятую, можно использовать таблицу со значениями.

#### Сенсорные переменные

Помимо использования константных числовых значений программисту в TRIK Studio доступны зарезервированные переменные, которые хранят значения показаний сенсоров, подключенных к соответствующим портам. Их значения можно присваивать переменным и использовать в математических выражениях. Переменные имеют вид "sensor<имя порта сенсора>", например, sensorA1 для ТРИК или sensor1 для Lego NXT. Полный список сенсорных переменных приводится в документации к конкретным конструкторам:

- ТРИК
- Lego NXT
- Lego EV3

#### Встроенные функции

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

Название функции | Описание
time | Время в миллисекундах с начала работы программы.
sin | Синус. Аргумент передаётся в градусах.
cos | Косинус. Аргумент передаётся в градусах.
ln | Натуральный логарифм.
exp | Экспонента (e в степени аргумента).
asin | Арксинус.
acos | Арккосинус.
atan | Арктангенс.
sgn | Знак. Возвращает 1, если аргумент положительный, -1, если отрицательный, и 0, если аргумент равен нулю.
sqrt | Квадратный корень аргумента. В случае, если аргумент отрицательный, переменной будет присвоено значение "nan" (Not A Number).
abs | Модуль аргумента.
ceil | Округляет переданный аргумент до целого в большую сторону.
floor | Округляет переданный аргумент до целого в меньшую сторону.
random | Случайное число в интервале от 0 до переданного аргумента.

#### Сенсорные переменные

Доступ к значениям датчиков робота прямо из математических выражений можно получить с помощью сенсорных переменных — специальных переменных, которые содержат текущие показания датчиков робота. В режиме интерпретации программы их значения обновляются раз в примерно 200 миллисекунд, при генерации обращение к сенсорной переменной генерируется в реальное чтение показаний датчика. Из сенсорных переменных можно только читать значения. Есть также константа pi, работать с которой можно так же, как и с сенсорными переменными, но её значение не меняется. Список доступных сенсорных переменных меняется от конструктора к конструктору, переменные для текущего конструктора показываются в окне "Переменные". Список переменных для каждого конструктора приведён в соответствующих разделах документации:

- ТРИК
- Lego NXT
- Lego EV3

#### Примеры

Объявление нескольких переменных в одном блоке "Функция":

То же, через блоки "Инициализация переменной":

Пропорциональный регулятор для езды по линии с использованием двух датчиков света для конструктора ТРИК:

Пример использования массивов для задания портов блока "Моторы вперёд". Создаётся таблица (массив) с именем a, в нулевой элемент кладётся порт M3, в первый – M1, потом содержимое первого элемента массива меняется на M4, затем получившийся массив передаётся в свойство "Порты" блока "Моторы вперёд":

### Редактирование свойств элементов

В TRIK Studio имеется несколько способов редактирования значений свойств, которые имеются у блоков и связей на диаграммах. Основным из них является использование редактора свойств (см. раздел Интерфейс TRIK Studio). При выделении блока связи или элемента на сцене в редакторе свойств отображаются все свойства текущего элемента (на рисунке представлено изображение редактора свойств блока "Моторы вперёд" для конструктора Lego NXT):

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

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

### Графики

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

Из выпадающего списка снизу можно выбрать сенсор, значения с которого будут отображаться. Кнопками "Старт" и "Стоп" можно запустить или остановить снятие показаний, не прерывая работы программы. Можно регулировать масштаб графика вручную, кроме того, график автоматически масштабируется, чтобы кривая показаний помещалась по высоте целиком. Ниже располагается кнопка "Очистить график". При наведении курсора мыши на точку на графике отобразится значение в этой точке. Ниже кнопки "Очистить график" находится кнопка "Выгрузить показания в файл", которая позволяет экспортировать в формат .csv (comma-separated value) все показания выбранного датчика с начала их записи.

### Программирование на текстовом языке

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

- Создать диаграмму, содержащую только блоки "начало" и "конец", соединённые стрелкой
- Нажать на кнопку "Сгенерировать код"

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

Конкретный текстовый язык программирования зависит от выбранного конструктора и используемого генератора и среды выполнения, один конструктор может иметь несколько целевых текстовых языков, работать с которыми можно в текстовом окне. На данный момент для Lego NXT поддерживается генерация в язык С с использованием библиотеки ECRobot и в Русский Си (который не может быть исполнен на роботе и служит для иллюстрации перехода к текстовому программированию для новичков). Для конструктора ТРИК возможна генерация в JavaScript и в F#. Доступные генераторы зависят от установленных подключаемых модулей. Подробнее о возможностях написания текстовых программ можно прочитать в документации для конкретных конструкторов:

- Lego NXT, C
- ТРИК, Qt Script
- ТРИК, F#

### Упражнения

Любую диаграмму, которая уже не является упражнением, можно сохранить как упражнение, запретив тем самым редактирование некоторых её частей и предоставив возможность решить задачу в некоторых ограничениях. Сохранить диаграмму как упражнение можно с помощью пункта меню "Инструменты" -> "Сохранить как упражнение...", при этом появляется следующий диалог:

1. Двумерная модель неизменяема запрещает редактировать стены и цветные линии в двумерной модели.
2. Положение и конфигурация сенсоров неизменяемы запрещает изменять конфигурацию датчиков, а также их положение и направление в двумерной модели.
3. Начальное положение робота в двумерной модели неизменяемо запрещает двигать робот "вручную".
4. Соответствие портов моторов и колёс неизменяемо запрещает менять моторы в настройках двумерной модели.
5. Настройки симуляции двумерной модели (физика, шумы и т.д.) неизменяемы запрещает менять настройки шумов датчиков и моторов, а также физический движок в двумерной модели.

По нажатию на кнопку "ОК" появится окно, в котором можно указать файл, куда будет сохранено упражнение. Упражнение сохранится и сразу же будет открыто в TRIK Studio, где можно убедиться, что выбранные опции недоступны для редактирования. Например, так выглядит окно настроек сенсоров, если их редактирование запрещено: