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

Сам проект растянулся на долгое время и оказался, в целом, не слишком удачным (хотя и был доведён до условно рабочего состояния). Из-за длительных перерывов как минимум один раз мне пришлось переписывать код практически с нуля – я уже не мог понять, как именно он работает и, главное, почему не работает. В итоге проект всё же был доведён до логического завершения и функционирующего прототипа, но по ряду причин я считаю его практически провальным – о них я расскажу в конце статьи.

  1. Концепт проекта и начало изготовления.

  2. Немного о приводах и управлении.

  3. Работало ли всё это?

Задумал его очень давно, в 2015 году. Я вернулся в нашу лабораторию инновационной ерунды (я никогда не помнил этого длинного и, по сути, ни о чём не говорящего названия) со стажировки в Испании и мой научный руководитель загорелся идеей построить что-то красивое, что могло бы служить интересной демонстрацией технологий для студентов. По крайней мере, мне так помнится, возможно, цель была другая. В любом случае, он хотел построить автоматизированную машину для готовки бургеров, в которой процесс готовки был бы наглядно показан человеку, ожидающему этот самый бургер. Мне эта идея не понравилась по многим причинам. Во-первых, это не особенно интересно. Интересно будет только когда ты видишь это в первый раз, следующий бургер уже будет заказан только ради бургера. Во-вторых, это будет сопряжено с огромным количеством непредвиденных технических сложностей, ведь наш творческий коллектив по специальности были инженеры автомобильного транспорта, а не пищевой промышленности. И, в-третьих, проблемы с различными разрешениями, типа санэпидемстанции, для такой установки виделись мне весьма туманными. А кроме того, эту штуку ещё нужно было кому-то обслуживать. В общем, затея в моих глазах была сомнительно��. Пока мы раздумывали и открещивались, у меня родилась идея о создании робота, который бы мог играть с человеком в шахматы, физически переставляя фигуры. Однако и эта идея тогда не имела ни четкой формы, ни конкретного плана по воплощению, поэтому я её руководству не озвучил.

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

Реконструкция турка. Картинка из Википедии
Реконструкция турка. Картинка из Википедии

❯ Концепт проекта и начало изготовления

В какой-то момент возникла мысль, что робот может быть терминатором модели Т-800, которого после победы человечества перепрограммировали под эту задачу. Думаю, что вполне очевидно, почему я назвал проект Чесстером – просто потому, что это слияние двух слов chess и terminator.

Потом из Севастополя я уехал в Испанию делать PhD. Свободное время у меня было, а также был 3д принтер, который я собрал дома специально для перевозки в самолёте.

Принтер из спичек и жигулей (старые клапанные втулки использованы в качестве подшипников скольжения – ещё походят)
Принтер из спичек и жигулей (старые клапанные втулки использованы в качестве подшипников скольжения – ещё походят)

Вернулся к моей задумке, когда стал изучать Python по роду своей основной деятельности. Тогда я интереса ради забил в поиск, есть ли библиотеки, посвященные шахматам, и нашел python-chess. После изучения этой библиотеки, кирпичики начали складываться во что-то толковое. Теперь стало более-менее понятно, чего я хочу и как это воплотить. За механику я особенно не волновался (и как показала практика, напрасно), а вот программная часть вызывала большие опасения. И я начал постепенно собирать робота, не имея полного представления каким он должен получиться и как должен работать. Это была одна из моих первых ошибок, но, с другой стороны, собирая конструкцию практически из мусора, который у меня набирался тоже не сразу (различные моторы были набраны в основном из принтеров и сканеров с помоек), избежать этого пути было сложно.

