Как мы делали робота-футболиста

25 ноября 2012 года в Таллинне проводилось крупнейшее в Балтии соревнование роботов — «Роботекс». Мы решили построить робота в категории профессиональный футбол. Конечно, это будет не Криштиану Роналдо, но вызов интересный. Я опишу детали создания и программирования робота. Имя его — Палмер.

Сам футбол проходит на площадке зеленого цвета, на котором расположены 11 оранжевых мячиков для гольфа. Имеются ворота, 15 см высотой и примерно 37 см шириной, желтые у одной стороны и синие с другой. Робот должен искать мячи на поле, захватывать их, выбирать нужные ворота и забивать. На поле находятся два робота. Побеждает тот, кто забьет больше мячей. Технические требования к роботу: цилиндр высотой 35 см и диаметром 35 см. Все просто.

После обсуждения деталей и пары ящиков пива пришли к такой конфигурации. На борту будет стоять материнская плата mini-формата с процессором Атом. Плюсы — не требуется охлаждение и отдельное питание, компактность. Минусы соответственно в невысокой производительности. Изображение захватывается камерой от Sony Playstation 3, идеальная камера по цене и качеству. Критичным является частота кадров, так как от нее зависит максимально возможная скорость робота. Допустим, при частоте 30 кадров в секунду и скорости робота 3 метра в секунду он будет проезжать между двумя кадрами 10 см, что явно недостаточно для точности захвата мяча. PS3 выдает до 125 кадров в секунду. Драйвер камеры хорошо вписывается в ядро Linux. Операционная система Ubuntu с загрузкой по USB. Для распознавания образов используется любимая OpenCV.

Помимо камеры для исследования окружающего мира используются ИР-датчики и маяки. Инфракрасные датчики позволяют избегать столкновений с другим роботом или воротами. Питание — литиевый аккумулятор, с понижением питания с 14.8V to 12V для материнской платы. Питание для моторов LiPo аккумуляторы (2x 4S 14.8V 2200mAh + 2x 2S 7.4V ~2000mAh). Отдельное питание для моторов используется потому, что при старте моторов происходит сильное падение напряжения в цепи, что в свою очередь может сбрасывать микроконтроллер. Да и отдельное питание позволяет убрать высокочастотный шум от моторов, что так же сбивает микроконтроллер. В цепи стоят два типа конденсаторов, одни сглаживают падения напряжения, другие, более быстрые, сглаживают высокочастотный шум. Широкополосный шум возникает в процессе искрения щеток мотора, который, проходя по цепи, сбивает микроконтроллеры. Для решения этой проблемы применяется H-Bridge с оптическими прерывателями. H-Bridge — это реле-мост, схема которого позволяет менять полярность тока на моторах без риска короткого замыкания. Сигналы подходящие к мосту проходят через оптические прерыватели. Оптические прерыватели разрывают сеть, и шум от моторов не попадает в цепь контроллера. Состоят из светодиода и фотоэлемента в одном корпусе, т.е. цепь разомкнута, но сигналы идут. Такие мосты применяются для управления чем угодно. Платы для моста делаем сами.

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

image

Далее в комплекте идут электролитические конденсаторы для стабилизации напряжения, и керамические конденсаторы и ферритовые кольца для борьбы с вездесущим шумом, ибо шумит ВСЕ. И остаются такие мелочи как рама, колеса, моторы, болты и прочие винтики. А вот начало.

image

И через несколько дней.

image

Механика и электроника собирались в режиме нон-стоп, иногда работали по ночам. Код начал писать параллельно, используя С++ и в качестве среды разработки Qt. Робот — это классический абстрактный автомат, у которого есть набор состояний (мяч найден, движение, поиск ворот, или цель найдена, ракета наведена), причем неважно, военный робот, игрушечный или промышленный. Проблема состоит в том, что состояний должно быть так мало как только возможно, и так много, как необходимо. Если алгоритм делать слишком запутанным, то в какой то момент не будешь понимать, почему робот реагирует именно так. У нас состояний 8: Стартовое, Поиск Мяча, Поиск Ворот, Прицеливание, Избегание препятствий, Заряд конденсаторов соленоида, Удар, Конечное. Переходы между ними образуют граф, который и является алгоритмом.

Больше всего времени уходит на написание и доводку кода, тестирование, калибровку. Что на самом деле и есть самое главное.

