Управление без обратной связи



В задачах управления обычно существуют два объекта: управляющий и управляемый. В простейшем варианте от управляющего объекта поступает команда и управляемый выполняет ее, ничего не сообщая о результате или об изменившихся условиях работы. В этом суть прямой связи (рис. 8.1).

 

Рис. 8.1. Прямая связь в управлении.

С точки зрения мобильного робота управляющий объект — это его контроллер с запущенной программой, объект управления — это его колеса и корпус (шасси). Управляющие команды контроллер подает на моторы, при прямой связи руководствуясь показаниями своих внутренних часов — таймера.

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

Движение в течение заданного времени вперед и назад

Для движения вперед используются команды управления моторами. Эти команды просто включают моторы. Особенность NXT заключается в том, что после окончания выполнения программы сохраняются все установки в поведении робота, но на моторы перестает подаваться напряжение. Таким образом, просходит пуск и сразу плавное торможение (рис. 8.2).

 

Рис. 8.2. Включение моторов.

Task main()

{ motor[motorB] = 100; // моторы вперед с motor[motorC] = 100; // максимальной мощностью

}

Обе команды выполняются практически мгновенно. Если сразу следом за ними выключить моторы, то тележка просто дернется и останется стоять на месте (рис. 8.3):

 

Рис. 8.3. Остановка при попытке начать движение.

Task main()

{ motor[motorB] = 100; motor[motorC] = 100; motor[motorB] = 0; // стоп мотор motor[motorC] = 0;

}

Таким образом, для осуществления движения требуется некоторая задержка перед выключением моторов. Команды ожидания не производят никаких конкретных действий, зато дают возможность моторам выполнить свою часть работы (рис. 8.4):

 

Рис. 8.4. Правильный порядок управления моторами.

Task main()

