http://poradumo.pp.ua

Online Журнал-Світ порад.
Головна сторінка
» » Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода


Опускаючи розказні про те, як саме я прийшов до думки побудувати гексапода (це були тонни відео на ютубі), перейду відразу до процесу вибору деталей. Це був січень 2012-го. Я відразу знав, чого я хочу від свого робота, а чого - ні. Я хотів:



щоб кожна нога мала 3 ступеня свободи - 3dof (3 dimensions of freedom), тому що більш простий варіант 2dof - не дає такого відчуття комахи, а 4dof - зайвий, 3dof і так дозволяє вільно переміщати кінчик ноги в 3д просторі;




6 ніг. Знову-таки, це вже не 4 (тоді робот незграбно скаче), але ще й не 8 як у павуків, що вже надмірно;




невеликий розмір;




дешевий по собівартості;




з мінімумом плат і з'єднань.




Крок 1 . Насамперед, звичайно, потрібно було вибирати motherboard для дитини. Багато як хорошого, так і поганого встиг почитати до того часу про Arduino. Але саме на нього і смився, як на основний варіант. Паяти контролери самому - часу не було, а брати більш просунуті плати з ARM cpu, наприклад - дорого, та й розбиратися, як їх программить, як працювати з ШІМ висновками тощо - довго. А ардуина: IDE запустив, код напедалил, upload натиснув - і привіт, воно тобі вже моргає. Краса! ;)

Спочатку я почав смитися на arduino mega і клонів, тому кількість ШІМ виходів, якими можна керувати сервами у них було достатньо. Нагадаю, що для 3dof гексапода потрібно 3*6 = 18 сервів, і роздільних каналів управління ними. Але потім я знайшов справжній Яззь серед arduino mega, це плата від Dagu, кликати Red Back Spider Controller. Ось вона на ebay .

