10 KiB
id | title |
---|---|
o2ac-repo-review | Команда o2ac есть чему поучиться |
Предыстория
Команда O2AC на World Robot Summit 2020 Assembly Challenge состояла из представителей OMRON SINIC X , OMRON , Osaka University, National Institute for Advanced Science and Technology (AIST) и Chukyo University.
Репозиторий который недавно был выложен на платформу GitHub данной командой, является их открытым исходным кодом, где представлено множетсво полезных решений в области автоматизированной сборки робототехническим сборочным комплексом. Их решение сводилось к полной автоматизации заранее заданной происзводственной операции. Итак рассмотрим основные фичи, которые были продемонстрированы этой командой
- Всё програмное обеспечение строилось на основе ROS Kinetic в Docker контейнере
- Используются одновременно 2 робота-манипулятора без риска столкновения
- Вставка детали в отверстие производится с помощью контроля импеданса
- Выравнивание детали производится за счёт сестемы технического зрения на библиотеке OpenCV
- Планирование следующего дейтсвия выполняется в момент выполнения траектории роботом-манипулятором, что оптимизирует общее время выполнения операции
- Автоматизированное закручивание винтов
- Используется собственно разработанный инструмент для затягивания винтов
- Обнаружение и захват деталей расположенных в лотке неструктурировано
- Для установленных деталей используется библиотека TF которая содержит локальную систему координат каждого установленного элемента
Обзор репозитория
Репозиторий состоит из 19 пакетов, в том числе есть пакеты которые достойны рассмотрения для реализации нашего Робосборщика. Кратко пройдёмся по каждому из них.
aist_modules
Данный пакет является метапакетом и разрабатывался членами команды из университета AIST. Он включает себя пакеты для 3D локализации и калибровки камер. Данный пакет можно рассмотреть в качестве альтернативы, но на сегодняшний момент возможно найдутся и другие пакеты которые справятся лучше.
o2ac_assemble_database
Данный пакет содержит базу данных, а также функции загрузки сборок в сцену планирования MoveIt.
Загрузка данных для сборки производится за счёт Python скрипта parts_reader.py
который загружает объекты в сцену как объекты с коллизией из исходных .yaml
файлов в папке o2ac_assembly_database/config/name_of_config/
. Также в данной базе данных присуствует информация о позиционировании захватного устройства, при захвате детали. Все эти данные загружаются непосредственно на сервер ROS откуда они уже забираются определённой нодой. Такая архитектура свойственна для ROS1, для ROS2 подход координально отличается, потому что параметры загружаются в ноду непосредственно при её запуске.
Если предыдущий скрипт брал геометрию каждой детали и публиковал их в сцену MoveIt, то следующий скрипт Assembly_reader.py
предназначен для обработки древовидной сборки и публикацию данной сборки в TF формате. То есть прямым образом заносит информацию на сервер какая деталь куда должна устанавливаться. Отдельно интересует данный фрагмент кода:
def get_frame_mating(self, base_object, child_object):
'''
Эта функция возвращает сопряжение двух деталей в сборке в виде сообщения geometry_msgs / Transform.
Вход 'base_object' - это строка, определяющая имя объекта, на который будет помещен дочерний объект.
Вход 'child_object' - это строка, определяющая имя объекта, который будет помещен в базовый объект.
Возвращает None, если между двумя объектами не определено сопряжение или объекты не являются частью загруженной сборки.
'''
base_object_id = next((part['id'] for part in self._parts_list if part['name'] == base_object), None)
child_object_id = next((part['id'] for part in self._parts_list if part['name'] == child_object), None)
transform = next((mating_transform for mating_transform in self.mating_transforms if int(mating_transform.header.frame_id.split('_')
[1]) == base_object_id and int(mating_transform.child_frame_id.split('_')[1]) == child_object_id), None)
if transform is not None:
frame_mating = get_transform(parent_frame=base_object + '/' + '_'.join(transform.header.frame_id.split('_')[2:]),
child_frame=child_object + '/' + '_'.join(transform.child_frame_id.split('_')[2:]),
transform=transform.transform)
return frame_mating
else:
return None
То есть данный фрагмент кода в соостветсвии с полученной базой данной последовательности сборки проверяет что куда устанавливать, выходом данной функции соответствует переменная frame_mating
которая "судя по всему" является фреймом стыковки двух деталей.
Так как же обрабатывается последовательность сборки двух деталей. Об этом нам скажет следующий фрагмент скрипта:
def get_assembly_tree(self, collision_objects=[]):
'''
Возвращает цель сборки в виде древа преобразования TF
'''
self.mating_transforms = self._read_frames_to_mate_csv()
if not self.mating_transforms:
rospy.loginfo("No assembly tree defined")
return False
base_id = int(self.mating_transforms[0].header.frame_id.split('_')[1]) # Имя фрейма - "part_NN _...""
base_name = next((part['name'] for part in self._parts_list if part['id'] == base_id), None)
base_object = next((collision_object for collision_object in self._collision_objects if collision_object.id == base_name), None)
assembly_tree = self._collision_object_to_tf_tree(base_object)
for mating_transform in self.mating_transforms:
child_id = int(mating_transform.child_frame_id.split('_')[1])
child_name = next((part['name'] for part in self._parts_list if part['id'] == child_id), None)
child_object = next((collision_object for collision_object in self._collision_objects if collision_object.id == child_name), None)
tree_2 = self._collision_object_to_tf_tree(child_object)
mating_transform.header.frame_id = mating_transform.header.frame_id
mating_transform.child_frame_id = mating_transform.child_frame_id
self._add_part_to_assembly_tree(assembly_tree, tree_2, mating_transform)
return assembly_tree
То есть после загрузки данных о деталях как последовательность сборки, формирутеся древо преобразований TF, в котором содержится информация о том что где должно стоять. Также есть интересная функция, которая непосредственно отвечает за добавление одной последовательности в другую
Следующий скрипт visualise_metadata.py
предназначен лишь для визуализации объектов в сцене.