{ motor[motorB] = 100; motor[motorC] = 100; wait1Msec(1000); // Ждать 1000 мс motor[motorB] = 0; motor[motorC] = 0; }

 

Движение вперед или назад, очевидно, определяется направлением вращения моторов (рис. 8.5). Для смены направления не требуется остановка:

 

Рис. 8.5. Проехать секунду вперед, секунду назад и остановиться.

Task main()

{ motor[motorB] = 100; motor[motorC] = 100; wait1Msec(1000);

motor[motorB] = -100; // «Полный назад» motor[motorC] = -100; wait1Msec(1000); motor[motorB] = 0; motor[motorC] = 0;

}

 

В момент смены направления на высокой скорости возможен занос. Плавное торможение возможно. Для этого перед подачей команды «назад» с моторов снимается напряжение и робот некоторое время едет по инерции (рис. 8.6). 

 

Рис. 8.6. Перед сменой направления полсекунды ехать по инерции.

Более краткий промежуток, чем 1 секунда, задается с помощью команды «N/100» и модификатора. В Robolab 2.9.4 можно задавать время в миллисекундах командой «N/1000»:

Task main()

{ motor[motorB] = 100; motor[motorC] = 100; wait1Msec(1000);

// Включить плавающий режим управления моторами bFloatDuringInactiveMotorPWM = true; motor[motorB] = 0; motor[motorC] = 0; wait1Msec(500); motor[motorB] = -100; motor[motorC] = -100; wait1Msec(1000);

// Включить режим «торможения» bFloatDuringInactiveMotorPWM = false; motor[motorB] = 0; motor[motorC] = 0;

}

 

В Robolab обычными командами моторы включаются в плавающем режиме, а в RobotC по умолчанию используется режим «торможения», который позволяет достичь более точного управления. Но и в Robolab существуют «продвинутые» команды управления моторами в режиме торможения да еще с диапазоном мощностей –100...100. 

Повороты

Для выполнения поворота на месте достаточно включить моторы в разные стороны. Тогда робот будет вращаться приблизительно вокруг центра оси ведущих колес со смещением в сторону центра тяжести. Для более точного поворота надо подбирать время в сотых долях секунды (рис. 8.7). Однако при изменении заряда батареек придется вводить новые параметры поворота:

 

 

Рис. 8.7. Поворот на месте.

Task main()

{ motor[motorB] = 100; // Моторы в разные motor[motorC] = -100; // стороны wait1Msec(300); motor[motorB] = 0; motor[motorC] = 0;

}

 

Существует другой тип поворотов. Если один из моторов остановить, а другой включить, то вращение будет происходить вокруг стоящего мотора. Поворот получится более плавным (рис. 8.8):

 

Рис. 8.8. Плавный поворот.

Task main()

{ motor[motorB] = 100; motor[motorC] = 0;

wait1Msec(1000); // вращается только мотор B motor[motorB] = 0;

}

Движение по квадрату

Используя полученные знания управления моторами, можно запрограммировать движение по квадрату или другому многоугольнику с помощью цикла или безусловного перехода (рис. 8.9):

 

Рис. 8.9. Движение по многоугольнику с плавными поворотами.

Task main()

{ while (true){ motor[motorB] = 100; motor[motorC] = 100; wait1Msec(1000); motor[motorC] = 0; wait1Msec(1000); motor[motorB] = 0;

}

}

 

Уточнив длительность поворотов и число повторений, научим тележку объезжать квадрат по периметру 1 раз (рис. 8.10). Для точности поворотов снизим мощность моторов примерно вдвое. Задержки придется подобрать самостоятельно:

 

Рис. 8.10. Для поворота на 90 градусов длительность придется подобрать самостоятельно.

Task main()

{ for(int i=0;i<4;i++){ // Цикл выполняется 4 раза motor[motorB] = 50; motor[motorC] = 50; wait1Msec(1000); motor[motorC] = -50; wait1Msec(400); motor[motorB] = 0;

}

}

 

Управление с обратной связью

Обратная связь

Появление обратной связи в системе означает то, что управляющий объект начинает получать информацию об объекте управления       

(рис. 8.11).

 

Рис. 8.11. Управление с обратной связью.

Обратная связь осуществляется с помощью датчиков, прикрепленных, например, на корпус робота. Данные поступают в контроллер, который является управляющим объектом.

Точные перемещения

Чтобы поворот не зависел от заряда батареек, можно воспользоваться встроенным в двигатели датчиком оборотов, «энкодером», который позволяет делать измерения с точностью до 1 градуса. Для более эффективного управления задействуем в Robolab «продвинутые» команды, считая что при повороте тележки на 90 градусов левое колесо поворачивается на 250 градусов вокруг своей оси (рис. 8.12):

 

Рис. 8.12. Точный поворот на месте.

task main() {

nMotorEncoder[motorB]=0; // Инициализация энкодера motor[motorB] = 100; motor[motorC] = -100;

// Пустой цикл ожидания показаний энкодера while(nMotorEncoder[motorB]<250); motor[motorB] = 0; motor[motorC] = 0;

}


Движение вдоль линии

Один датчик

Для первого опыта подойдут робот, созданный для задания «Танец в круге», и то же поле — черная окружность на белом фоне. Если уже все готово для изготовления полноценного поля для траектории, можно обратиться к разделу «Поле» в конце этой части. Единственная поправка: датчик освещенности следует выдвинуть немного вперед, чтобы он образовывал вместе с ведущими колесами равносторонний или хотя бы равнобедренный прямоугольный треугольник (рис. 8.32). 

 

Рис. 8.32. Варианты расположения датчика освещенности относительно ведущих колес.

Задача такова: двигаться вдоль окружности по границе черного и белого. Решается элементарно применением релейного (или пропорционального) регулятора, который рассмотрен в главе «Алгоритмы управления». Только алгоритм будет записан не в виде ветвления, а с использованием блоков «Жди темнее» и «Жди светлее». Базовая конструкиця приведена на рис. 8.33—8.35, а простейшая программа для начинающих — на рис. 8.36. Без модификаторов предполагается, что датчик освещенности подключен к первому порту, а на моторы подается максимальная мощность.

 

Рис. 8.33. Крепление датчика освещенности к трехколесной тележке.

 

Рис. 8.34. Ось для регулировки высоты датчика может быть любой длины.

 

Рис. 8.35. Высота датчика над поверхностью поля — от 5 до 10 мм.

 

Рис. 8.36. Алгоритм движения по линии с одним датчиком освещенности.

Перед стартом ставим робота на линию так, чтобы датчик был чуть слева. По алгоритму робот плавно поворачивает направо, пока освещенность не понизится на 5 пунктов (по умолчанию). Затем поворачивает налево, пока освещенность не повысится на 5 пунктов. Движение получается похожим на «змейку».

Возможные проблемы

Перечислим трудности, которые могут возникнуть:

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

— робот проскакивает линию, не успевая среагировать. Следует понизить мощность моторов;

— робот реагирует на мелкие помехи на белом, не доезжая до черного. Надо увеличить порог чувствительности датчика (например, не на 5, а на 8 пунктов). Вообще говоря, это число можно рассчитать. Для этого следует снять показания датчика на белом, затем на черном, вычесть одно из другого и поделить пополам. Например, (56 – 40) / 2 = 8.

Усовершенствованная программа показана на рис. 8.37.

 

Рис. 8.37. Алгоритм движения по линии с одним датчиком освещенности: понижена скорость, увеличена разность между черным и белым.

Более устойчиво алгоритм работает, если использовать моторы с управлением скоростью –100...100. В этом случае есть возможность отрегулировать плавность поворота в соответствии с кривизной линии

(рис. 8.38).

 

Рис. 8.38. Алгоритм движения по линии с одним датчиком освещенности: улучшено управление моторами.

В этом алгоритме притормаживающие моторы на повороте не останавливаются полностью, а лишь понижают скорость до 20 пунктов. Это делает поворот более плавным, но может привести и к потере линии на резком повороте. Поэтому числа 80 и 20 поставлены условно, их стоит подобрать самостоятельно. 

П-регулятор

И, наконец, для сравнения надо посмотреть, как будет работать П-регулятор для одного датчика. Этот пример уже приводился в главе 7. Но его стоит повторить с некоторыми дополнениями (рис. 8.39).

 

Рис. 8.39. Алгоритм движения по линии с одним датчиком освещенности на пропорциональном регуляторе.

Число 48, использованное в формуле управления u, — это среднее арифметическое показаний датчика освещенности на черном и на белом, например (40 + 56) / 2 = 48. Однако показания датчиков часто меняются по разным причинам: другая поверхность, изменение общей освещенности в помещении, небольшая модификация конструкции и т.п. Поэтому имеет смысл научить робота самостоятельно вычислять среднее арифметическое, т. е. значение границы белого и черного.

Есть несколько способов выполнить калибровку датчика. В простейшем случае вместо вычисления среднего арифметического просто понижается значение белого. Смысл способа в том, что робот снимает показания на белом, вычитает из него некоторое предполагаемое значение и полученное число считает границей белого и черного. Например, 56 – 7 = 49 можно считать значением серого (рис. 8.40).

 

Рис. 8.40. Алгоритм движения по линии с одним датчиком освещенности на пропорциональном регуляторе с предварительной калибровкой (определением значения серого).

task main() { int u, v=50; float k=2; int red=SensorValue[S1]-7; while(true) {

u=k*(SensorValue[s1]-red); motor[motorB]=v+u; motor[motorC]=v-u; wait1Msec(1);

}

}

 

По умолчанию значение освещенности с датчика на порту 1 считывается в красный контейнер, после чего оно уменьшается на число 7, и в формуле управления u используется уже измененное значение красного контейнера red. Если указывать все модификаторы, программа будет выглядеть так, как показано на рис. 8.41.

 

Рис. 8.41. Алгоритм движения по линии с одним датчиком освещенности на пропорциональном регуляторе — с модификаторами.

Надо иметь ввиду, что такой способ калибровки не учитывает все возможные варианты, а только экономит время на программирование и отладку. Если же времени достаточно, есть другой способ, при котором действительно производится расчет среднего арифметического показаний датчика освещенности на черном и на белом (рис. 8.42). 

 

Рис. 8.42. Алгоритм движения по линии с одним датчиком освещенности на пропорциональном регуляторе с расчетом значения серого.

task main() { int u, v=50; float k=2; int c4=SensorValue[S1]; PlaySound(soundBeepBeep); wait1Msec(2000); int c5=SensorValue[S1]; PlaySound(soundBeepBeep); int grey=(c4+c5)/2; while(true) {

u=k*(SensorValue[S1]-grey); motor[motorB]=v+u; motor[motorC]=v-u; wait1Msec(1);

}

}

Предложенный алгоритм обладает некоторым неудобством: при запуске потребуется быть внимательным и не пропустить звукового сигнала, после которого робота надо переместить так, чтобы датчик освещенности оказался над белым полем. Понятно, что в начале следует поместить робота точно над черной линией. В контейнере с номером 4 (обозначается c4) будет сохранено значение черного, в контейнере с номером 5 (c5) — значение белого. В переменную grey помещается значение серого, которое используется в регуляторе. Сразу после второго звукового сигнала робот начнет движение.

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

Рассмотрим простейший пример с дополнительным датчиком касания, подсоединенным ко второму порту. Запустить программу имеет смысл, аккуратно установив тележку датчиком освещенности над черной линией (рис. 8.43).

 

Рис. 8.43. Калибровка датчика освещенности с ожиданием касания.

task main() { int u, v=50; float k=2; int c4=SensorValue[S1]; PlaySound(soundBeepBeep);

while(SensorValue[S2]==0); // Жди, пока не нажато wait1Msec(100);        // Защита от залипаний while(SensorValue[S2]==1); // Жди, пока нажато wait1Msec(100); int c5=SensorValue[S1]; PlaySound(soundBeepBeep); int grey=(c4+c5)/2; while(SensorValue[S2]==0); wait1Msec(100); while(SensorValue[S2]==1); while(true)

{

u=k*(SensorValue[S1]-grey); motor[motorB]=v+u; motor[motorC]=v-u; wait1Msec(1);

}

}

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

Аналогичный опыт можно провести, используя датчик расстояния вместо датчика нажатия. Преимущество здесь в том, что старт робота будет осуществляться бесконтактно. Это поможет стартовать в точно выбранном положении. Только надо быть внимательным и несвоевременно не провести рукой возле датчика расстояния (рис. 8.44).

 

Рис. 8.44. Калибровка датчика освещенности с ожиданием объекта (руки).

В примере использованы именованные контейнеры (black и white), которые по сути являются переменными, как в обычном языке программирования. Обратите внимание, что звуковой сигнал между двумя ожиданиями изменения расстояния способствует тому, чтобы робот не среагировал дважды подряд на одно приближение руки.

Полученный опыт стоит применить для окончательного выталкивания кеглей из круга, если таковые еще остались на границе. Доработайте самостоятельно алгоритм, приведенный на рис. 8.31.

Поле для следования по линии

Более интересную траекторию, чем окружность, стоит сделать самостоятельно на светлой поверхности достаточно большой площади с помощью той же черной изоленты. В качестве поверхности подойдет лист фанеры или оргалита, обратная сторона листа линолеума, белая клеенка и многое другое. Размеры поля желательно делать не меньше, чем 100 · 150 см. При разметке траектории следует учесть отступ от линии до края поля не менее 20 см, чтобы колеса робота не съезжали с трассы во время движения. 

Имея определенный навык, можно наклеить изоленту так, что получится замкнутая кривая. Если не получается с одним куском изоленты, смело пользуйтесь ножницами, чтобы изгибы с малым радиусом кривизны составить из нескольких кусочков. Для начала не стоит рисовать слишком резких поворотов. Линию можно составить как из одной, так и из двух и даже трех полос изоленты. Тогда роботу будет легче ориентироваться и не съехать с курса. Помимо изоленты может быть использована матовая черная самоклеющаяся пленка. И, наконец, оптимальное решение печать графического файла на баннерной ткани. Стоимость такой печати обычно не превосходит 400 руб. за 1 м2. Небольшое поле для движения по линии приведено на рис. 8.45.

 

Рис. 8.45. Пример самодельного поля для движения по линии.

На рис. 8.46 приведен пример траектории для состязаний по правилам Открытого турнира на кубок Политехнического музея (г. Москва). Ширина линии составляет 5 см, а минимальный радиус кривизны 30 см. Актуальные регламенты состязаний размещены на сайте http://railab.ru. Регламент состязаний «Гонки по линии» и само поле в векторном формате можно найти на сайте http://myrobot.ru[11].

 

Рис. 8.46. Поле для состязаний «Гонки по линии».


Путешествие по комнате

Маленький исследователь

Естественно, нормальная среда обитания для робота, построенного из домашнего конструктора, — это комната с мебелью. И для начала

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

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

препятствие или, наоборот,   что-то серьезное не будет за- Рис. 8.78. Маленький исследователь из мечено.     набора 9797 с ультразвуковым датчиком.

Более простой вариант конструкции (рис. 8.79) можно построить на основе тележки, которая рассматривалась в главе 3. Программа очень похожа алгоритм на путешествия в круге. Меняется лишь датчик (рис. 8.80).

 

   
 

Рис. 8.79. Датчик, прикрепленный к корпусу тележки, должен смотреть строго горизонтально.

 250

 

Рис. 8.80. Алгоритм путешествия по комнате.

Можно сделать несколько короче, если заменить отъезд назад с поворотом на месте одним действием: плавным поворотом задним ходом

(рис. 8.81). 

 

Рис. 8.81. Алгоритм путешествия по комнате с поворотом задним ходом.

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

Защита от застреваний

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

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

                                                                                                           251

 

Рис. 8.82. Если на сторожевом таймере «натикает» 10 с, включается защита от застреваний.

Можно заметить в нашей программе повторяющиеся группы блоков. Их стоит объединить в подпрограмму, которая будет осуществлять отъезд назад с разворотом (рис. 8.83). Таким образом, подпрограмма отъезда будет вызываться в двух случаях: 1) при наличии препятствия, 2) при срабатывании сторожевого таймера.

 