Начал я с головы, т.к. масштаб, по сути, её и определялся. Принтер имеет очень маленькую рабочую зону, всего 120х120 мм и, чтобы не сильно заморачиваться с разрезанием и последующей сборкой головы из огромного количества частей (в итоге собирал из четырёх), я решил сделать робота немного меньше настоящего Шварцнегера. В сети я нашёл несколько 3д моделей черепа Т-800, но ни одна из них не подходила для моих целей на 100%. Пришлось осваивать Meshmixer и немного Blender, чтобы дорабатывать модели в соответствии с моими представлениями. Во-первых, голова должна была «говорить», то есть открывать рот в такт речи. По идее, робот должен был отпускать комментарии по ходу игры, спрашивать, не знаете ли вы, где живёт Сара Конор, он же хочет отправить открытку, честно. Функционал разговора я пытался опробовать, но делал это очень примитивно (я вообще тогда не очень сильно разбирался ни в электронике, ни в программировании): Ардуина слушала звуковой выход компа и открывала рот робота, когда уровень сигнала превышал определённый порог. Это была довольно глупая затея, так как очевидно, что робот будет открывать рот как минимум с запаздыванием, обусловленным временем реакции сервы. Я думал как бы можно было организовать задержку, но так толком и не придумал, и этот функционал остался не реализованным.

Голова Т-800
Голова Т-800

Ещё хотелось, чтобы робот мог вращать глазами. Эта задумка родилась после пересмотра первого терминатора, проведенного для освежения памяти. В самом конце есть сцена, когда Т-800 заходит внутрь завода и пытается понять, прислушиваясь, где прячется Сара. В этот момент он медленно переводит взгляд с одного места на другое и это очень выразительно смотрится. Я хотел того же эффекта, плюс он мог бы смотреть противнику в глаза во время игры, что должно было бы оказывать некоторое психологическое давление.

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

По поводу привода глаз моя первая идея была, в некотором роде, вдохновлена реальными человеческими глазами, только вместо мышц, глаза должны были приводиться в движение тросиками от сервоприводов. Я считал, что будет достаточно 4 тросика и два сервопривода на глаз. Однако собрав прототип, оказалось, что двигать глазом можно, а вот точное положение задавать не получается, по крайней мере с теми материалами и устройствами, что были в моем распоряжении. Делать терминатора со взглядом сиамского кота как-то не хотелось, поэтому пришлось искать другое решение. Далее мне подумалось, что управлять глазами можно только с двумя сервами, не разделяя управление каждый глазом. В этом случае робот не мог бы «фокусировать» взгляд, а смотрел бы на две тысячи ярдов, в прочем ему можно, у него ПТСД. Но даже это решение я в результате воплощать не стал, так как визуальные эффекты было решено оставить на закуску и сначала реализовать боевой функционал, а потом, увы, и вовсе было решено избавиться от этого проекта.

Дальнейший рост робота был довольно странным – из головы вырос позвоночник, который упирался в основание. В качестве этого основания была взята металлическая пластина от подставки старого условно плоского телевизора. Телевизор был весьма массивный и пластина была соответствующей. Кроме того, своей формой она очень хорошо подходила. В качестве опоры плечевого пояса была взята банка от чипсов «Принглс». Она была вклеена в позвоночник для чего в оном был сделан вырез по диаметру банки.

Также робот должен был наклонять голову вниз и вверх, переводя таким образом взгляд с шахматной доски на противника. Для этого в позвоночнике, в районе третьего – четвертого шейного позвонка, был размещен шарнир, а на спине, в уже упомянутой банке, жили две сервы, которые тянули голову вверх. Дешёвые MG90S в определенных положениях со своими задачами не справлялись, поэтому сильно наклонять голову было нельзя. Увы, и эту задумку я не реализовал и привод подъёма головы не был подключен к управляющей плате.

Видно уже упомянутое основание, банку от чипсов, а также левый и кусочек от правого тяжа, ведущих от спинных серв
Видно уже упомянутое основание, банку от чипсов, а также левый и кусочек от правого тяжа, ведущих от спинных серв

