Проект реализует управление по камере грузовым роботом с возможной поддержкой нескольких роботов для перевозки грузов из одной зоны в другую
Мы калибровали камеры с помощью шахматной доски. (файл colibr.py) Чтобы обнаружить узор на шахматной доске, можно использовать функцию cv.findChessboardCorners(). Для этого необходимо указать, какой узор мы ищем, например, сетку 8x8, 5x5 и так далее. В данном примере мы будем использовать сетку 6x8. (Обычно шахматная доска состоит из 8x8 квадратов, что соответствует 7x7 внутренним углам.) Функция возвращает координаты угловых точек и значение retval, которое будет равно True, если узор успешно обнаружен. Угловые точки будут упорядочены слева направо и сверху вниз. Далее мы получаем коеффиценты с помощью функции cv2.calibrateCamera, откалибровываем методом cv2.undistort.
За определение зон отвечает функция get_zones. На вход подаётся изображение, а на выходе алгоритм получает словарь контуров, где ключами являются цвета (red, white, blue). Значения соответствующие ключам - списки контуров определенного цвета. Так как get_zones тратит много ресурсов компьютера во время цикличного вызова, а зоны и ракурс камеры статичны, имеет смысл создавать снимок зон заранее. Калибровка зон проводится при освящении выше среднего, и при отсутствии всех грузов/иных объектов на рабочем пространстве. Выполните следующую команду, чтобы создать снимок:
python dumb_zones()Скрипт создаст файл zones_info.pkl, который в дальнейшем будет использоваться основной программой для разметки зон. Зоны размечаются по внутреннему контуру, а не по внешнему, так как для точного построения маршрута данный метод подходит лучше
Первым шагом является создание маски, которая включает в себя только цвет заднего фона рабочего пространства. Для подавления шумов маска проходит процедуру медианного блюра, именно медианного, обычный блюр не подойдет, так как размоет в том числе контуры.
mask = cv2.inRange(rgb, cfg.BACKGROUND_COLOR_RANGE_BOUND['lower'], cfg.BACKGROUND_COLOR_RANGE_BOUND['upper'])
mask = cv2.medianBlur(mask, cfg.BLUR_SIZE)
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
contours = tuple(filter(lambda x: cfg.CONTOUR_SIZE_FILTER_RANGE[0] < cv2.contourArea(x) < cfg.CONTOUR_SIZE_FILTER_RANGE[1], contours))С помощью маски весь цвет заднего фона на изображении заменяется на черный цвет.
image[mask > 0] = (0, 0, 0)Далее следует апроксимация контуров. Так как мы ищем прямоугольники, чтобы уменьшить количество вершин найденных контуров мы проводим процедуру апроксимации, исключая возможные недочёты контура.
for i, contour in enumerate(contours):
contour_length = cv2.arcLength(contour, True)
epsilon = contour_length * cfg.APPROX_COEFFICIENT
approx = cv2.approxPolyDP(contour, epsilon, True)
approx_zones.append(approx)
for approx in approx_zones:
if len(approx) == cfg.VERTEXES and is_angles_straight() and len(get_zone_color_if_inner()) != 0:
filtered_zones.append(approx)
zone_color = get_zone_color_if_inner()
if len(zone_color[(cfg.WHITE_ZONE_COLOR_RANGE_BOUND['lower'] <= zone_color) & (zone_color <= cfg.WHITE_ZONE_COLOR_RANGE_BOUND['upper'])]) == 3:
zones['white'].append(approx)
elif len(zone_color[(cfg.RED_ZONE_COLOR_RANGE_BOUND['lower'] <= zone_color) & (zone_color <= cfg.RED_ZONE_COLOR_RANGE_BOUND['upper'])]) == 3:
zones['red'].append(approx)
elif len(zone_color[(cfg.BLUE_ZONE_COLOR_RANGE_BOUND['lower'] <= zone_color) & (zone_color <= cfg.BLUE_ZONE_COLOR_RANGE_BOUND['upper'])]) == 3:
zones['blue'].append(approx)Результат после сортировки
Задания приходят с сервера, ip адрес, которого задан в файле .env. Модуль task.py анализирует полученное задание и в соответствие с результатом анализа запускает определённую инструкцию выполнения задания.
Получив изображение с камеры, url адрес, которой задан в файле config.py, программа ищет на изображении арукомаркеры функцией get_all_arucos. Далее следует определение границ грузов, положений целевых грузов и робота. Построение маршрута происходит по методу "A*". По построенному маршруту строится сплайн. Сплайн - более удобный в работе, так как маршрут представляется не пикселями, а векторами. Это позволяет сглаживать траекторию движения робота.
Перед роботом создаётся точка, которая при помощи pd регулятора стремится к линии сплайна. Также, для повышения стабильности, скорости моторов меняются в зависимости от кривизны сплайна.