Рис. 8.83. Защита от застреваний с использованием подпрограмм.

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

252

Объезд предметов

Новая конструкция

может увидеть краем глаза. Учитывая это свойство, разместим датчик расстояния не перпендикулярно курсу движения, а под острым углом (рис. Рис. 8.89. Датчик расстояния устанавливается под острым углом к направлению движения.

Первые шаги к объезду предметов сделаны в главе «Алгоритмы управления». Движение вдоль стены с небольшими отклонениями возможно с помощью ПД-регулятора. Однако описанный робот сможет объезжать стены только при малых отклонениях от прямой линии. При резких изгибах робот может потерять контакт со стеной и начать крутиться на месте. Эту проблему можно отчасти разрешить конструктивно.

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

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

(рис. 8.89). Это напоминает периферийное зрение человека: кое-что он

8.90 8.91). Так можно «убить сразу двух зайцев». Во-первых, робот будет видеть препятствия спереди; во-вторых, более стабильно будет придерживаться курса вдоль стены, постоянно находясь на грани видимости. Таким образом без добавления новых устройств можно более эффективно использовать возможности дальномера.

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

256

 
 
 

Рис. 8.90. Крепление размещается на левой стороне. Как и в первой конструкции, датчик располагается вертикально.

 

Рис. 8.91. Увеличенное за счет корпуса робота расстояние до стены способствует расширению области обзора.