Распознавание робота выделенное в отдельные классы, строится так. Каждый кадр проходит обработку, где сначала конвертируются цвета из RGB в HSL, которое более близко к нашему восприятию, и с которым удобнее работать. Для удобства конвертации используется не встроенная функция OpenCV, поскольку конвертация — это вычисления и на них тратится такое дорогое время, а заранее вычисленная таблица цветов (lookup table), где из RGB значение получается смещение в таблице, а после делается выборка цвета по адресу. Выигрываем в скорости, проигрываем в памяти, все как в теории. Далее последовательно ищутся объекты (мячи, ворота) и записываются в список. Объекты ищутся по общему алгоритму, пробегается в цикле каждый пиксель, и если он попадает в диапазон цвета объекта, то на карте ставится бит. В итоге получается битмап-карта с выделенными объектами. Битмап-карта отправляется на вход OpenCV функции, которая выдает обратно список контуров. Далее находим площадь контуров и если площадь контуров больше 40-50% от площади круга (прямоугольника) или в диапазоне 4/Pi, то считаем этот объект распознанным и добавляем его в список. Шары ищутся в некоем диапазоне (маленькие шум, больших не бывает, на потолке тоже смысла шары искать нет). Поскольку камера выдает до 125 кадров в секунду, использовать некоторые встроенные функции OpenCV нельзя, они долгие, но библиотека устроена удобно и через указатели можно пробегать по всей матрице. Осталось сделать проверку того, не выкатился ли мяч за край поля (черным ограничено), поскольку робот не должен выезжать за черную линию. Проверка достаточно проста, чертим линию из центра нижней части изображения до мяча и смотрим, не пересекает ли она черную область. Если пересекает, то контур из списка выкидывается.

Дальше — самое интересное. Робот имеет определенное количество состояний, в которые он переходит в зависимости от условий. Это просто. Алгоритм пишется именно на этом этапе. Самое сложное — это калибровка. Как из полученных объектов и их координат выстроить функцию скорости, направления?

Пробегаем весь выданный список и находим самый большой мяч по площади. Это самый близкий. Теперь, чтобы из координат объекта получить функцию скорости и направления, требуется подумать и покурить матан. Чем выше координаты мяча на изображении и чем он меньше по площади, тем он дальше. Чем более сдвинут по оси X и дальше/ближе, тем более острый, или наоборот тупой угол. Чтобы получить коэффициенты, ставится робот на площадку в один конец по центру, дальше начинается процесс ползания с рулеткой, измерения точек с неким шагом (33 см) и снятием показаний значений объекта в системе распознавания (площадь контура). Наносим значения и пытаемся найти функцию, которая была бы связью одних значений с другими. Точность сильная не нужна, поскольку робот не строит путь раз и навсегда, а корректирует себя 17-18 раз в секунду, столько выдает наша маленькая система. Т.е. надо найти функцию, предел которой стремится к искомым результатам при небольших изменениях аргументов. Далее на колеса подается угол и направление, откуда скорости вычисляются простейшими векторными уравнениями. Рисунок объяснит.

image

Далее, когда мы умеем двигаться к объектам, алгоритм игры в футбол написать не так сложно. А вот уже близко к соревнованиям. Мой справа.

image

Результат в действии:



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

Самое главное, что невозможно все просчитать, и упор делается на тестирование. Кто дольше тестирует и доводит, тот и главный. Допустим, повороты лучше делать не всем роботом, а робот должен вращаться вокруг мяча, т.к. при вращении робота мячу добавляется импульс вращения робота, и если на близких дистанциях можно бить с упреждением, и ошибка несущественна, то при ударе с дальних дистанций ошибка огромна, линейная скорость ворот относительно робота большая, и момент стрельбы должен быть еще больше упреждающим. Тут вылезают проблемы. Первая, это то, что ты не знаешь, какая скорость поворота была у робота до этого. То есть если робот едет под углом упреждения прямо на мяч, то он ударит сразу и мимо, поскольку не имел вращения. Или наоборот — подъедет к мячу с поворота в другую сторону, начнет поворачиваться и ударит, но это будет мимо, поскольку из-за инерции его скорость поворота еще не будет расчетной. Т.е. слишком много вариантов, которые надо просчитать. Поворот вокруг оси мяча не добавляет ему импульса вращения, и можно стрелять сразу.