Постепенно я сделал торс и начал работать над рукой. Так как бандит был одноруким, я решил поместить актуатор, поднимающий руку, в левом плече, пропустив вал, на котором сидела рука через плечи насквозь. Так было удобнее, и нагрузка распределялась лучше. Кроме вала, через плечи проходили и две шпильки М3, стягивающие фланцы с подшипниками, в которых вращался вал привода плеча. К левому фланцу и был прикреплен актуатор. Чтобы он не проворачивался вместе с фланцем, внизу была организована дополнительная опора в виде треугольника из двух стержней, которые соединяли фланец с основанием робота. Под правый фланец была сделана аналогичная опора, в основном, чтобы его разгрузить. Дело в том, что кроме нагрузки от руки, на правое плечо приходилась также нагрузка от противовеса, который был призван облегчить нагрузку на актуатор подъёма руки, когда та полностью выпрямлена и перпендикулярна линии плеч. Противовес был козырный – из нержавеющей стали, чушка, извлеченная из отходов цеха, на которой экспериментировали со сваркой (на самом деле там какой-то ЧПУ станок что-то наваривает, что за технология – не знаю). На роботе он сначала просто висел, а потом был помещен в короб, чтобы не болтался при перемещении робота, да и просто на всякий случай.

Хотя я немного забежал вперед. На самом деле, перед установкой каких-либо работающих приводов на руку, я был занят шахматной доской. Доска – это важно, так как робот не мог играть с чем угодно. Дело в том, что из-за слабости моих навыков программирования, я решил не лезть в компьютерное зрение и делать систему как можно проще. А как сделать так, чтобы робот играл вслепую? Я решил, что необходимо чтобы доска была активной и могла сообщать компьютеру своё состояние. Я уверен, что есть огромное количество различных вариантов реализации этой задачи, но я выбрал самый примитивный – матричную клавиатуру. В результате компьютер получал матрицу 8х8 состоящую из 0 (клетка пуста) и 1 (клетка занята). Зная изначальное положение фигур, можно довольно легко отслеживать прогресс партии.

Схема матричной клавиатуры. Диоды позволяют занимать одновременно любое количество полей. Единственное, что в реальности я использовал Nano, а не Uno, но это одно и то же в плане контроллера
Схема матричной клавиатуры. Диоды позволяют занимать одновременно любое количество полей. Единственное, что в реальности я использовал Nano, а не Uno, но это одно и то же в плане контроллера

Хорошо, а практическая реализация? Тут я подумал, что робот, собранный из мусора, скорее всего, особой точностью похвастаться не сможет. Значит, надо сделать такую доску, чтобы можно было гарантированно точно поставить фигуру. Для этого, я решил сделать основание фигур конусным. Таким образом, когда робот фигуру отпускает, она автоматически самоустанавливается при падении. Это дало пространство для ошибки примерно ±1 см. Ладно, а как доска вообще должна работать? Не кнопки же туда действительно ставить? Да, не кнопки. В самом низу каждой фигуры я поместил небольшой круглый магнит 10×2 мм, а в ячейках доски стояли герконы. Как видно из схемы выше, всё это подключалось к Ардуино и в принципе могло вполне быть протестировано отдельно от остального робота, что было удобно. Да, кстати, я использовал ROS (Robot Operating System) для связи разных частей робота – было очень удобно в плане коммуникации.

Доска: слева первый вариант с довольно тупыми конусами, которые себя не оправдали, справа – окончательный вариант с напаянными поверх основы более острыми конусами. У фигур тоже конус имел обе части – тупую и острую
Доска: слева первый вариант с довольно тупыми конусами, которые себя не оправдали, справа – окончательный вариант с напаянными поверх основы более острыми конусами. У фигур тоже конус имел обе части – тупую и острую

Хотя я и говорил раньше про основание робота, на самом деле, это было скорее основание торса. Мне нужно было что-то, что бы объединяло доску и торс. Для этого я купил старую подставку на колёсах от ЭЛТ-телевизора. У этой штуки было два разных уровня (вероятно, один из них для видеомагнитофона), что мне отлично подходило. Самый верхний уровень я отвёл под доску, а вот на уровень пониже прикрепил деревянный ящик, внутрь которого должен был встать управляющий комп (не судьба), а сверху я поставил торс робота.