Очевидно, что изменение конструкции влечет изменение коэффициентов регулятора k1 и k2. Обычно подбор начинается с пропорционального коэффициента при нулевом дифференциальном. Когда достигнута некоторая стабильность на небольших отклонениях, добавляется дифференциальная составляющая.

Поворот за угол

Следующим шагом необходимо ограничить реакцию робота на «бесконечность». Как известно, когда в поле видимости нет объекта, показания датчика расстояния NXT равны 250 или 255 см. Если это число попадает на пропорциональный регулятор, робот начинает кру-

257

титься на месте. А в ситуации, когда роботу следует завернуть за угол, именно это и произойдет. 

Для объезда предметов потребуется ввести контроль показаний датчика расстояния: при резком изменении робот должен делать вывод о возможном повороте, который надо будет производить с другими коэффициентами или просто с постоянным значением управляющего воздействия.

Рассмотрим пример поворота направо «за угол» (рис. 8.92). Если робот движется на расстоянии L от стены, то и поворот, очевидно, он будет выполнять по окружности с радиусом L

 

Рис. 8.92. Выполнение поворота при потере контакта со стенкой.

Нетрудно рассчитать, каким должно быть отношение скоростей колес, чтобы радиус поворота оказался равен L. Для этого достаточно измерить расстояние между передними колесами. Пусть в нашем роботе оно будет равно k = 16 см, а его половина d = 16 / 2 = 8 см. Тогда левое и правое колеса движутся по окружностям радиусов, соответственно, R1 = L + d и R2 = L d. Пройденные ими пути за единицу времени должны быть пропорциональны радиусам, следовательно, скорости точек крепления колес v1 и v2 связаны следующим отношением:

