Разработка манипулятора для игры в шахматы
Мы с моими одногруппниками любим поиграть в шахматы. Но из-за того, что живем мы далеко друг от друга, то поиграть вживую получается нечасто и приходится довольствоваться онлайн приложениями. По этой причине я и мой одногруппник Михаил Крахотин решили собрать манипулятор, способный определять, захватывать и переставлять шахматные фигуры.
Идея
Мы решили создать 5 осевой манипулятор с классическим захватом, который будет анализировал фигуры на доске, а затем принимать от нас команды – какую фигуру куда поставить, после чего хватать фигуру и переставлять. Такой манипулятор не требует фиксированного места для шахматной доски или жесткой привязки позиций фигур – можно использовать произвольную доску и фигуры любого размера. Это открывает перспективы использования манипулятора в домашних условиях: можно поставить его на любое свободное место, поиграть, а потом убрать, не переживая о повторной калибровке. Работу над проектом мы решили разбить на несколько задач:
Распознавание типа фигуры и ее цвета
Сегментация фигуры
Моделирование манипулятора
Определение координат фигуры и движение манипулятора в заданную точку
Далее о них подробнее.
Распознавание типа фигуры и сегментация
Для распознавания классификации фигуры мы используем свёрточную нейронную сеть, которая хорошо справляется с данной задачей. В первую очередь мы составили датасет, который использовали для обучения и проверки нейронной модели. Датасет состоит из 6 классов, каждый из которых соответствует конкретной фигуре (Bishop, King, Knight, Queen, Rook, Pawn).
Для определения цвета фигуры, а также сегментации, используем встроенную цветовую модель OpenCV – HSV, которая работает с цветовым тоном, насыщенностью и значением, представляющим яркость относительно насыщенности цвета. Для определения к какому типу относится фигура (светлая, темная), были заданы верхние и нижние пределы значений (upper, lower). После чего созданы две маски, которые состоят из изображения, переведенного в HSV, и значений upper и lower. Каждая маска будет рассматривать изображение в своем диапазоне цветов: первая в диапазоне белого, вторая в диапазоне черного. Посчитав количество пикселей для каждого изображения и взяв их среднее значение, определяем, какой является фигура, светлой или темной. Этот способ не идеален, но он работает.
После цвета фигуры (светлая, темная), создаем маску, которая сможет выделить фигуру на изображении. Полученную маску используем для получения контура изображения. Из данного контура берем координаты для рамки и определения центра фигуры.
Выбор ПО
ROS
Для начала хотелось бы сказать о том, что было принято решение использовать ROS для реализации управления манипулятором. ROS предоставляет удобные инструменты для реализации симуляции и визуализации робота. Однако в первую очередь он привлекает тем, что можно использовать чёткую и структурированную систему обмена данными через топики. Была использована версия ROS Noetic, поскольку она является последней версией ROS 1, и не было необходимости переходить на ROS 2.
Симулятор
В качестве симулятора был выбран Gazebo. Несмотря на некоторые недостатки, Gazebo хорошо интегрируется с ROS и имеет большое сообщество пользователей, что сыграло решающую роль в выборе этого симулятора.
MoveIt
Для того чтобы манипулятор двигался в точку, нужно решить задачу инверсной кинематики, то есть мы задаем положение конечного эффектора (захвата), а программа должна вычислить положения каждого сустава, чтобы робот мог достичь цели. Решение этой задачи описано для тривиального случая, когда манипулятор движется в одной плоскости и у него всего два сустава. В нашем случае все куда сложнее, поэтому я решил прибегнуть к фреймворку MoveIt, который позволяет как задавать положения суставов напрямую, так и просто задать целевую точку роботу.
Выбор железа
Механическая часть
Корпус был куплен на AliExpress. К нему там же заказаны 6 сервоприводов MG996R с металлическими шестеренками и моментом 11 кг*см. Однако при первых же испытаниях заметили, что при небольшой нагрузке моторы уходят в свое крайнее положение и там клинят. В причине этого так и не получилось разобраться, пришлось купить новые сервоприводы TD8120MG уже на 20 кг*см. Они работают гораздо лучше, почти не греются и хорошо держат нагрузку.
Камера глубины
Для измерения глубины был использован Kinect v1 для Xbox 360. Это не самый оптимальный выбор из-за низкой точности, но других доступных вариантов не было. Сенсор глубины имеет разрешение 320x240 при 30 кадрах в секунду, а RGB камера - 640x480 с аналогичной частотой кадров.
Камера и датчик расстояния
Простая и очень дешевая камера, которая должна быть закреплена на роботе - DEXP Live DCM138 с HD разрешением. Датчик глубины VL53L0X способен измерять расстояние от 30 до 2000 мм с погрешность 3%.
Нижний и верхний уровень
В качестве контроллера для управления сервоприводами использовали Arduino Uno, а для верхнего уровня - ноутбук с установленной Ubuntu 20.04 Desktop.
Моделирование манипулятора
Модель создавалась с помощь URDF описания робота. На описании подробно останавливаться смысла нет, оно довольно простое: с помощью макросов Xacro были определены размеры звеньев и их ориентация в пространстве, заданы углы поворота суставов. Для визуального отображения робота используется лишь простая геометрия.
Теперь необходимо было создать конфигурацию для работы MoveIt. Для этого был использован удобный ассистент с графическим интерфейсом. В нем было настроено начальное положение манипулятора, конечный эффектор и параметры коллизии.
Затем написали контроллер для публикации данных о положении манипулятора из Gazebo, а также файл запуска для него. Теперь робот спавнится в симуляторе, после чего можно задавать его целевое состояние через Rviz, и он будет двигаться в Gazebo.
Почти готово, осталось добавить описание камер в файл с роботом. Ранее я упоминал, что используется и камера глубины, и обычная камера, и отдельный лазерный дальномер. Это было сделано с целью реализации двух алгоритмов, о которых чуть позже. Для этого просто изменили URDF файл, добавив описанные выше сенсоры после описания основного робота.
Реализация с помощью камеры и дальномера
В попытке реализовать захват фигуры было решено сначала немного упростить себе задачу. Для этого закрепили обычную камеру и лазерный дальномер на захвате робота. Алгоритм предельно прост: нужно совместить центр распознанной фигуры с центром изображения с камеры. Так как центр камеры совпадает с центром захвата, то получится, что захват по двум осям наведется на искомый объект. Для этого просто нужно поворачивать нижний сустав, а также верхний. Затем получаем расстояние до объекта, и если бы мы условились, что объект находится на полу, то есть его высота всегда нулевая, то можно было бы по теореме Пифагора рассчитать расстояние, которое нужно двигаться до цели. Но такого условия не было, а значит необходимо сделать преобразование координат и двигаться вдоль оси эффектора в его же системе, а затем произвести преобразование к базовой, тем самым получив искомую точку, после чего можно генерировать траектории и начинать движение.
Практическая реализация выполнена на питоне и довольно простая: робот становится в некую начальную позицию, наводится по 2 осям, затем шлет в топик сигнал, что наведение завершено, после чего вторая нода уже производит преобразование координат, планирование и движение.
Реализация с помощью камеры глубины
Здесь дело обстоит немного интереснее. Так как камера имеет диапазон измерений от 50 см, а также она довольно большая и громоздкая, было принято решение подвесить ее на расстоянии 100 см над уровнем пола под углом в 60 градусов. Теперь мы можем определить координаты объекта с помощью формулы, связывающей фокусное расстояние , центр изображения камеры , координаты пикселя , а также дистанцию от камеры до объекта.
Стоит помнить, что эти координаты получены в системе камеры глубины, и для задания целевой точки захвата необходимо сделать преобразование координат. В итоге робот перемещается к целевой точке, как и ранее, с помощью Moveit. Для того, чтобы избегать препятствия была добавлена карта занятости, построенная с помощью Octomap и показанная ниже.
Практическая реализация
После успешного выполнения задачи в симуляторе, было решено собрать и протестировать его в реальных условиях. Для управления сервоприводами написан код для Arduino, использующий библиотеку rosserial и данные, которые публикуются в топик joint_states, отвечающий за углы поворота узлов робота. Затем был установлен kinect и откалиброван манипулятор, после чего успешно протестировано движение к точке. Однако при финальном тестировании выяснилось, что точность реальных данных значительно отличается от тех, которые были получены в симуляторе. Из-за этого робот часто промахивался, задевая или проходя мимо фигуры. Скорее всего это связано с недостаточным разрешением камеры для данной задачи и слишком маленькими шахматными фигурами.
Заключение
Хотя в симуляторе и были получены удовлетворительные результаты, в реальности итог можно назвать провальным. Чтобы исправить это планируется приобрести RGBD камеру Intel Realsense для более точного определения координат фигуры и провести тесты робота с более крупными фигурами. Стоит отметить, что сейчас реализована лишь часть функционала. В дальнейшем необходимо добавить распознавание шахматной доски и возможность послать команду роботу через Telegram-бота поставить фигуру на определенную клетку доски.