Робот на теле подставке. Ящика пока ещё нет, торс стоит на компе, который должен был управлять системой
Робот на теле подставке. Ящика пока ещё нет, торс стоит на компе, который должен был управлять системой

Но это было позже, а до этого я продолжил работу над рукой. Желая, чтобы она была максимально похожей на оригинал, я повторял хотя бы примерно пропорции и форму, что налагало некоторые ограничения. Например, плечевая кость была сильно больше размеров поля моего принтера, и ее пришлось «сваривать» из многих частей. С этой самой костью произошёл забавный, но неприятный случай. Как-то раз я разобрал руку и сняв её с робота, оставил на столе. Жаркое испанское солнце нагрело черный пластик, и когда я вернулся к работе, оказалось, что плечо имеет уже совсем не ту форму, которую я задумывал. Пришлось греть феном и исправлять.

Пострадавшая деталь. PLA, ну фу таким быть! А ещё я поместил сюда подвижную систему координат X1Y1Z1, чтобы лучше объяснить актуацию руки
Пострадавшая деталь. PLA, ну фу таким быть! А ещё я поместил сюда подвижную систему координат X1Y1Z1, чтобы лучше объяснить актуацию руки

Чтобы сымитировать плечевой сустав достаточно, чтобы в нём было 2 степени свободы, про один актуатор (подъём руки над доской), я сказал. Он вращает сустав вокруг оси Y1. Второй расположен непосредственно в плече, он поворачивает руку вокруг Z1. Испанское солнце поворачивает руку вокруг X1. Далее на плечевой кости располагаются «бицепс» и «трицепс», как у настоящего Т-800. Активным из них является «трицепс», он и разгибает, и сгибает руку в локте. Впрочем, «бицепс» не является только лишь муляжом – в нём установлена пружина, которая компенсирует люфты механизма.

Мускулатура «киборга-убийцы»
Мускулатура «киборга-убийцы»

Пойдём дальше по руке. За локтем у нас идёт предплечье, где в самом основании расположен следующий актуатор, поворачивающий руку в запястье. Это уже знакомая нам серва MG90S. Разумеется, непосредственно на неё нельзя повесить всё предплечье – она чрезвычайно хилая, поэтому конструкция вращается вокруг оси (видимой на картинке выше), посаженная на пару подшипников. В такой конфигурации серве хватает мощи, чтобы вращать предплечье/запястье. А дальше… актуаторов нет. Ну, вернее, почти нет. Дальше у меня стоял только актуатор захвата, но на кинематику руки он не влиял. Меня спросят – а как же это будет работать с четырьмя степенями свободы, если в человеческой (и, я подозреваю, что в терминаторской тоже) руке их аж семь, не считая пальцев?! А фигово это будет работать. Но будет. Зато примитивно просто в управлении и конструкции.

Что же до захвата, то сначала я не очень представлял как его осуществить, думал делать хотя бы один реально двигающийся палец. Но такая система точно бы не отличалась стабильностью, и на выручку пришли магниты. Наверху каждой фигуры вклеивался маленький магнит, что-то вроде 3×6 мм, а в полом большом пальце робота ходил вверх-вниз магнит помощнее, 6×20 мм, который мог стабильно удерживать в воздухе любую фигуру. Как происходило расцепление, если магнит был постоянным? Его просто втягивала тросиком внутрь пальца ещё одна серва MG90S, расположенная в районе локтя.

Тут я понял, что мои фигуры придётся переделывать. Во-первых, я их уже напечатал без пазов под магниты. А во-вторых, когда я начал проводить первые эксперименты с подъёмом руки, я понял, что часть моих фигур – слишком высокие и робот просто не сможет поднять их достаточно высоко, чтобы перенести через другие фигуры на поле или наоборот – не сможет перенести другие фигуры через них. Я имею в виду всё, что выше пешки. Да и пешки можно было уменьшить. В результате под замену пошло всё, кроме коней, им я просто отрезал верхушку (которой у них, кстати, и не должно было быть – её я присобачил туда для механического захвата) и вклеил магнит. Таким образом, я сделал фигуры трёх разных высот: самые мелкие – пешки, чуть выше – ладьи, кони и слоны, а самые высокие, естественно – ферзь и король. Разница в высоте, правда, была незначительной – около 5 мм между каждой ступенью.

