ROBOTC — КРОСС-РОБОТОТЕХНИЧЕСКИЙ ЯЗЫК ПРОГРАММИРОВАНИЯ

Статья опубликована в рамках: Международной научно-практической интернет-конференции «Актуальные проблемы методики обучения информатике и математике в современной школе» (Россия, г.Москва, МПГУ, 22 — 26 апреля 2019г.)

ROBOTC — КРОСС-РОБОТОТЕХНИЧЕСКИЙ ЯЗЫК ПРОГРАММИРОВАНИЯ

Векслер Виталий Абрамович,
кандидат педагогических наук, доцент
Саратовский национальный исследовательский государственный университет
имени Н. Г. Чернышевского

Аннотация: Робототехника стала универсальным педагогическим инструментов, она легко вошла в дополнительное образование, во внеурочную школьную деятельность, в преподавание предметов школьной программы. Одним из базовых языков программирования для робототехнических конструкций стал RobotC. В статье описываются особенности и преимущества данного языка программирования. Приводятся примеры решения практических задач.
Ключевые слова: робототехника, программирование, обучение, RobotC, Vex IQ

Сегодня одним из ведущих языков программирования устройств для образовательной робототехники и соревнований стал RobotC, кросс-робототехнический язык программирования, используемый в популярных образовательных системах. RobotC созданный на основе языка Си, поддерживает следующие робототехнические конструкции: VEX IQ, VEX CORTEX (EDR), VEX PIC, LEGO MINDSTORMS EV3, LEGO MINDSTORMS NXT, TETRIX, RCX (Legacy Support) Arduino UNO / MEGA 1280.

К преимуществам языка можем отнести: использует стандартный язык Cи-программирования; cовременный Windows GUI со стандартным визуальным интерфейсом; единственное решение с полностью интегрированным программным отладчиком, позволяющее пользователям шаг за шагом выполнять программы и анализировать все переменные; дополнительные инструменты отладки позволяют пользователю видеть в режиме реального времени состояния всех двигателей и датчиков; одно решение работает кроссплатформенно для разных робототехнических систем, поставляется с сотней примеров программ с обширной документацией, для того чтобы студенты, школьники и любители могли начать учиться программировать; усовершенствованный редактор исходного кода с интеллектуальным отступом; многофункциональный интерфейс со вкладками, позволяющий открывать несколько программ одновременно; бесплатные вебинары, видеоуроки, форумы сообщества, подробные файлы справки и учебная программа, предоставляются Академией робототехники Карнеги-Меллона; полученные навыки легко переходят в использование более профессиональных инструментов, используемых инженерами и программистами, язык программирования имеет тот же синтаксис и семантику, что и профессиональные языки.

Язык программирования может быть интегрирован так же с виртуальной средой роботов. Robot Virtual Worlds — это элитная среда моделирования, которая позволяет учащимся без роботов изучать программирование. Исследования показали, что обучение программированию в RVW более эффективно, чем обучение программированию с использованием физических роботов. RVW моделирует популярные роботы VEX, LEGO и TETRIX в реальном мире в трехмерных средах, позволяет использовать один и тот же язык, RobotC, для программирования виртуальных роботов. 

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

RobotC — это процедурный язык, в нем нет классов. Программист может использовать «struct» (структуры) в качестве альтернативы групповым переменным. Для работы с переменными и константами представлены типы данных Integers, Longs, Floats, Bytes, Bool, Chars and Strings (в графической версии языка для чисел определен только один тип – float). Определены не только директивы предпроцессора, условные конструкции, обширный набор циклических конструкций, стандартный набор  математических и нематематических функций, но и механизм создания собственных функций. Кроме функций основными блоками стали задания (потоки событий), главный поток   это “task main()”, при этом возможен запуск параллельных  потоков событий (task). Принята общесемантическая для языков Си группировка набора команд фигурными скобками. Описание алгоритма возможно в нескольких модулях, которые можно вызывать один через другого, принято создание файлов библиотек (.h) для удобной организации кода.

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

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