v1 = R1 . v2 R2

Выражая скорости перемещения колес через базовую скорость v и неизвестную x, а радиусы через L, получаем следующее: v + x L+d

= , vL+xL-vd-xd =vL+vd-xL-xd , 2xL=2vd , v - x L-d x = vd , v1 = v + vd = v(1+ d ), v2 = v - vd = v(1- d).

                L             L         L               L         L

258

Линейная скорость v пропорциональнаугловой скорости колеса ω, которая в свою очередь пропорциональна мощности, подаваемой на моторы (в режиме торможения). Мы привели закон управления к стандартному виду, что позволяет задать управляющее воздействие на время поворота за угол. Таким образом, получаем расчет для управления моторами нашего робота.

 u=v*8/L; motor[motorB]=v+u; motor[motorC]=v-u;

 

Когда расстояние до стены становится больше 2L (используем такой порог видимости), т. е. открывается поворот за угол, управляющее воздействие начинает вычисляться по приведенным формулам

(рис. 8.93). 

 

Рис. 8.93. Объезд предметов на заданном расстоянии по правилу правой руки.

task main() {

float u, k1=2, k2=10; int v=50, d=8, Sold, L, Snew;

Sold=L=SensorValue[S1]; // Запомнили начальное состояние while(true) {

Snew=SensorValue[S1]; // Получили показания датчика if (Snew>L*2) {  u=v*d/L;  Sold=L*2; } else {

u = k1*(Snew-L) + k2*(Snew-Sold);

Sold=Snew;

} motor[motorB]=v+u; motor[motorC]=v-u; wait1Msec(1); }

}

