Skip to content

Repository files navigation

Проект команды "Секундочку"

Проект реализует управление по камере грузовым роботом с возможной поддержкой нескольких роботов для перевозки грузов из одной зоны в другую

Калибровка камеры

Мы калибровали камеры с помощью шахматной доски. (файл 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 регулятора стремится к линии сплайна. Также, для повышения стабильности, скорости моторов меняются в зависимости от кривизны сплайна.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Contributors

Languages