#pragma config(Sensor, port2,  tLed,           sensorVexIQ_LED)
#pragma config(Sensor, port3,  Color,          sensorVexIQ_Color12Color)
#pragma config(Sensor, port4,  Gyro,           sensorVexIQ_Gyro)
#pragma config(Sensor, port5,  leftBump,       sensorVexIQ_Touch)
#pragma config(Sensor, port7,  Sonar,          sensorVexIQ_Distance)
#pragma config(Sensor, port8,  rightBump,      sensorVexIQ_Touch)
#pragma config(Motor,  motor1,          leftMotor,     tmotorVexIQ, openLoop, driveLeft, encoder)
#pragma config(Motor,  motor6,          rightMotor,    tmotorVexIQ, openLoop, reversed, driveRight, encoder)
#pragma config(Motor,  motor11,         back,          tmotorVexIQ, PIDControl, encoder)
#pragma config(Motor,  motor12,         arm,           tmotorVexIQ, PIDControl, encoder)

Пример 1. Реализовать PID Control при движении робота назад на пять оборотов колеса.

Пропорционально-интегрально-производный контроллер (PID Control) — это механизм обратной связи контура управления, широко используемый в системах управления. Вычисляет значение ошибки как разницу между измеренным значением и желаемым значением. Может использоваться с любым датчиком, который обеспечивает диапазон значений.

Одно действительно полезное использование кодировщиков (энкодеры – измерители числа оборотов колеса) — это выпрямление линий. Эта техника позволяет роботу распрямляться при движении вперед. Идея заключается в том, что одно колесо будет регулировать свою скорость, если градусы энкодера другого колеса не синхронизированы с его градусами. Алгоритм имитирует работу пропорционально-интегрально-производный контроллера.

Решение:

while (nMotorEncoder(rightMotor)>-1800)
     { if (nMotorEncoder(rightMotor)<nMotorEncoder(leftMotor))
          { motor[rightMotor]=-50; motor[leftMotor]=-63;}
          if (nMotorEncoder(rightMotor)>nMotorEncoder(leftMotor))
          { motor[rightMotor]=-63; motor[leftMotor]=-50;}
          if (nMotorEncoder(rightMotor)==nMotorEncoder(leftMotor))
          { motor[rightMotor]=-63;motor[leftMotor]=-63;}}

Приведенный пример показывает, каким образом использовать кодировщики для написания функции, которая позволяет вашему роботу повернуть вспять по прямой линии за пять оборотов. Постоянным мониторингом вращения каждого колеса, программа может корректировать движение робота, пока оба колеса движутся с одинаковой скоростью. Состояние while остановит выполнение программы после 5 оборотов прошло. Происходит движение в обратную сторону, если, например, показания левого энкодера больше, значит колесо отстает и на мотор нужно подать большую мощность. Алгоритмы PID должны иметь «место для маневра» для правильной работы Установка слишком высокой скорости двигателя (> 100 мощностей) может не дать алгоритму достаточно места для регулировок.

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

void move(int speed, int correctSpeed, int degree)
{   nMotorEncoder[leftMotor] = 0; nMotorEncoder[rightMotor] = 0;
     while( abs( nMotorEncoder[leftMotor] ) < abs(degree) )
     { if( abs( nMotorEncoder[leftMotor] ) < abs( nMotorEncoder[rightMotor] ) )
     {  motor[leftMotor] = correctSpeed; motor[rightMotor] = speed;}
     else  if(abs(nMotorEncoder[leftMotor] ) > abs( nMotorEncoder[rightMotor] ) ) { motor[leftMotor] = speed; motor[rightMotor] = correctSpeed;}
     else { motor[leftMotor] = speed; motor[rightMotor] = speed;}}
          motor[leftMotor] = 0; motor[rightMotor] = 0;}
task main
{ move (60,80,500);move (-60,-80,-500);}

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

Решение.
int l=0;
task arms
{         int k = 0;
          while (k<l-2){ resetMotorEncoder(arm);
                   setMotorTarget(arm, 200, 50); waitUntilMotorStop(arm);
                   setMotorTarget(arm, 0, 50); waitUntilMotorStop(arm); k++;}}