Вона пропонує всі свої виходи у вигляді готових 3-х штирків (земля, харчування, сигнал), і розв'язку з харчування. Харчування самого контролера стабілізовано, а на роз'єми двиглов йде як є (UPD: не як, а теж стабілізовані 5 вольт. І мабуть розв'язано з харчуванням контролера, тому перешкод у роботу контролера 18 одночасно працюючих сервів не вносять). Це дозволяє просто подати на клему харчування 7-30 вольт достатньої потужності (питальника від eee pc 901 на 12В і 3А - виявилося достатньо для дзижчання усіма 18 сервами) і не морочити голову з роздільним харчуванням логіки і двиглов. Також це дозволить у майбутньому легко посадити все це чудовисько на пачку Li-Po акумуляторів на 7.4 вольт. І при всьому цьому, з програмної точки зору - це звичайна ардуїнов мега, сумісна з софтом і либами, так і залізом (крім шилдов, що встановлюються прямо на оригінальну mega - вони не пройдуть). Правда ціна ще вища, ніж навіть оригінальна мега, але всі інші плюси переважили це.

Крок 2 . Далі сервоприводи. На ebay за запитом micro servo їх багато різних. Я взяв найпотужніші із самих маленьких і дешевих, вагою 9 грам, пластмасовими редукторами. Якщо брати лоти де їх пачками шлють - виходить дешевше. Я брав 3 пачки по 6 здається, і вийшло менше $2 штука. Забігаючи вперед, скажу, що шкодую, що не витратив більше і не взяв серви з металевими шестернями і кульковими підшипниками. У цих пластмасових виявилися досить помітні люфти, і характерний хрускіт при надмірному зусиллі коли шестерні проскакують. З-за люфтів - кінематику досить важко налаштувати точно (так це взагалі найважче виявилося).

Ось власне і все що я замовив, з доставкою це вийшло приблизно $100. Батарейки і передавачі/приймачі для контролю і радиоуправляемости - залишив на потім. Тому що радіокерована машинка у мене є і не цікава, а що мене справді цікавило - це ноги! Відео плавно ходять гексаподов на ютубі - заворожувало я смився його, переглядав, і кожен раз сльози котилися по щоках, і я здавлена хрипів «хочу!». Хочу не замовити таку готову штуку, а хочу зробити самому що-небудь таке!

Поки чекав замовлення, читав, як освічені люди оживляють свої творіння. Звичайно, відразу ж спливла інверсна кінематика . Якщо сказати просто і відразу про шарнитние «кінцівки», то пряма кінематика - це коли на вхід подаються кути шарнірів, а на виході ми маємо модель кінцівки в просторі, координати крайньої точки кінцівки. Зворотна ж кінематика - очевидно працює навпаки - на вхід надходять координати крайньої точки кінцівки, куди нам треба дотягнутися, а на виході ми отримуємо кути, на які потрібно повернути шарніри, щоб це здійснити. Сервоприводи якраз отримують на вхід кутове положення, в яке їм потрібно повернутися (по одному сигнального проводу, закодоване ШІМ /PWM ).

Крок 3 . Почав з того, про що читав: продумувати реалізацію ІК. Але швидко прийшло відчуття, що для мого випадку він надмірно складний. Причому як громіздкий в реалізації, так і обчислювально дуже складний - розрахунок йде ітеративне. А в мене 6 ніг, для кожної з яких слід вважати ІК, і всього 16Мгц не самої спритною архітектури AVR. Але і всього 3 ступеня свободи. І нескладно здогадатися, що до довільної точки в області дотягування» можна дотягнутися тільки одним способом. Рішення вже дозріло в голові.

Але тут прийшов лютий і посилки - одна з Китаю, інша UK. Першим ділом я, звичайно, просто погрався з платою ардуїнов - поморгал світлодіодом і попиликал в підключеного туди динамік. Потім зайнявся реалізацією власне ІК, вже в залозі. Для чого спорусм прототип ноги з підручних матеріалів (досить м'яка пластмасска, яку легко різати ножицями, шурупи і насадки - все з комплектів сервоприводів). Цю ногу термінатора закріпив прямо на плату ардуини. Можна розглянути, як бюджетно виконані зчленування.

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода


Помилувався на цю справу, і помріяв, що якщо я на основі цього робота в майбутньому спаяю термінатора, який оголосить війну людству, то потім Джон Коннор зі Шварцнеггером повернуться до мене сюди у минуле, і відберуть цей прототип і расплавят його в Ородруине. Але ніхто не повернувся, нічого не відібрав, і я спокійно продовжив.

Крок 4 . Виявилося, що ІК зовсім не потрібно боятися, в моєму випадку все звелося до банальної геометрії-тригонометрії. Щоб простіше було звертатися до суглобів, звернувся до вікіпедії і почитав про комах. У них є спеціальні назви для елементів кінцівки:

Збираємо та змушуємо бігати бюджетного гексапода


Російською теж є свої дуже цікаві назви для цього, але «тазик», «вертлуг», «гомілка» і т.п., перебуваючи в коді, не давали мені заснути. Тому я 3-х кінцівках і відповідним сервам залишив назви Coxa, Femur, Tibia. З прототипу ноги вище видно, що у мене для coxa навіть немає окремої деталі. Це просто два серва, скріплених гумками. Femur - реалізований смужкою пластику, до якої з обох сторін кріпляться важелі сервів. Таким чином, останній залишився серводвижок - є початком tibia, для подовження якої до нього прикручений ще шматок пластику.

Крок 5 . Запустив редактор, не мудствуя створив файл Leg.h, І в ньому клас Leg. Ну і купу допоміжної муті. Нехай в просторі є точка A(ax, ay, az), до якої треба дотягнутися. Тоді вигляд зверху виглядає так:

Збираємо та змушуємо бігати бюджетного гексапода


На малюнку я відразу показав і спосіб обчислення першого кута - це кут повороту серва, керуючого Coxa, що обертає всю кінцівку в горизонтальній площині. На схемі червоним відразу позначені змінні, використовувані в коді (далеко не всі). Не дуже математично, зате зручно. Видно, що цікавить нас кут знаходиться елементарно. Спочатку primaryCoxaAngle - знаходиться просто кутом (0;A) до осі X (що еквівалентно куті точки A в полярних координатах). Але на схемі видно, що при цьому сама нога - не распаложена під цим кутом. Причина в тому, що вісь обертання coxa не перебуває на «лінії ноги» - не знаю як це правильно сказати. Не знаходиться в площині, в якій обертаються інші 2 суглоба і перебуває кінчик ноги, ось. Це можна легко компенсувати, вважаючи additionalCoxaAngle (як його вважати - навіть не утруждаюсь зупинятися, адже все ж були в школі, правда?).

Разом, у нас є перший шматочок коду, це нутрощі методу reach(Point& dest):



float hDist = sqrt( sqr(dest.x - _cStart.x) + sqr(dest.y - _cStart.y) );
float additionalCoxaAngle = hDist == 0.0 ? DONT_MOVE
: asin( _cFemurOffset /hDist );

float primaryCoxaAngle = polarAngle(dest.x - _cStart.x, dest.y - _cStart.y, _thirdQuarterFix);

float cAngle = hDist == 0.0 ? DONT_MOVE
: primaryCoxaAngle - additionalCoxaAngle - _cStartAngle;


Тут dest - це точка, куди нажо тягнутися, _cStart - координати точки кріплення (і центру обертання) coxa, в hDist вважаємо відстань від _cStart до dest в горизонтальній площині. DONT_MOVE - це просто прапор, який означає що coxa не потрібно нікуди обертати, а залишити в поточному положенні (тому dest - десь прямо на осі обертання coxa - рідко, але буває). Ось cAngle - це вже той кут, на який потрібно буде відхилитися сервоприводу від його початкового кута (який знаходиться в середині його робочого діапазону). Видно що також юзается _cStartAngle - це кут у просторі, на який повернутий серво за деволту, при монтажі. Про _thirdQuarterFix розповім пізніше, якщо не забуду.

Крок 6 . Далі все стає ще простіше. Нам просто потрібно поглянути на згадану вище площину «лінії ноги»:

Збираємо та змушуємо бігати бюджетного гексапода


При цьому, завдання раптово зведеться до пошуку точки перетину 2-х кіл. Одна - в точці, звідки «росте» наша femur, друга - точка, куди нам треба дотягнутися (локальним 2d координатами). Радіуси кіл - довжини femur і tibia відповідно. Якщо кола перетинаються в одній з 2х точок можна розташувати суглоб. Ми завжди вибираємо верхню, щоб «коліна» у чудовиська були вигнуті вгору, а не вниз. Якщо не перетинаються - то ми не дотянемся до цільової крапки. Ще трохи коду, перехід у площину робиться елементарно, тільки пара підводних каменів ще врахована і задокументована в коментарі, щоб я не ламав голову потім, розбираючи код. Для простоти, що в цій локальній координатної «площині ноги» я вибрав початком координат точку, звідки росте femur:

  //Moving to local Coxa-Femur-target coordinate system 
//Note the case when hDist <= _cFemurOffset. This is for the blind zone.
//We never can't reach the point that is nearer to the _cStart then
//femur offset (_fStartFarOffset)
float localDestX = hDist sqr(_fLength + _tLenght))
{
log("can't reach!");
return false;
}


Крок 7 . Тепер localDestX і localDestY - це координати цільової точки. Все що залишилося - знайти точку перетину кіл з центрами в (00) та (localDestX, localDestY), і радіусами _fLength і _tLength (відповідно довжина femur і довжина tibia). З цим теж школяр впорається, але тут я допускав досить багато помилок, бо для перевірки себе і взагалі щоб кожен міг перевірити, що це за стрьомні формули, залишив посилання на джерела, де ясно і зрозуміло разжована ця елементарна геометрична задача:

  //Find joint as circle intersect ( equations from http://e-maxx.ru/algo/circles_intersection & http://e-maxx.ru/algo/circle_line_intersection ) 
float A = -2 * localDestX;
float B = -2 * localDestY;
float C = sqr(localDestX) + sqr(localDestY) + sqr(_fLength) - sqr(_tLenght);
float X0 = -A * C /(sqr(A) + sqr(B));
float Y0 = -B * C /(sqr(A) + sqr(B));
float D = sqrt( sqr(_fLength) - (sqr(C) /(sqr(A) + sqr(B))) );
float mult = sqrt ( sqr(D) /(sqr(A) + sqr(B)));
float ax, ay, bx, by;
ax = X0 + B * mult;
bx = X0 - B * mult;
ay = Y0 - A * mult;
by = Y0 + A * mult;
//Select solution on top as joint
float jointLocalX = (ax > bx) ? ax : bx;
float jointLocalY = (ax > bx) ? ay : by;



Все, залишилося ще трохи-за отриманими координатами обчислити власне кути для femur і tibia сервів:

  float primaryFemurAngle = polarAngle(jointLocalX, jointLocalY, false); 
float fAngle = primaryFemurAngle - _fStartAngle;

float primaryTibiaAngle = polarAngle(localDestX - jointLocalX, localDestY - jointLocalY, false);
float tAngle = (primaryTibiaAngle - fAngle) - _tStartAngle;


Крок 8 . Знову элементарщина - кутові координати і все. Я сподіваюся, іменування змінних вже повинно бути зрозумілим, приміром, _fStartAngle - це femur start angle, кут на який femur спрямований по дефолту. І останній рядок методу reach() (він сказав, поїхали, і махнув рукою):

  move(cAngle, fAngle, клубок);  



Метод move вже безпосередньо віддає команди сервам. Насправді, в ньому ще потім довелося додати всякі штуки для захисту від нехороших кутів (на які серво повернутися не може, але буде намагатися), а також для інших ніг, які заркально розташовані та/або спрямовані в інші сторони. Але поки що ми працюємо з однією тільки лапою.

Крок 9 . Ці шматки - це вже фінальний код, який далекий від досконалості, і напевно його можна значно поліпшити. Але він працює! Жодного разу не вийшовши за шкільний курс геометрії-тригонометрії, ми реалізували полнофункционалную инверсную кінематику для 3dof ноги! Та ще й отримуємо рішення відразу, за одну ітерацію. Щоб це все працювало, ногу треба було ретельно виміряти, і сконфігурувати клас отриманими даними. в тому числі кутовими, які складніше всього вимірювати на готовому виробі. Може якщо проектувати в автокад і наробити красивих рендерів - було б легше з вимірюванням кутів, але у мене не було ні часу, ні бажання займатися цим пафосом.

Лютий тільки почався, а відео з ногою вже було готове. Для перевірки ІК, я змушував ногу описувати всякі фігури у просторі (для цього потрібно було послідовно викликати reach, обходячи точки на прямокутнику, або кола, код нудний і нудний, тому не наводжу (а закінчивши експерименти з тим, щоб обводити примітивів, я його взагалі випиляв)):



Крок 10 . Далі потрібно було закінчувати гратися з цим виробом, на одній нозі далеко не упригаешь (хоча такий робот вийшов би дійсно цікавим). Але мені потрібен гексапод. Вирушив на найближчу барахолку шукати оргскло. Знайшов 2 відмінних шматка - один 3 мм товщиною (як раз для тулуба, подумав я), інший 2 мм і синій (відмінні кінцівки, в тон сервоприводам). Ще через пару тижнів я викроїв вечір, щоб що-небудь зробити з цього. Зробив начерки на папері. приміряв - ніби все ок, далі справа за ножівкою.

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода

Збираємо та змушуємо бігати бюджетного гексапода


Крок 11 . І ось воно, заморське чудовисько, шестилапое. Коли я тест одну ногу, я мав це справа якимось лівим питальником від зовнішнього гвинта. Вистачало. Але живити 6 ніг від нього було вже страшнувато. Тому я на деякий час повісив руки, думаючи, що мені потрібно ще роздобути підходящий питальник. Але виявилося все набагато простіше, я вже згадував вище - підійшов питальник від eee pc 901. Ну й чудово.

Крок 12 . Налагодити роботу 6-ти ніг виявилося ще складніше, ніж написати движок однієї ноги. Половина ніг була дзеркально відображена щодо іншої. Крім того спрямовані всі у різні боки. Вобщем конфигурировал і налаштовував я все дуже довго, і це мене не дуже надихало, тому коштів зручною налагодження не було, максимум на що я міг розраховувати - висновок лода у Serial. І той нормально працював з основного *.ino файлу, а з підключеного Leg.h - вже не бачився потрібний об'єкт. Накрутив милиць для лода (facepalm). З часом отрефакторю. А тут ще й весна прийшла, велосезон був відкритий в повну силу, і я закинув свого вихованця в шестилапого шафа. Так пройшло все літо і тепла частина осені.

Крок 13 . Але пішли дощі, стало холодно, і гексапод був витягнутий. Ноги його були налагоджені, в тому числі був введений той самий _thirdQuarterFix для функції розрахунку polarAngle. Проблема була в тому, що 2 ноги (ліва середня і задня ліва) рухалися так, що більшу частину часу перебували в III чверті:

Збираємо та змушуємо бігати бюджетного гексапода


А polarAngle у мене була наївна - вона повертала кути від-пі до пі, щодо осі X. І, якщо іноді однієї з цих 2-х ніг потрібно було повернутися в II-ю чверть, то значення polarAngle стрибало від-пі до пі, що власне негативно впливало на подальший розрахунок. Пофиксил милицею - для цих 2-х ніг polarAngle вважається «інакше». Соромно, соромно мені за код, але весь проект - це proof of concept, єдина мета якого - не просто зрозуміти, я можу зібрати реалістично рухається гексапода чи ні. Тому код повинен працювати, і прямо зараз. А вже потім рефакторинг - перерефакторинг.

Впоравшись з 3-ї чвертю, почав педалить патерни кроку. Для цього ввів в клас Leg точку default, тобто в якій нога знаходиться, коли робот стоїть струнко і рівно. Цю точку можна тюнінгувати, головне щоб всі ноги були на одній координаті z (щоб при цьому ноги реально фізично перебували на одній площині, у Leg є ще сама низькорівнева tuneRestAngles()). А в межах однієї координати Z, їх можна рухати майже як завгодно. Майже - тому що діапазон руху не нескінченний, і щоб при кроці не виходити за рамки цього диапазода - default положення ніг намагався розмістити десь ближче до центру цього діапазону.

Крок 14 . Код тут в тексті вже не наводжу, він занадто елементарний, і я наприкінці наведу посилання на повну версію усіх сорца - заодно навчуся користуватися github.

Послідовність кроку вибрав просту - 3 ноги на землі, 3 - у повітрі переставляються. Таким чином, координати ніг щодо їх default положення - можна розділити на 2 групи. Для цих двох груп я і провертав крок у циклі (см функцію walk() в Buggy.ino). А в підсумку, кожна нога обчислювала собі свою інсмідуальну координату, виходячи зі своєї default координати.

І він пішов! Але поки тільки вперед. На ноги надів йому резинки, щоб не так ковзав на лінолеумі. І кинувся знімати це на відео, щоб показати друзям.



Крок 15 . До а-пода, звичайно, далеко. Але я ж не закінчив ще .) Попедалил ще вечір - і додав можливість рухатися в будь-якому напрямку (але не повертаючи корпус .)). Плюс для згладжування між рухами додав функцію (smoothTo()), яка акуратно переміщує ноги (піднімаючи вгору, знову в 2-х групах, одна з яких завжди внизу, тварюка на ній стоїть, поки інша піднімається і переміщується) в нове положення. Це потрібно щоб тварина не смикала різко ногами, змінюючи напрямок руху (цієї фічі ох як не вистачає багатьом ігровим персонажам минулих років). І він жваво забігав в будь-якому напрямку - убік, по діагоналі:



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

Результати, які поки можна виділити:

- склепати самому гексапода - справа здійсненне;
- написати йому кінематику самому з нуля - теж цілком під силу будь-кому (розробнику);
- бюджет може бути мінімальним, єдине, на що дійсно необхідно витрачатися - це сервоприводи; а так, якщо є паяльник, то можна будь-яким мікроконтролером обійтися; чим зручніше, тим дорожче, втім;
- на сервах краще не економити, але і найдешевші - працюють;
- такого задоволення від програмування я не відчував з 9-ти років, коли вперше побачив на комп'ютерному гуртку zx spectrum і навчився писати перші програмки для нього; це так кайфово, коли твій код не просто десь працює і чого-то там комусь показує, а бігає прямо перед тобою і лякає кішку.

Попереду більш просунуті алгоритми для плавного переміщення тіла, ну і бездротове управління і батареї, звичайно ж.

habrahabr.ru
of your page -->

Популярні поради

загрузка...