259


task main() {

float u, k1=2, k2=10, a=0.2, Snew;   int v=50, d=8, Sold, L; Snew=Sold=L=SensorValue[S1]; while(true)

{

Snew=(1-a)*Snew+a*SensorValue[S1]; if (Snew>L*2) {  u=v*d/L;  Sold=L*2; } else {

u = k1*(Snew-L) + k2*(Snew-Sold);

Sold=Snew;

}   motor[motorB]=v+u; motor[motorC]=v-u; wait1Msec(1);

}

}

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

Роботы-барабанщики

Предыстория

Идея построить робота-барабанщика из Lego появилась в 2009 году на кружке робототехники физико-математического лицея № 239 г. Санкт-Петербурга. Ребятам она понравилась и вскоре было создано несколько моделей, которые запоминали и воспроизводили ритм, импровизировали, управлялись удаленно, играли заранее записанные мелодии и даже аккомпанировали компьютеру в проигрывании midiфайлов. Через 10 месяцев робот-барабанщик получил бронзовую медаль на Всемирной олимпиаде роботов в Южной Корее (фотография награждения команды лицея «Старый барабанщик» на задней стороне обложки). Впоследствии он много путешествовал по России от Москвы до Сибири, выступая на фестивалях, выставках и форумах.

  
 

Рис. 8.96. Первые версии робота-барабанщика с игрушечным и пионерским барабанами.

Первые версии робота были сделаны целиком из деталей Lego и программировались через Robolab. Основой служил игрушечный барабан (рис. 8.96). Андроид-барабанщик был построен из пластиковых водопроводных труб (рис. 8.97), перед ним стояла целая барабанная установка, а программировался он на языках RobotC и Java.

 

Рис. 8.97. Андроид-барабанщик.

Алгоритмы управления роботами-барабанщиками основаны на П-регуляторах, что дает возможность повысить точность позиционирования барабанных палочек. Это описано далее.

Калибровка и удар

Конструкция для барабанщика с одной палочкой изображена на рис. 7.1. Ничего особенного, разве что балку стоит сделать подлиннее (рис. 8.98). Барабанить он будет по столу. Однако прежде чем нанести удар, надо определиться, где именно находится поверхность «барабана». Для этого необходимо выполнить калибровку. Простейший ее вариант заключается в следующем. 

 

Рис. 8.98. Движения «барабанной палочки».

Робот опускает «палочку» на низкой скорости в течение достаточно большого промежутка времени, около 2 с (рис. 8.99). Поскольку скорость и мощность моторов взаимосвязаны, то, упершись в поверхность, палочка не причинит роботу никакого вреда и просто остановится. Полученное положение мотора запоминается как нулевое. Калибровка произведена. 

 

Рис. 8.99. Простейшая импровизация одной палочкой.

Удар будет представлять из себя поднятие палочки в абсолютное положение под углом 15 градусов (замах) и опускание в нулевое положение (удар). Однако, учитывая люфт моторов Lego, а также инерцию их движения, следует прекращать опускание не в нулевом положении, а значительно раньше, например при достижении угла 10 градусов. Это позволит сократить длительность соприкосновения с поверхностью и воспользоваться энергией отскока, что значительно ускорит движение палочек. Робот получит возможность воспроизводить довольно быстрый ритм. 

Управление с помощью датчика

Заменив ожидание таймера ожиданием нажатия датчика касания, можно получить управляемую игрушку (рис. 8.100). Человек будет нажимать на кнопку, а робот послушно выполнять удар.

 

Рис. 8.100. Управление палочкой с помощью датчика касания.

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

 

Рис. 8.101. Датчики можно прикрепить на робота или вынести отдельно.

Чтобы настроить управление двумя палочками, потребуется поместить калибровку второго мотора и удар в параллельный процесс. Вытянем алгоритм в цепочку и сдублируем его. Единственное незначительное изменение — это изменение типа и мощности управления моторами при калибровке. Поскольку уже два двигателя будут прижимать палочки к полу, то во избежание поднятия всего робота стоит понизить их мощность до 5—10 %.

Дублируя часть алгоритма, постарайтесь внимательно заменить все команды мотору A на команды мотору B (рис. 8.102). 

 

Рис. 8.102. Алгоритм управления палочками с помощью двух датчиков.

 
 
 

Рис. 8.103. Конструкции для управления роботом-барабанщиком: слева — на датчиках касания, справа — на гироскопических датчиках.

