Блоки программы в TRIK Studio выполняют определённые функциии и можно сказать, что та или иная программа состоит последовательности вызовов функций. Такой способ программирования движений является наглядным, но не обладает гибкостью, которую может предоставить интерпретатор данных..
На этом занятии мы рассмотрим вопрос, который обходят стороной в обучающих материалах по визуальному программированию робототехнических конструкторов. Он относится к текстовому программированию и может быть сложен для восприятия начинающими, но с другой стороны даёт в руки достаточно мощный и гибкий инструмент для программирования автоматического движения.
Попробуем при помощи тележки нарисовать прямоугольник. Для этого нужно чередовать прямолинейное движение с поворотами на 90 градусов. Определим экспериментальным путём время, за которое тележка совершит поворот на этот угол. В моём случае для этого требуется около 1050 мс. Для быстрого составления программы используйте операции копирования и вставки блоков.
После запуска программы тележка нарисует кривой незамкнутый прямоугольник. Необходимо точнее задать время поворота тележки, но не будем с этим спешить. Для изменения времени нам придётся исправить его в четырёх местах программы. Это сделать несложно, но представьте, если бы в программе было 20 поворотов! На это пришлось бы затратить очень много времени и сил, чего можно избежать при помощи подпрограмм. В нашем случае необходимо создать три подпрограммы:
Добавьте на поле диаграммы блок "Подпрограмма". После её добавления появится диалог, в котором нужно ввести имя подпрограммы "Поворот". Аналогичным образом создайте оставшиеся подпрограммы.
После замены блоков диаграмма главной программы примет следующий вид.
Подпрограмма рисования сторон отличается только значением одного параметра. Для длинной стороны время задаётся значением 3000, а для короткой - 1000. Вместо этих двух подпрограмм (функций) создадим одну, которой при помощи параметра будем передавать в одном случае значение 3000, а в другом - 1000. Создайте новую подпрограмму и в её свойствах добавьте параметр Время, а на диаграмме вместо числового значения таймера укажите имя этого параметра. Добавим для контроля блок "Напечатать текст" для вывода значения параметра на дисплее контроллера. В его свойстве Текст укажите имя переменной, а на панели свойств установите свойство Вычислять = истина.
Недостатком этой подпрограммы является то, что она не является универсальной. Значение скорости задано числовой константой - 100%. Для исправления этого необходимо вместо данной числовой константы также использовать переменную, значение которой можно будет изменять из главной программы. Аналогично нужно заменить числовые констранты на переменные в подпрограмме Поворот.
В идеале подпрограмма должна представлять собой чёрный ящик, устройство которого нам неизвестно, но известно, какие параметры ему нужно передать для выполнения заложенных в него действий и какие параметры он может вернуть (если он возвращает параметры). Это как с телевизором. Мы не знаем, что у него внутри, но при помощи пульта управления (интерфейса) можем управлять его работой.
После введения параметра Время главная программа примет следующий вид.
Теперь можно вынести в главную программу все переменные из подпрограмм... Подождите, а нужно ли это делать? Наша главная программа имеет большой недостаток - она не универсальна и состоит из определённой последовательности действий, которая подойдёт для рисования только прямоугольников. Если же нам нужно нарисовать треугольник, то придётся создать новую программу. Получится так, что затратим много времени и сил на оптимизацию программы, которая на практике имеет крайне ограниченное применение. Как сделать программу универсальной? Для этого вместо последовательности действий следует использовать последовательность данных. В этом случае структура программы останется неизменной. Строку данных можно составить, например, в таком виде:
дX;пУгол;дY;пУгол;дX;пУгол;дY;пУгол, где д - движение, п - поворот, X, Y и Угол - переменные, значения которых задаются при старте программы
Для работы с такой строкой требуется две подпрограммы, одна - для прямолинейного движения, другая - для поворота. Но эти два действия можно реализовать при помощи одной подпрограммы, если обратить внимание на то, что для выполнения каждого из этих действий требуется три параметра - скорость правого мотора, скорость левого мотора и время работы моторов. Создадим строку данных в виде последовательности троек этих значений:
100,100,3000;100,0,1050;100,100,1000;100,0,1050;100,100,3000;100,0,1050
Эта строка данных сначала разбивается на шаги по символу точки с запятой, а затем по разделителю запятой на параметры, передаваемые соответствующим блокам. После выполнения первого шага он удаляется из массива. Программа выполняется до тех пор, пока в строке есть данные.
Общий алгоритм понятен, но блок "Функция" поддерживает только простые выражения и создать с его помощью универсальную программу не получится (в отличие от текстового программирования).
Подпрограмма Движение.
Программа стала более универсальной, но, если нам не нужно рисовать линию, то придётся изменить подпрограмму, убрав из неё блок "Опустить маркер". Для создания ещё более универсальной программы необходимо в программу добавить интерпретатор данных (команд), который будет разбирать данные и направлять их соответствующим отдельным блокам. Каждая команда должна состоять из идентификатора действия и параметров, например:
Дв{m:{M3,M4},c:100}, где Дв - движение вперёд, m - моторы, с - скорость.
Получается JSON-подобный формат данных. Упрощённая программа такого интерпретатора показана ниже.
Благодаря замене последовательности блоков (функций) на последовательность данных мы выигрываем в универсальности программы, но проигрываем в её наглядности. Команды типа Дв{m:{M3,M4},c:100}понятны интерпретатору команд, но не пользователю. Значит, при составлении программы нужно использовать язык данных, понятных пользователю, а затем переводить его в данные, понятные устройству.
Если мы хотим получить универсальную программу, то придётся в диаграмму включить все блоки, которые мы хотим использовать. Это сделать можно, но затем перед нами встанет препятствие в виде ограниченной функциональности блоков, для преодоления которого придётся перейти к текстовому программированию.
До сих пор мы рассматривали тайм-модели, преимуществом которых является простота реализации, а недостатком - зависимость пройденного расстояния от величины заряда питающей батареи. При разряде батареи тележка будет проходить за то же время меньшее расстояние и поворачивать на меньший угол относительно тех, которые были рассчитаны при полном заряде батареи. В результате получается непредсказуемое поведение устройства. Мы можем методом проб и ошибок создать программу для рисования прямоугольника, но при использовании реальных устройств и батарей с разным зарядом придётся вносить в программу поправки. Для устранения зависимости пройденного расстояния от заряда батареи применяют энкодеры - датчики числа поворотов вала двигателя.