task main
{ l = 10; int m=1; startTask(arms);
          repeat(l)
          {      nMotorEncoder[rightMotor] = 0; nMotorEncoder[leftMotor] = 0;
                   if (m>0)
                    { while(nMotorEncoder[rightMotor]<360)
                             { motor[rightMotor] = 10; motor[leftMotor] = -10;}}
                    else { while(nMotorEncoder[rightMotor]>-360)
                             {motor[rightMotor] = -10;motor[leftMotor] = 10;}
                    }
                    m=m*-1;
          }
          stopTask(arms);}

Пример 4. Сторожевой таймер. Робот исследует комнату, посредством датчика расстояний.

Присмотревшись к поведению робота повнимательнее, можно заметить, что не все предметы на пути попадают в его поле зрения. Например, если препятствие достаточно низкое, то ультразвуковой датчик его может не заметить, или покрытая тканевой обивкой поверхность вовсе поглощает ультразвуковые сигналы, т. е. не отражает их на чувствительный элемент. Не увидев препятствие (тапок или ножку стула), робот может застрять и будет бесконечно пытаться продолжать движение вперед. Однако, можно прийти к выводу, что в комнате движение не должно быть бесконечным. Скажем, от одной стенки до другой робот может доехать за 15 с. Если за это время он не увидит ни одного препятствия, можно с уверенностью утверждать, что произошло застревание и надо предпринять экстренные меры: отъехать назад и развернуться. Поможет в этом «сторожевой таймер». Такие устройства применяются в микроконтроллерах и защищают их от зависаний.

Сначала вы должны сбросить и запустить таймер с помощью команды ClearTimer (). Вот как настроена команда: ClearTimer (Timer_number). VEX имеет 4 встроенных таймера: T1, T2, T3 и T4. Если вы хотите сбросить и запустить таймер T1, вы должны набрать: ClearTimer (Т1). Затем вы можете получить значение таймера, используя time1 [T1], time10[T1] или time100 [T1] в зависимости от того, хотите ли вы, чтобы выходные данные имели значения 1, 10 или 100 миллисекунд.

Решение.

void move(int speed1, int speed2, int time)
{ motor[leftMotor]=speed1; motor[rightMotor]=speed2; sleep(time);}
task main()
{  clearTimer(T1);
   repeat (forever)
  {if (getDistanceValue(Sonar)>200&&time1[T1]<15000){ move(50,50,0);}
else { move(0,0,100); move(-50,-50,1000); move(50,-50,700);clearTimer(T1);}
displayTextLine(1,»Time %i»,time1[T1]);}}

Пример 5. «Не собьёшь меня с моего пути». Робот всегда держится от «хозяина» на определённом расстоянии (в 20 сантиметров).

Решение.

repeat (forever) { setMultipleMotors( (getDistanceValue(Sonar)-200)/2, leftMotor, rightMotor, noMotor, noMotor);}

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

resetGyro(Gyro); int degree;
repeat(forever)
{ degree = getGyroDegrees(Gyro);
             setMotorSpeed(leftMotor, 20 + degree); setMotorSpeed(rightMotor, 20 — degree);}

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

void iqCalibrateGyro() { startGyroCalibration(Gyro, gyroCalibrateSamples1024);
wait1Msec(100); displayTextLine(1, «Calibrating…»);
while (getGyroCalibrationFlag(Gyro)) {}; resetGyro(Gyro); }

Пример 7. Проблемное исследование. Поворот робота вокруг своей оси на 90 градусов. Не используйте гироскоп и эмпирический подбор данных. Результаты вычислений выведите на экран.

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

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

  1. Определение пути колеса робота за один оборот. Диаметр колеса 6.37 см. Для вычисления пути необходимо диаметр умножить на число Пи.
  2. Определение пути, которое необходимо проделать колесу для поворота на 90 градусов. Робот будет делать разворот вокруг своего центра. Это может быть центр расположения своих колес, вращающихся в разные стороны. В этом случае необходимо измерить расстояние между колесами (данные могут разниться в зависимости от конструкции). Так же возможно, левый и правый моторы находится в центре конструкции, посредством зубчатой передачи они управляют каждый своей парой колес, расположенных по бокам. В этом случае нужно определить диаметр окружности по которой будет проходить вращение робота. Возможно измерение расстояния между первым левым и вторым правым колесом. Поэтому данный путь строго определяется в зависимости от конструкции. Предположим, он равен 23 см. Умножив данное число на Пи, мы узнаем путь для полного оборота, на 360 градусов. Поделив на четыре, мы вычислим какой путь необходимо проехать роботу, для того чтобы развернуться на 90 градусов.
  3. Разделим путь, который необходимо проехать на путь колеса мы вычисли число оборотов колеса. Умножив данное число на 360 мы вычислим данные для разворота в градусах.