Второе — это проблема с распознаванием. Когда робот крутится, на дальних дистанциях мячи и ворота имеют опять таки большую линейную скорость, и кадр на распознавание идет смазанный. Функция поиска контуров работает по градиентам, но смазанные ворота не имеют четких градиентов, и поэтому вместо одного контура ворот на выходе получаются или десятки контуриков (это ест ресурсы) или ничего не получается (мяч размазывается в маленький оранжевый туманчик). Я имел на входе 17 кадров в секунду, соответственно дальние объекты при вращении для меня были недоступны. Плюс задержка по процессингу. Т.е. когда робот понимает, что вдалеке были ворота, их уже там нет (правда, это я и использовал в свою пользу, когда давал вращение от своих ворот, и задержка как раз была такая, что мой робот поворачивался почти к вражеским воротам). Ультрабук на голове робота решил бы проблемы.

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

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

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

Второй мое упущение — это то, что я не знал, что стартуют роботы с правого угла. Робот должен помнить, в какой стороне ворота противника и куда он должен поворачиваться, иначе неправильный оборот берет много времени. Я определял стороны ворот по цвету, но пока ворота не появились в поле зрения, переменная-множитель направления (плюс или минус один задает сторону поворота) по умолчанию принимала значение -1 против часовой стрелки, а надо было по часовой. И из-за этого в проигрышном матче первые два мяча наш забил на противоходе и потерял время. Итог 6-4, а во втором ничья 5-5, и наш проигрыш. 5 место из 18 команд. Мешал еще высокий центр тяжести, не поставить большую скорость — начинает танцевать. Я прозвал его принтер.

Вообще, здесь очень много нюансов. Что запомнилось — так это интересная тусовка. И ритм. Т.е. скорость и постоянная доработка машин. После каждого матча. С чемпионом мы сыграли 4-3! (тактика защиты, закрыли ворота и били издалека). Первый матч один на один мы провели на соревнованиях! Отсюда невозможность оттестировать стратегию поведения. В течении недели нас преследовали поломки. Плюс у нас камера сбилась (ось) я пытался решить проблемы механики кодом, чего никогда нельзя делать, но времени не было, и только перед последним матчем я все решил. Всего мы сыграли 4 матча.
В первом победили робот-кубик.

image

Во втором выиграли команду Скайпа, у которых был очень интересный робот. Безумно быстрый, маленький, с 8 камерами и FPGA! То есть они сделали то, что вообще не должно было бы работать. Он быстро вылетел, но был очарователен. Вот он.

image

Были очень интересные решения. Робот, занявший первое место (3 год дорабатывался) имеет обзор 360 градусов. Камера смотрит наверх на конусообразное зеркало. Получается картинка в полярных координатах.

image

А по поводу все просчитать, есть такая история в анналах «Роботекса», над которой все постоянно смеются.

Как-то лет 5 назад пришли на соревнования два магистра и сказали, что они все все просчитали и построили робота. Они были встречены взрывом хохота. И последующим поражением.