Фигуры: слева – было, справа – стало
Фигуры: слева – было, справа – стало

Изменения так же коснулись и расположения доски. Оказалось, что рабочая зона робота меньше, чем доска. Ну, я ж дурной и вообще никаких прикидок не делал. Но выход я нашёл – поставил доску на две мебельные линейные направляющие и стал двигать её в зависимости от того, где находится нужная клетка. Доска имела всего два положения – ближнее и дальнее, и управлялась связкой из Atmega8 и ULN2003. Контроллер принимал на вход 0 или 1 и переводил доску в нужную позицию.

Привод доски. Мотор снят с какого-то древнего сканера, ремень оттуда же. А вот справа видна жёлтая коробка – это интерфейс взаимодействия с пользователем. Туда было можно ввести положение фигур (если играем не с начала) и объявить об окончании твоего хода. Спойлер – коробка потом сдохла, и я обходился без неё
Привод доски. Мотор снят с какого-то древнего сканера, ремень оттуда же. А вот справа видна жёлтая коробка – это интерфейс взаимодействия с пользователем. Туда было можно ввести положение фигур (если играем не с начала) и объявить об окончании твоего хода. Спойлер – коробка потом сдохла, и я обходился без неё

❯ Немного о приводах и управлении

Помимо упомянутых серв, все остальные моторы, которые были использованы – шаговые. Сначала была идея попробовать сделать что-то вроде сервопривода, но после нескольких неудачных попыток я пришёл к выводу, что не осилю. Шаговые, напротив, я уже более-менее освоил. На обоих плечевых степенях свободы трудились б/у двигатели из принтеров и сканеров, а вот в «трицепсе» стоял новый моторчик, который ранее предназначался для врачебного девайса для урологов, который я пытался делать будучи аспирантом в Севастополе. Девайс не удался, а мотор остался. Моторчик очень узкий, но длинный и момент у него был довольно приличным для его размеров. Вообще, думаю, это единственный более-менее интересный актуатор в роботе. Он, понятное дело, линейный, оснащён одним концевиком и винтом М4. Всё это располагалось в теле «гидроцилиндра», которое было сделано из фотобарабана лазерного принтера. В штоке «гидроцилиндра» помещалась гайка. Шток не фиксировался от проворота ничем, если не был прикреплён к локтю.

Обработка узла крепления мотора «трицепса» на самодельном фрезерном станке с ЧПУ. Видно мотор «трицепса», зажатый в тисочках, тоже самодельных
Обработка узла крепления мотора «трицепса» на самодельном фрезерном станке с ЧПУ. Видно мотор «трицепса», зажатый в тисочках, тоже самодельных

Привод подъёма руки был выдран из какого-то видеомагнитофона, изначально там стоял коллекторный мотор, который я, как уже было сказано, заменил шаговым. Мотор крутил червяк, который входил в зацепление с колесом, на котором, в свою очередь, сидела шестерня с модулем 1 на 8-10 зубов, не помню. А эта шестерня вращала большое колесо на 100 зубов, которое и приводило в движение вал руки. Привод был самотормозящимся, поэтому в случае отключения питания проблем не имел. Второй плечевой привод включал довольно слабый шаговик из старого сканера вместе с редуктором, от которого дополнительным ременным приводом шла понижающая передача на поворот руки. Причём чтобы мотор сильно не грелся, я прицепил на него радиатор с северного моста какой-то материнской платы. Это, конечно, изврат, но работало.