Решение.

float cir = PI * 6.37; float turnover = PI * 23;
float t90 = turnover/4; float target = (t90/cir)*360;
resetMotorEncoder(leftMotor); resetMotorEncoder(rightMotor);
displayTextLine(1, «%d», cir); displayTextLine(2, «%d», turnover);
displayTextLine(3, «%d», t90); displayTextLine(4, «%d», target);
setMotorTarget(leftMotor, target, 50); setMotorTarget(rightMotor, -1*target, 50);
waitUntilMotorStop(leftMotor); waitUntilMotorStop(rightMotor);

Пример 8. Робот-часы. На экране робота отобразите секундную стрелку. В такт секундной стрелке мотор передвигает прикрепленную к ему балку.

Решение.

float xPosTo,yPosTo, a=0; resetMotorEncoder(leftMotor);
repeat(forever){
xPosTo = 23*cos(90-a*6)+63; yPosTo = 23*sin(360-(90+a*6))+24;
drawLine(63, 24, xPosTo, yPosTo);     a++;
moveMotorTarget(leftMotor,6,50);wait1Msec(1000);
eraseDisplay(); waitUntilMotorStop(leftMotor);}

В графическом режиме экран отображает 128 на 48 точек. Начало отсчёта левый нижний угол. Секундная стрелка рисуется из центра экрана (63,24) линией для которой задаются координаты начальной и конечной точки. Формулы для расчетов расположения конечной точки представлены в коде.”a” – количество выполнений шагов цикла, умноженное на шесть, поскольку за каждый шаг цикла секундная стрелка должна повернуться на шесть градусов.

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

ЛИТЕРАТУРА:

  1. Introduction of Programming Vex IQ // URL: http://curriculum.cs2n.org/vexiq (дата обращения: 10.01.2019).
  2. Robomatter is a Global Leader in STEM Education // URL: http://www.robomatter.com/stem-solutions/for-students/ (дата обращения: 15.02.2019).
  3. RobotC a C Programming Language for Robotics // URL: http://www.robotc.net/ (дата обращения: 02.04.2019).
  4. ROBOTC for VEX Robotics 4.X — User’s Manual // URL: http://help.robotc.net/WebHelpVEX/index.htm#Resources/topics/Welcome.htm (дата обращения: 14.03.2019).
  5. Овсяницкая, Л.Ю. Курс программирования робота EV3 в среде Lego Mindstorms EV3/ Л.Ю. Овсяницкая, Д.Н. Овсяницкий, А.Д. Овсяницкий. М.: Издательство «Перо», 2016.
Подписаться
Уведомить о
guest
2 комментариев
oldest
newest
Inline Feedbacks
View all comments
Дмитрий Павлов
Дмитрий Павлов
4 лет назад

Добрый день!
Спасибо за интересный материал.
Вопрос: сегодня для конструкторов EV3 стал доступен Python, что вызвало много положительных отзывов у преподавателей. Будет доступен Python и для платформы Spyke Prime. Используется питон и с целым рядом решений на базе Arduino. В этой связи вопрос, какой путь — RobotC или Python вы считаете перспективнее для массового обучения и для подготовки «спортсменов» ?

Виталий
Виталий
Reply to  Дмитрий Павлов
4 лет назад

Сегодня мы уже обладаем возможностью выбора средств текстового программирования робототехнических устройств (Small Basic Ev3, Python, RobotC и др.). Сложно и наверное не нужно ограничиваться одной средой программирования, у каждой из них есть свои преимущества. Среда RobotC обладает большим выбором специализированных команд, синтаксически восполнена в стандартах языков Си, что готовит школьника уже к пониманию принципов работы с «профессиональными» языками.