Ребята из команды «Старый барабанщик» сконструировали специальную перчатку с закрепленным на ней двумя датчиками касания (рис. 8.103, слева). Быть может, и читатель придумает нечто подобное. А при наличии пары гироскопических датчиков не составит труда настроить управление роботом с помощью настоящих барабанных  

(рис. 8.103, справа).

Создаем свой ритм

Вернемся к одномоторному барабанщику. Преобразуем удар в процедуру, которая вызывается через определенные промежутки времени. Задавая длительность этих промежутков, создадим ритмический рисунок (рис. 8.104). Лучше будет использовать длительности, кратные 0.2 секунды: 20 сотых, 40 сотых, 60 сотых и т. д. Если задать чересчур малую длительность, то либо робот не успеет произвести удар, либо удар будет слишком тихим. Эту особенность можно использовать для регулирования громкости.

Очевидно, что для повышения точности процесса надо поднимать палочку не до удара, а сразу после него.

 

Рис. 8.104. Создаем собственный ритимический рисунок.

Удар обладает некоторой длительностью, и ее тоже надо учитывать при определении пауз. Удобнее всего это сделать с помощью системного таймера. Команда «Жди таймер» будет предшествовать каждому удару, а очередное ожидаемое значение задаваться непосредственно перед ней (рис. 8.105). 

 

Рис. 8.105. Ритмический рисунок соответствует реальному времени.

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


Лабиринт

Виртуальные исполнители

Перед решением задачи прохождения лабиринта стоит познакомиться со средой «Исполнители»[12], созданной проф. К. Ю. Поляковым из Санкт-Петербургского Государственного морского технического университета. Исполнитель робот, реализованный в ней, очень подходит для начального освоения алгоритмики. Среда полностью русифицирована и содержит Си-ориентированный язык программирования с русской и английской лексикой. Задача поиска выхода из лабиринта решается в этой среде различными способами. Наиболее интересный набор задач[13] для робота разработан учителем информатики Д. М. Ушаковым из физико-математического лицея № 239 Центральнго района Санкт-Петербурга. Среда «Исполнители» особенно актуальна для желающих в будущем освоить язык RobotC.

Также можно порекомендовать систему программирования «КуМир»[14], в которой есть исполнитель робот, способный найти выход из лабиринта. В системе «КуМир» используется школьный алгоритмический язык с русской лексикой, ориентированный на язык Паскаль. Система «КуМир» разработана в Научно-исследовательском институте системных исследований (НИИСИ) РАН по заказу Российской Академии Наук.

Обе среды распространяются бесплатно.

Полигон

На первый взгляд, построение поля лабиринта может вызвать затруднения, однако вложенные усилия вполне окупаются результатом. Поиск выхода из лабиринта является классической задачей, которую решают не только робототехники, но и программисты. Одно из самых ярких соревнований — состязания роботов Micromouse — проводится среди студентов. В нем участвуют разные роботы, совсем не из Lego, оборудованные большим числом датчиков и сложными алгоритмами. И размеры лабиринта составляют 16 · 16 квадратных ячеек.

Наш лабиринт может быть поменьше, например, размером 5 · 5 ячеек, а размер ячейки специально подобран для Lego-роботов: около 30 · 30 см. С учетом толщины стенок, как правило, сторона квадрата ячейки колеблется в диапазоне от 28 до 30 см. Число ячеек и структура лабиринта могут быть любыми. Распространена столешница 150 · 150 см, что и соответствует размеру 5 · 5 ячеек. Обеспечим ее съемными внутренними стенками. Стенки лабиринта желательно сделать повыше, до 16 см, однако подойдут и стандартные, высотой 10 см (рис. 8.110). 

Итак, особенность лабиринта в том, что его можно в любой момент изменить, сделав задачу более интересной.

 

Рис. 8.110. Примеры лабиринтов.

Робот для лабиринта

Каковы характеристики робота? Поскольку приходится иметь дело с замкнутым пространством, робот не должен быть быстрым. В «прямоугольном мире» поворот на 90 градусов должен осуществляться с высокой точностью, как и проезд одной ячейки вперед. Соприкосновение со стеной для робота нежелательно, но не должно вызывать немедленного выхода его из строя. Кроме того, стоит предусмотреть способность двигаться вдоль стены при непрерывном касании. Датчики ультразвука, которые помогут определять расстояние до стен, следует располагать не на самом краю корпуса, чтобы соблюсти минимальное расстояние видимости ультразвукового датчика 5 см.