Слева – привод подъёма руки (поворот вокруг Y1), справа – поворота (не хватает ступени с ремнём, она снята) вокруг оси Z1
Слева – привод подъёма руки (поворот вокруг Y1), справа – поворота (не хватает ступени с ремнём, она снята) вокруг оси Z1

На каждом приводе стояло по одному концевому выключателю, чтобы определять начальное положение и от него затем отсчитывать текущую позицию. Итого, у меня было три шаговика с тремя концевиками. Чем же это всё удобно управлять? Мне, как человеку уже построившему пару 3D принтеров, ответ был очевиден – связкой RAMPS 1.4 – Arduino Mega. На плате RAMPS есть также достаточно выходов под сервомоторы, что удобно. Итого, в состав робота, включая доску входило две ардуины (это если не считать сдохшей жёлтой коробки). Питалось всё это добро от старого ATX-блока питания – их у меня было в достатке.

В качестве компьютера, гоняющего Ubuntu и ROS, предполагалось использовать старый ПК на Pentium 4, собранный из универовского мусора. Однако, это было бы, в случае успешного завершения проекта. Поэтому до стационарного выделенного специально ПК дело не дошло, и я использовал свой ноутбук. Конкретно версии Ubuntu и ROS я не помню, да это и не важно. Код узлов, я тоже думаю, особого смысла нет приводить, только опишу в целом как всё работало. Для этого посмотрим на то, что выводит rqt_graph.

Овалы – это узлы (nodes), а прямоугольники – темы (topics)
Овалы – это узлы (nodes), а прямоугольники – темы (topics)

Наверное, начать лучше всего с доски. Это узел /ard_1 работает, как это подразумевает название, на Ардуине Nano, что в доске. Я уже говорил, что это устройство не делает различий между фигурами и шлёт сообщение в тему /board примерно такого содержания: 1111111111111111000000000000000000000000000000001111111111111111 (если это начальная позиция). Более понятно это выглядит так:

Изменение поля после двух первых ходов
Изменение поля после двух первых ходов

Ардуина шлёт сообщение при любом изменении в этой матрице. Это нужно для определения хода и человека, и робота. С человеком понятно – роботу надо знать, куда он походит, а ход робота надо определять, чтобы быть уверенным, что робот таки смог передвинуть фигуру(ы) правильно. Анализом положений доски занимается узел /move_reader. Он слушает ещё и тему /move_finished, куда идут сообщения о завершении хода. Узел работает следующим образом. В нём есть список состояний доски, опустошаемый при завершении хода. Эти позиции анализируются по количеству состояний доски, по количеству фигур и по изменению их положений. Например, есть два состояния и количество фигур одно и то же. Это может быть обычный ход, скажем e2e4, если мы видим, что одна из фигур теперь стоит в другом месте, а может быть игрок просто поднял и опустил фигуру в том же месте (чего, кстати, делать нельзя). Или, например, три состояния: первое – исчезает одна фигура; второе – исчезает вторая фигура; и третье – фигура появляется в том же месте, где раньше одна исчезла. Это значит, что кто-то кого-то сожрал.

Результат выдаётся в обычном шахматном формате (как пример – тот же е2е4) в тему /move_seen. Эту тему слушает «мозг» всего робота – /ai_chesster. Именно тут находится ИИ, который и решает, куда будет ходить робот. В качестве ИИ используется вяленая ры��а популярный шахматный движок stockfish. У этого узла есть две дополнительные функции. Первая – проверить, что ход человека правильный, и вторая (читерская) – подсказывать мне лучшие ходы (лошадью ходи, век воли не видать!). Подло? Зато аутентично – человечество победило потому, что ему помог Т-800. Где бы был без него этот ваш Джон Коннор? Да, и я не прикидываюсь хорошим игроком и не тешу себя надеждой рыбку обыграть своими силами. Зачем я вообще сделал такую функцию, если, по сути, робот играет сам с собой? В основном, для тестирования. Сложность я бы потом подстроил, а вначале хотелось попробовать длинные партии, чтобы убедиться в правильной работе машины. Играл бы сам – партии были бы короткими, и Т-800 таки заборол бы человечество в лице меня.