Спасибо за внимание.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 19

    +1
    Круто!

    p.s. а почему 'быстрый и маленький, с 8-мью камерами с FPGA' не должен был работать?
      0
      Во первых, применение 8 камер само по себе ставит задачу огромной сложности, поскольку необходимо каким либо образом интегрировать информацию поступающую с них в единую модель. Камеры должны быть идеально откалиброваны, чтобы не решать проблемы механики кодом. К примеру каждая камера имеет свои искажения. Первое — это то, что оптическая ось не располагается по центру матрицы. Невозможно установить линзу так, чтобы оптическая ось располагалась точно по центру, сама линза на будет паралелльно матрице. Сама матрица также имеет некоторый угол (мельчайшие неровности клея, плюс сам клей на который сажают чип может играть при засыхании). Все это ставит сложности в использовании многих камер. Но для робота, который имеет большую скорость процессинга большой точностью можно пренебречь, поскольку распознавание и корректировка идет не один раз, а много раз в секунду.
      Во вторых, как реализовать распознавание на FPGA, это реальный вызов поскольку там меняется логика работы принципиальной схемы.

        0
        Я прекрасно понимаю — FPGA это реально вызов, но о сложностях калибровки и центрирования я не согласен. Конечно, если строить алгоритм, основываясь на утверждении что все камеры идеально расположены и искажения идентичны, но это глупо. Калибровку проводить всеравно придется!

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

        p.s. Интересно, ребята с FPGA выложили в публичный доступ свои алгоритмы?
          0
          Да, все верно. Плохо то, что каждую камеру легко сбить, может возникнуть необходимость менять камеру. Решать проблемы с перекрывающимися полями.
          Насчет доступности решения на FPGA в открытом доступе, я ничего не слышал.
      0
      --на соревнования два магистра

      Mагистра чего? Магии?

      А почему не сделать удаленное вычисление на внешнем сервере? Или правила запрешают?
        0
        Магистры Electrical Engineering, Computer Science, не могу точно сказать, потому что это уже из разряда уже легенд.

        Вычисления на внешнем сервере запрещают правила. Кстати, эта проблема часто встречается при проектировании дронов. То есть, если мы ставим основную систему на сам дрон, то он заметно утежеляется за счет аккумуляторов и веса самих компонентов, и как результат уменьшается время полета. Можно проводить все вычисления на внешней системе, которая стоит на земле. Дрону требуется лишь быстрый канал связи. К примеру, в Европа вся покрыта вышками мобильной связи, и у нас в принципе есть канал связи. Плюсы — облегчение и увеличение времени полета дрона, возможность реализовывать сложные вычисления. Минусы — зависимость от канала связи, и как результат возможность потери дрона, если связь пропадет.

        В лаборатории Таллиннского Технического Университета проектировали систему для дронов, на OpenCV, которая бы по CornerPoints отслеживала бы обьекты. Грубо говоря берем с Гугл-карт изображение вбиваем, даем GPS координаты и дрон летает вокруг и снимает. У них возникли проблемы с производительностью, поскольку изначально была выбрана неверная архитектура. На борту паралелльно шла запись видео, его сжатие, плюс распознавание, которое ест ресурсы, вдобавок ко всему отсылка видео, не помню уже по какому каналу. Как результат 10 фпс, что совершенно неприменимо для дрона.
          0
          Too late… Deleted…
          0
          Спасибо за статью! Не могли бы вы, пожалуйста, более детально рассказать об ударном механизме на основе соленоида и конденсаторов для большого импульса? Зачем нужны конденсаторы, в них накачивается большое напряжение, или это для того, чтобы не перегружать аккумулятор большим током?
            +2
            Конденсаторы используются для получения импульса большой мощности, как в фотовспышках. Импульс идет на катушку и индуцированное магнитное поле выталкивает стержень. Чем больше импульс, тем сильнее импульс получает стержень. Мы экспериментировали с количеством конденсаторов, оптимальное количество шесть штук, к сожалению параметры уже не помню. Если взять больше, то увеличивается время заряда конденсаторов, ток сильно нагревает провода и реле. Вот собственно реле HFKW и конденсаторы.

            image

            image

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

            Здесь детально все описано.
              0
              Спасибо! А саму катушку вы наматывали самостоятельно? И что у вас в качестве ударного стержня? Он в конце удара как-то останавливается?
                +1
                Нет, катушку откуда-то принес один из наших механиков. В качестве стержня используется стальной цилиндр, происхождение его тоже загадка. Мы нашли его, когда копались в куче всякого хлама. Для возврата стержня используется пружина, которая держит стержень с одной стороны.
                  0
                  Т.е. получается, что при выстреле на цилиндр одновременно действуют две силы — магнитный толчок вперед и нарастающая обратная сила, вызванная растяжением пружины?
                    +1
                    Да, все верно.
            0
            Еще интересно, вы еще будете участвовать в последующих соревнованиях?
              0
              Я думаю, что когда-нибудь да. И основной интерес это взаимодействие между роботами. Стратегии и обмен информацией.
                +1
                Я вот думаю по поводу роботов — а что если в качестве захвата использовать пылесос? Были ли такие решения? Или не хватит мощности? При использовании пылесоса мяч будет выравниваться идеально перед выстрелом, да и захват возможен с некоторого расстояния.
                  0
                  Теоретически да. Но во первых пылесос это устроиство большой массы и размера, и к примеру трудно решить проблему переключения между режимами всасывания и удара. Иначе же потоки воздуха будут отклонять мяч.
              +1
              Интересно, а наработки потом как-нибудь используются, или же это все остается на уровне соревнований?
                0
                Некоторые наработки используются для распознавания образов. Я собираюсь подробнее написать об этом статью позже.

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое