Занятие 20. Двухмоторная тележка
Это самая распространенная разновидность роботов. Тележка может быть с тремя точками опоры, две из которых — ведущие колеса, а третья — волокуша, или свободно вращающееся колесико.
Процесс построения одной из наиболее простых тележек.
Шаг 1. Для крепления моторов, которые будут располагаться по обе стороны от NXT, берем две изогнутые балки:
Шаг 2. В зависимости от расположения балок центр тяжести тележки может быть смещен:
Шаг3. Дополнительные крепления для придания устойчивости:
Все готово для установки контроллера:
Шаг 4. Колеса устанавливаются на 6-модульные оси, втулки предохраняют от нежелательного трения о корпус.
Шаг 5. Конструкция для крепления третьего колеса:
Шаг 6. Элементы подвижного колеса. Длины осей — 3 и 5 модулей. Колесо должно вращаться свободно.
Тележка готова.
Знакомство со средой Robolab 2.9
Палитра функций включает в себя различные типы команд:
Простейшие алгоритмы.
Квадрат. По умолчанию считаем, что левый мотор подключен к порту В, правый — к порту С. Проверьте подключение.
Повторяй 4 раза:
- моторы B, C вперед;
- жди N/100 секунды;
- мотор С назад (B продолжает двигаться вперед);
- жди N/100 секунды.
Стоп моторы.
Установка шестеренок и колес для полноприводной тележки уже знакома по предыдущей модели, поэтому вдаваться в детали не станем
(рис. 3.21-3.23).
Рис. 3.15. Повторение основы тележки.
Рис. 3.16. Заднее крепление для NXT на базе одномоторной тележки.
46
Рис. 3.17. Установка вертикальных штифтов для крепления к NXT снизу.
Рис. 3.18. Можно ставить контроллер.
47
Рис. 3.19. Для надежности колеса закрепляются полувтулками.
Рис. 3.20. Мотор подключается на порт B.
48
Рис. 3.21. Установка полного привода.
Рис. 3.22. Установка колес возможна с удлинителями осей.
49
Если вы до сих пор еще не начали программировать на NXT, то простую инструкцию по движению одноили двухмоторной тележки найдете в начале данной главы. При запуске берегите пальцы – зубцы шестеренок соприкасаются с большой силой!
Рис. 3.23. Вид сбоку.
Тележка с изменением передаточного отношения
Итак, первая задача выполнена, тележка тронулась с места. Теперь попытаемся сделать из нее гоночный автомобиль. Понятно, что нагружать ее при этом пока не будем. Для увеличения скорости достаточно увеличить передаточное отношение (рис. 3.26).
Приступим к строительству. Необходимо снять с предыдущей модели колеса, шестеренки и несущие балки (рис. 3.24), модифицировав конструкцию (рис. 3.25—3.26).
Попробуйте поэкспериментировать. Можно заметить, что при достаточно высоком передаточном числе тележка просто не тронется с места: ее придется самим разгонять и подталкивать. А в приподнятом состоянии колеса будут крутиться быстро-быстро. Чего же не хватает? Очевидно, тяговой силы. Выиграв в скорости, мы потеряли в силе — моторам уже не хватает мощности для старта. Автомобилисты сталкиваются с этим при переключении коробки передач. Самое большое усилие развивается на низких передачах. Воспользуемся ими.
50
Двухмоторная тележка
Трехточечная схема
Это самая распространенная |
||
разновидность роботов. Тележка мо- |
||
жет быть с тремя точками опоры, две |
||
из которых — ведущие колеса, а тре- |
||
тья — волокуша, или свободно вра- |
||
щающееся колесико (рис. 3.71). Та- |
||
кие модели являются базовыми для |
||
наборов 8527 и 9797. Инструкции по |
||
сборке прилагаеются. Если попытае- |
||
тесь построить такую тележку само- |
Рис. 3.71. Схема трехколесной |
|
стоятельно, помните, что центр масс |
||
должен находиться не над волоку- |
тележки с подвижным третьим |
|
колесом. |
||
шей, а ближе к ведущим колесам. |
||
Именно по этой схеме построена |
стандартная тележка из наборов 8527 и 9797 (рис. 3.72). В инструкциях этих наборов есть небольшие различия, но суть одна.
Рис. 3.72. Стандартная основа для робота из набора 9797.
Для тех, кто не хочет ограничиваться базовыми конструкциями, рассмотрим несколько примеров крепления моторов к NXT. От них можно отталкиваться при создании собственных роботов. Второй пример любезно предоставлен Центром инженерной поддержки образова-
ния на сайте http://www.legoengineering.com [4].
75
Простейшая тележка
Для придания устойчивости роботу имеет смысл поставить моторы по двум сторонам от NXT. Это несколько расширит корпус тележки
(рис. 3.73).
Рис. 3.73. Широкая тележка — простейший вариант.
Рис. 3.74. Изогнутые балки для крепления моторов.
Предлагаемую конструкцию (рис. 3.74—3.81) можно делать вдвоем
— бóльшая часть деталей устанавливается симметрично. А вот на подключение моторов следует обратить внимание. Для совместимости с алгоритмами, изложенными в этой книге, договоримся, что мотор B — слева, а мотор C — справа по курсу движения. На нашей тележке провода придется подсоединить накрест.
76
Рис. 3.75. В зависимости от расположения балок может быть смещен центр тяжести тележки.
Рис. 3.76. Дополнительные крепления для придания устойчивости.
77
Рис. 3.77. Колеса устанавливаются на 6-модульные оси, втулки предохраняют от нежелательного трения шин о корпуса двигателей.
Рис. 3.78. Две половинки соединяются контроллером NXT и 15-модульной балкой, которая крепится к каждому мотору на 2 штифта.
78
Рис. 3.79. Элементы подвижного колеса. Длины осей — 3 и 5 модулей.
Рис. 3.80. Сборка заднего подвижного колеса. Обе оси должны вращаться свободно.
Простейшая конструкция тележки показана на рис. 3.81, однако в ней есть пара недостатков. Корпус тележки расположен с небольшим наклоном вперед. Если убрать одну втулку из вертикальной оси подвижного колеса, корпус выровняется, но тогда тележка потеряет возможность двигаться назад: колесико начнет цепляться за балку. Замена втулки на полувтулку решит проблему лишь отчасти.
79
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
Двухмоторная тележка
Двухмоторная тележка
Трехточечная схема
Это самая распространенная разновидность роботов. Тележка может быть с тремя точками опоры, две из которых — ведущие колеса, а третья — волокуша, или свободно вращающееся колесико (рис. 3.71). Такие модели являются базовыми для наборов 8527 и 9797. Инструкции по сборке прилагаются. Если попытаетесь построить такую тележку самостоятельно, помните, что центр масс должен находиться не над волокушей, а ближе к ведущим колесам.
Именно по этой схеме построена стандартная тележка из наборов 8527 и 9797. В инструкциях этих наборов есть небольшие различия, но суть одна.
Для тех, кто не хочет ограничиваться базовыми конструкциями, рассмотрим несколько примеров крепления моторов к NXT. От них можно отталкиваться при создании собственных роботов. Один из примеров любезно предоставлен Центром инженерной поддержки образования.Саму инструкцию можно посмотреть здесь или воспользоваться изображениями, выложенными ниже:
Название проекта: Робот Educator Vehicle LEGO Mindstorms Education EV3
Платформа: LEGO Mindstorms
Робот Educator Vehicle — стандартная модель для базового образовательного набора LEGO Mindstorms EV3 Education. Это простая модель двухмоторной тележки подходит для отработки навыков настройки и программирования легороботов начинающими, детьми и студентами. Используя робота можно решать общепринятые задачи образовательной робототехники: движение по линии, избегание препятствий, движения вдоль стены и другие. Для этих целей на робота можно установить датчики: цвета, расстояния, касания и другие.
Скачать инструкцию по сборке.
Использованные компоненты: базовый набор LEGO Mindstorms Education EV3, артикул 45544
Сайт проекта: http://robotsquare.com/2013/10/01/education-ev3-45544-instruction/
Другие проекты на этой платформе:
- Двуногий робот из Arduino, LEGO и деталей 3D печати
- LEGO EV3 робот-художник
- SpinnerBot из LEGO Mindstorms
- LegoGun — двуствольный пистолет из Lego Mindstorms EV3
- Спирограф — рисующий робот из LEGO Mindstorms EV3
- Бесполезная коробка из Lego Mindstoms EV3
- Гексапод из Lego Mindstorms EV3
- Роботизированная рука из Lego Mindstorms EV3
- Подъемные механизмы из LEGO Mindstorms
- Прибор автоматической подачи одноразовых стаканчиков из LEGO Mindstorms
- Робот-кабан-динозавр DINOR3X из LEGO Mindstorms EV3
- Znap — робот из LEGO Mindstorms EV3
- Робот-сортировщик (Color Sorter) из LEGO Mindstorms EV3
- Робот-сигвей (Gyro Boy) из Lego Mindstorms
- Робот-манипулятор Arm H25 из LEGO Mindstorms
- Робот-гексапод NXTAPOD из LEGO Mindstorms. Модель Даниэля Бенедеттелли
- Робот-щенок (Puppy) из LEGO Mindstorms EV3
- Лимоноид — робот, продающий напитки
- Киноаппарат из Lego Mindstorms
- Принтер из Lego Mindstorms «STALKER ver. 2.0»
- Робот-пожарный из LEGO Mindstorms
- Крестики-нолики — ARBUZIKI-TEAM
- EZ Wilber — говорящий балансирующий робот из Lego Mindstorms
- Ev3 Print3rbot — робот-художник из Lego Mindstorms
- 3D-принтер из Lego печатает шоколадом
- Lego Mindstorms NXT 2.0 играет в шахматы
- Робот-гексапод из Lego Mindstorms NXT 2.0
- Робоноги из Lego Mindstorms
- Lego Mindstorms-экскаватор, управляемый Microsoft Kinect
- Lego-робот DIZZ3
- Крестики-нолики для Lego-робота
- Lego Mindstorms EV3 3D-принтер 2.0
Перейти в каталог DIY-проектов роботов
Как добавить робопроект в каталог?
Теги: Lego Education, Lego Mindstorms, инструкция
Последнее время вокруг все больше разговоров об искусственном интеллекте, то там то тут звучат модные термины «нейросети» и «генетические алгоритмы». В прошлых проектах (НейроКачели, НейроБашня и N3uralV1s10n) мы уже создавали простейшие нейронные сети, разобрались с тем что это такое в первом приближении и как они работают. Похоже пришло время сделать тоже самое с генетическими алгоритмами.
Генетический алгоритм — это прежде всего алгоритм эволюционный. Его основная фишка взята из живой природы. При поиске оптимального решения задачи мы порождаем варианты, отбираем из них лучшие, «скрещиваем» между собой, получая решения с общими для «родителей» удачными свойствами.
Для того чтобы пощупать всю эту магию в действии мы применим ее к решению классической задачи робототехники — движению робота по черной линии, а точнее — к подбору параметров ПИД-регулятора для того, чтобы робот смог двигаться по линии быстрее и точнее.
Замечание: данный проект не несет в себе ни оттенка соревновательной составляющей. Наша основная цель не в том, чтобы «вывести» быстрого гонца по линии, мы хотим получить опыт использования алгоритмов генетического типа с целью дальнейшего их использования в близкой нам по духу хоббийной робототехнике.
Начнем с конструкции робота. Это традиционная двухмоторная тележка на базе LEGO Mindstorms NXT, в передней части установлено 4 датчика освещенности, два из которых (внутренних, подключенных к портам 2 и 3) используются ПИД-регулятором робота для движения по линии, а два внешних(подключенных соответственно к портам 1 и 4) — для контроля срыва с линии в процессе обучения. Инструкцию в формате LEGO Digital Designer можно скачать по ссылке.
Для реализации поиска лучших для данной трассы коэффициентов ПИД-регулятора с применением генетического алгоритма нам потребуется создавать в памяти экземпляры ПИД-регулятора и автоматизированно тестировать их на реальном роботе, оценивая результат на соответствие заданному условию — более длинный пройденный путь в единицу времени, соответственно выше скорость движения по линии, при этом срывы с трассы недопустимы.
Алгоритм в общем виде выглядит следующим образом:
Для создания первой популяции виртуальных роботов давайте, для начала, опишем пользовательскую структуру данных, которая будет использоваться в качестве шаблона для создания особей в популяции.
struct person
{
// у каждой особи должно быть имя, хотя бы codename
string name;
// номер поколения, в котором родилась данная особь
int generation;
// энергичность (быстрота) особи
int speed;
// скорость реакции
float reaction;
// мудрость (память) особи
float memory;
// интуиция (проницательность)
float intuition;
// степень доминантности особи
float dominance;
// пройденный особью путь за отведенный на тестирование промежуток времени
int path;
};
Теперь создадим первую популяцию на основе этого шаблона, в ней у нас будет 6 особей:
person robot[6];
Генерируем случайным образом свойства особей первой популяции:
for (int i=0;i<6;i++){
robot[i].name = «GeneLINEr_»+NumToStr(Random(1000));
robot[i].generation=1;
// энергичность (быстрота) особи 0..100
robot[i].speed = Random(70)+30;
// скорость реакции 0..3
robot[i].reaction = Random(3000)/1000;
// мудрость (память) особи 0..0,1
robot[i].memory = Random(100)/1000;
// интуиция (проницательность) 0..3
robot[i].intuition = Random(3000)/1000;
// степень доминантности особи не понятна до тестирования
robot[i].dominance = 0;
// пройденный особью жизненный путь = 0
robot[i].path = 0;
}
Далее начинается самое интересное. Начинаем условно бесконечный цикл смены поколений. В каждом поколении нам нужно испытать особей данного поколения и выявить из них самых быстрых и точных, не слетающих с трассы.
В роботе реализована функция ПИД-регулятора движения по линии, принимающий на вход параметры Kp, Ki, Kd, скорость робота, выполняющая 5 секундное движение по линии и возвращающая длину пройденного пути, сглаженного до криволинейной траектории.
long pid(float Pk,float Ik,float Dk,int speed){
long B=0;
long C=0;
long path=0;
long MC=MotorRotationCount(OUT_C);
long MB=MotorRotationCount(OUT_B);
long e = 0;
int porog=28;
float ERRo=0;
float ERR=0;
float u=0;
float z1=0;
float z2=0;
long tmp=CurrentTick();
int p;
int i;
int d;
while(CurrentTick()-tmp<=5000){
MC=MotorRotationCount(OUT_C);
MB=MotorRotationCount(OUT_B);
ERR=Sensor(IN_3)-Sensor(IN_2);
p=Pk*ERR;
d=Dk*(ERR-ERRo);
i=Ik*e;
if(i>10)i=10;
if(i<-10)i= -10;
u=p+i+d;
z1=speed-u;
z2=speed+u;
if(speed-u>100)z1=100;
if(speed-u<-100)z1=-100;
if(speed+u>100)z2=100;
if(speed+u<-100)z2=-100;
OnFwd(OUT_B,z1);
OnFwd(OUT_C,z2);
if(Sensor(IN_1)<=porog){
PlayTone(TONE_C5, MS_500);
RotateMotorEx(OUT_BC, 35, 100, 100, true, true);
go_to_line();
break;
}
if(Sensor(IN_4)<=porog){
PlayTone(TONE_C5, MS_500);
RotateMotorEx(OUT_BC, 35, 100, -100, true, true);
go_to_line();
break;
}
ERRo=ERR;
e+=ERR;
B=MotorRotationCount(OUT_B)-MB;
C=MotorRotationCount(OUT_C)-MC;
if(B>0 && C>0){
if(B<C){
path+=B;
}
else{
path+=C;
}
}
}
Off(OUT_BC);
return path;
}
void go_to_line(){
float P=1.0;
float D=1.0;
float ERRo=0;
float ERR=0;
float u=0;
while(abs(Sensor(IN_2)-Sensor(IN_3))>5){
int ERR=Sensor(IN_3)-Sensor(IN_2);
int u=P*ERR+D*(ERR-ERRo);
int z1=-u;
int z2=+u;
if(z1>100) z1=100;
if(z1<-100) z1=-100;
if(z2>100) z2=100;
if(z2<-100) z2=-100;
OnFwd(OUT_B,z1);
OnFwd(OUT_C,z2);
}
}
В случае, если в процессе 5-секундного испытания особи один из внешних датчиков видит линию, считается что робот сошел с трассы. При этом функция возвращает его на линию и особь выбывает из тестирования с результатом, который успела набрать до срыва, как правило рейтинг данной особи будет низким.
for (int i=5;i>=0;i—){
robot[i].path = pid(robot[i].reaction,
robot[i].memory,robot[i].intuition,robot[i].speed);
PlayTone(TONE_A4, MS_500);
}
После испытания всех особей текущего поколения ранжируем их в порядке убывания пройденного за время тестирования пути. Так как время на тест для каждой особи фиксировано — 5 секунд, соответственно у особей убывает и скорость. Будем использовать пузырьковую сортировку и «временную особь», для перестановки пар при ранжировании.
person robot_tmp;
for (int i=0;i<5;i++){
for (int j=0;j<(5-i);j++){
if(robot[j].path < robot[j+1].path){
robot_tmp = robot[j];
robot[j]=robot[j+1];
robot[j+1]= robot_tmp;
}
}
}
Чем выше у особи рейтинг, тем выше и доминантность данной особи, соответственно тем большую часть свойст данной особи унаследуют ее потомки (выше = ближе к 1):
for (int i=0;i<6;i++){
robot[i].dominance=i+1;
}
Две особи, самые слабые в популяции (5 и 6 в ранжированном списке) умирают, остальные дают потомство, порождая 6 особей новой популяции, наследующих черты родительских особей. В скрещивании участвуют доминантные признаки особей, давая соотношение унаследованных признаков. Унаследованный признак новорожденного кроме этого подвергается колебанию в 20%, для ускорения эволюции.
person newborn(person male, person female){
person newburn;
male.dominance = 1 — (male.dominance/(male.dominance+female.dominance));
female.dominance = 1 — male.dominance;
newburn.name = «GeneLINEr_«+NumToStr(Random(1000));
newburn.generation=male.generation+1;
if(male.speed>female.speed){
newburn.speed = male.speed;
}
else{
newburn.speed=female.speed;
}
newburn.reaction = male.reaction * male.dominance + female.reaction * female.dominance;
newburn.reaction =newburn.reaction *((Random(40)+80)/100.0);
newburn.memory = male.memory * male.dominance + female.memory * female.dominance;
newburn.memory =newburn.memory *((Random(40)+80)/100.0);
newburn.intuition = male.intuition * male.dominance + female.intuition * female.dominance;
newburn.intuition = newburn.intuition *((Random(40)+80)/100.0);
newburn.path = 0;
newburn.dominance = 0;
if(newburn.speed>max_speed){
max_speed=newburn.speed;
}
return newburn;
}
// новая популяция из 6 особей
person robot_next_generation[6];
robot_next_generation[0] = newborn(0,1);
robot_next_generation[1] = newborn(0,2);
robot_next_generation[2] = newborn(0,3);
robot_next_generation[3] = newborn(1,2);
robot_next_generation[4] = newborn(1,3);
robot_next_generation[5] = newborn(2,3);
Теперь в дело вступает природа и у одной, случайной особи происходит мутация — ее один, случайный, признак изменяется. Мутация чаще всего приводит к появлению неконкурентоспособных или вообще нежизнеспособных особей, однако очень полезна в ситуации, когда вектор развития эволюции пошел изначально не в том направлении. В результате мутации может появиться особь со свойством, выигрышно выделяющим ее на фоне остальных. Такая особь сразу же окажется на вершине рейтинга и даст начало новой династии.
// Мутация
void mutants(){
int property=Random(3);
int mutant=Random(5);;
if(mutant<4){
switch(property){
case 0:
robot_next_generation[mutant].speed = max_speed+5;
break;
case 1:
robot_next_generation[mutant].reaction =robot_next_generation[mutant].reaction *((Random(40)+80)/100.0);
break;
case 2:
robot_next_generation[mutant].memory =robot_next_generation[mutant].memory *((Random(40)+80)/100.0);
break;
case 3:
robot_next_generation[mutant].intuition = robot_next_generation[mutant].intuition *((Random(40)+80)/100.0);
break;
default:
break;
}
}
else{
switch(property) {
case 0:
robot_next_generation[mutant].speed = max_speed+5;
break;
case 1:
robot_next_generation[mutant].reaction = Random(3000)/1000;
break;
case 2:
robot_next_generation[mutant].memory = Random(100)/1000;
break;
case 3:
robot_next_generation[mutant].intuition = Random(3000)/1000;
break;
default:
break;
}
}
}
Теперь производим смену популяций. Дети сменяют родителей:
for(int i=0;i<6;i++){
robot[i]=robot_next_generation[i];
}
Теперь снова пришла пора испытать новое поколение, более приспособленное к решению поставленной задачи, оценить возросшую скорость,, выявить сильнейших и так до тех пор, пока результат не будет нас устраивать.
На этапе ранжирования можно сохранять информацию о свойствах особей в каждой популяции в файл.
byte fh;
int msg_len;
string logstr;
for(int i=0;i<6;i++){
logstr = robot[i].name;
logstr = logstr + «;» + NumToStr(robot[i].generation);
logstr = logstr + «;» + NumToStr(robot[i].reaction) +»;»+NumToStr(robot[i].memory)+»;»+NumToStr(robot[i].intuition);
logstr = logstr + «;» + NumToStr(robot[i].path)+»;»+NumToStr(robot[i].speed);
msg_len = StrLen(logstr);
WriteLnString(fh, logstr, msg_len);
}
По данным, накопленным в файле в процессе работы программы, можно представить ход эволюции в виде наглядного графика (ось X — номер поколения, ось Y — средняя скорость особи):