Исходя из перечисленных условий, оптимальным будет выбор конструкции компактного гусеничного робота. Построить его можно на основе одного конструктора 8547 или конструктора 9797 с добавлением двух гусениц из ресурсного набора 9695. Модель подобного робота предлагается в наборе 8547 в качестве одного из примеров. В нашей версии постараемся сделать робота более компактным за счет извлечения третьего мотора (рис. 8.111—8.117). Самую важную часть — гусеницы — следует закрепить наиболее прочно, по возможности с предельным натяжением.

 

  
 

Рис. 8.111. Крепление моторов с помощью 11-модульной балки и угловых соединительных штифтов.

 

Рис. 8.112. Дополнительные уголки размером 3 · 5 для крепления блока NXT.

 

Рис. 8.113. Для крепления колесных дисков используются 8-модульные оси в задней части робота.

 
 

Рис. 8.114. Вертикальные балки для крепления NXT спереди могут быть любой длины. В оранжевые диски моторов вставляются 10-модульные оси.

 

Рис. 8.115. Колесные диски прижимаются к желтым втулкам.

 

Рис. 8.116. Гусеницы можно закрепить 16-модульными балками с выступами.

 

Рис. 8.117. Первая версия тележки готова.

Направление движения робота — вперед оранжевыми дисками моторов, подключенный на порты B (левый) и C (правый). Протестируйте работоспособность модели на примере программ из NXT Program.

Известный лабиринт

Первое, что научится выполнять наш робот, — точные перемещения. Для начала их будет всего три вида: проезд одной клетки вперед, поворот направо на 90 градусов, поворот налево на 90 градусов. Выделим их в три отдельных набора команд (рис. 8.118). Строго говоря, команды такого типа являются высокоуровневыми, т. е. содержат внутри себя какие-то сложные действия, исполняемые операционной системой, которые программисту не видны. В системах с виртуальным исполнителем «Робот» так и происходит. Для реализации этого в физическом мире необходимо научиться управлять роботом на «низком уровне», т. е. все команды управления роботом указывать достаточно подробно.

 

Моторы B, C вперед

Жди 1000 на энкодере B

Моторы стоп

 

Рис. 8.118. Реализация трех базовых команд для лабиринта на языке Robolab.

Конструкция гусеничного робота такова, что проезд ячейки длиной 30 см требует поворота моторов примерно на 1000 градусов. А поворот на 90 градусов на месте выполяняется при повороте одного мотора на 500 градусов вперед, а другого на –500 градусов назад.

Пример на языке Robolab показывает прохождение первых трех ячеек лабиринта (рис. 8.119). Программа составлена из трех блоков команд, повторяющихся в разном порядке.

 

Рис. 8.119. Пример программы прохождения трех ячеек лабиринта.

Первые запуски, скорее всего, приведут к тому, что робот начнет зацепляться за неровности в стенах лабиринта своими бортами. Для защиты от зацепов существует элементарное решение, уже использованное в шагающем роботе для NXT 2.0. Это горизонтальные свободно вращающиеся колесики (рис. 8.120).

      
 

Рис. 8.120. Горизонтальные колесики устанавливаются на гладкие штифты или оси в круглые отверстия на изогнутых балках.

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

Возвращаясь к программированию, придется признать, что действуя по предложенному выше алгоритму, можно составить программу прохождения лабиринта размером 5 · 5, которая уже не уместится в один экран Robolab. Копирование блоков сильно удлиняет программу, что увеличивает вероятность возикновения ошибок, а при смене структуры лабиринта делает редактирование затруднительным. Опытный программист сразу догадается, что можно использовать подпрограммы! 

Для ясности управления следует представить робота как классического исполнителя с тремя базовыми командами: «Вперед», «Налево», «Направо». Каждая из них является высокоуровневой и с точки зрения реального исполнителя — довольно сложной. Команда «Вперед» — это проезд одной клетки лабиринта с последующей остановкой. Команды «Налево» и «Направо» — это повороты на 90 градусов с максимально возможной точностью. Недостатки исполнения команд, связанные с люфтом и трением, придется компенсировать конструктивно.

По принципу нумерования верхних кнопок контроллера NXT три процедуры получат соответствующие номера: 3 — «Вперед», 2 — «Налево», 1 — «Направо». В процедуры стоит включить необязательные, но полезные действия, которые позволят лучше контролировать выполнение отдельных команд: остановки, задержки и звуковые сигналы.

Используя отдельные вызовы процедур, составьте программу прохождения некоторой части лабиринта (рис. 8.121).

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

 

Рис. 8.121. Три базовых действия в процедурах и начало программы прохождения лабиринта.


Дата добавления: 2019-02-22; просмотров: 1939; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!