Узел /ai_chesster пишет в две темы: /current_board_position и /robot_move. Обе они слушаются узлом /robot_move_translator, основная задача которого – определить, какие действия надо проделать роботу, чтобы физически осуществить ход на доске. Для этого надо знать и ход, и «видеть» доску (в /current_board_position позиция записывается в стандартной шахматной нотации Форсайта – Эдвардса). После чего определяется последовательность действий руки, которая передаётся по одному движению далее в тему /move_to_make. Когда механика осуществила это движение, сообщение об этом принимается из темы /robot_finished и передаётся команда на следующее действие. Когда последовательность закончится, узел рапортует об этом в /move_finished.

А дальше следует самая тупая часть моего проекта – узел /move_processor. Почему? Сейчас расскажу. Эта штука непосредственно командует второй Ардуиной (узел /ard_2) через тему /robot_data. Здесь петля, подобная предыдущей – Ардуина получает команду, исполняет, рапортует в /result, получает следующую. А тупость в том, как задаётся команда. Я ведь не стал делать кинематическую модель робота. Мне стыдно за это, но тогда я просто не знал, как это сделать. Вместо этого я просто составил три таблицы в MS Excel 8×8, где лежали команды для перемещения руки на заданную клетку. И координаты в этих командах я задавал вручную. Да, 64 клетки в каждой из трёх таблиц (192 позиции) я задавал вручную. А самое замечательное – при малейшем повреждении робота, его ремонте, длительном простое, изменении погоды на Марсе – эти координаты сбивались. И приходилось задавать всё заново. Пару часов каждый раз. Это –фиаско.

Теперь объясню немного подробнее, почему три таблицы. Опять же из-за того, что нет кинематической модели. Это для трёх положений фигур на/над каждой клеткой – полностью поднятое для переноса, полностью опущенное и поднятое так, чтобы нижний конус фигуры был на пару миллиметров выше отверстия клетки. Зачем так? Потому, что в силу устройства руки, при опускании и поднятии, фигура не движется строго вертикально. Значит, надо задать несколько точек, чтобы фигура точно встала на место (это особенно важно при опускании). Минимальное количество этих точек в траектории – 3, отсюда и количество таблиц.

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

В целом, на этом можно закончить объяснения логики работы системы. Единственно, что ещё забыл упомянуть – так как жёлтая коробка сдохла (этот узел имел прозаическое название /yellow_box), то сообщение в тему /move_finished о завершении хода человека я каждый раз писал в терминал сам вместо того, чтобы на кнопку жать.

❯ Работало ли всё это?

Да, работало. В первый раз я его почти довёл до рабочего состояния во времена морового поветрия, но к сожалению, робот потерпел крах. Его случайно толкнула жена и, так как центр тяжести у него был смещён назад, он просто завалился.

Крах-тарарах!
Крах-тарарах!

Исправлять надо было много чего, в том числе устойчивость, для чего крестовина с колёсами была повёрнута на 90 градусов. Однако времени у меня уже было не особо много – сначала я уехал на стажировку в Рим, потом была активная работа над завершением диссертации и её защита. В результате, робот пережил переезд, и вот когда я сидел без работы, ожидая постдок, я занялся им снова, и именно тогда я и переписал почти весь код до того вида, в котором он описан выше, так как не мог понять ничего из того, что вроде бы работало раньше.

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

На этом проект завершился, после чего робот был разобран, осталась только пластиковая черепушка.

Принц мудатский и бедный робот:  «Я знал его, Горацио…»
Принц мудатский и бедный робот: «Я знал его, Горацио…»

Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале 

Перед оплатой в разделе «Бонусы и промокоды» в панели управления активируйте промокод и получите кэшбэк на баланс.
Перед оплатой в разделе «Бонусы и промокоды» в панели управления активируйте промокод и получите кэшбэк на баланс.
Близкое по теме: