Первоначально, OMower разрабатывался под простые интерфейсы управления pfodApp и Modbus. Первый — это текстовый протокол высокого уровня, в котором передаются менюшки и управляющие команды, а второй — известная, но не слишком удобная в данном применении вещь, так как требует от управляющей программы постоянно опрашивать состояние всех используемых датчиков «вручную». Поэтому, было принято решение постепенно переходить на ROS (Robot OS), широко используемый фреймворк для управления различными роботами.
На данный момент, поддержка ROS находится в начальной стадии, включая в себя только передачу информации от датчиков в виде простых массивов (без использования специализированных форматов сообщений, предлагаемых многими библиотеками ROS), отладочного лога и управляющих потоков команд в формате pfodApp/Modbus, без возможности реально управлять роботом стандартными средствами ROS. То есть, чтобы сдвинуть робота с места или изменить какую-либо внутреннюю настройку робота — вы должны будете отправить на него текстовую команду в формате pfodApp. Но даже в таком усеченном виде — можно легко транслировать и записывать происходящее с роботом, визуализируя его движения в стандартных средствах ROS (rviz), а также добавлять сервисы для дополнительных функций. Такие, например, предоставляемая omower_seeker.py возможность езды в направлении визуального шаблона (шахматной доски), для точного заезда на парковочную станцию.
На картинке нарисованы потоки данных в роботе. Основные сервисы ROS исполняются на Orange PI Zero, воткнутой в специальный разъем на плате робота (на тестовой машинке для этого используется Raspberry PI3, соединенная аналогичным способом — через последовательный порт). Через интерфейс rosserial — робот передает в ядро ROS сообщения от датчиков (такие, как /imu/orientation или /motors/PWM), свой отладочный лог в текстовом формате и вывод меню/сообщений в формате pfodApp или Modbus, принимая поток текстовых команд или Modbus-запросов. От двух дополнительных Raspberry PI Zero приходят потоки картинок с камер, но как показала практика — получить нормальной синхронизации для обработки стерео-изображений при такой схеме нельзя (качество видно на картинке внизу), поэтому скоро будет произведена замена на нормальную стереокамеру.
Степень интеграции ROS в OMower будет постепенно расширяться, вплоть до предоставления полного доступа ко всем внутренним переменным робота и возможности управлять им через стандартные средства ROS (типа cmd_vel-сообщений, задающих требуемую скорость движения).
Расскажу немного поподробнее про модуль omower_seeker.py, как пример использования ROS для добавления функций в OMower. Его назначение довольно простое — ехать в направлении шахматной доски, корректируя свой маршрут в реальном времени. Эта функция будет использоваться для заезда газонокосилки на парковочную станцию, где он может быстро заряжать свои аккумуляторы. Анализируя изображение с одной из камер — модуль вычисляет два угла (угол отклонения доски от центра камеры и угол поворота самой доски относительно перпендикуляра) и передает их в виде текстовой команды внутреннему модулю seeker (omower-seeker.h/cpp в OMower SDK).
Внешне это выглядит довольно простой задачей, но в реальной жизни возникает серьезная проблема — скорость обработки изображений на встроенном в робота микрокомпьютере. Как показывает практика, скорость поиска шаблонов в opencv на изображении при использовании относительно маломощных Orange PI и Raspberry Pi — очень невысокая и нестабильная, занимающая от десятков до сотен миллисекунд при разрешении 640x480, что во время езды превращается в отклонения от необходимого маршрута, так как робот, даже со своей невысокой скоростью движения, успевает за это время повернуться на существенный угол или проехать относительно большую дистанцию. Собственно, поэтому и была выбрана шахматная доска c минимумом клеток, так как другие шаблоны отнимают еще больше времени.
Чтобы компенсировать большое время поиска визуального шаблона, применяется схема с использованием компаса — микроконтроллер робота сохраняет его значения каждые 100 миллисекунд, храня пять отсчетов за последнюю половину секунды (более продолжительные анализы просто отбрасываются, в виду их малой пригодности для точной навигации). Вычисленные углы от omower_seeker.py (который также передает микроконтроллеру и время поиска шаблона) — пересчитываются в реальный угол поворота, с использованием сохраненного значения компаса, отстоящего от времени поиска не более чем на 100 миллисекунд, а уже по этому углу робот и едет. Это позволяет более-менее точно ехать в направлении шахматной доски по прямой. Или, если она немного повернута относительно перпендикуляра — по дуге, корректирующей угол приближения так, чтобы он был максимально близок к оси шаблона, так как нам нужно не просто подъехать к доске, но и попасть в направляющие полозья и подключиться к контактам зарядки.
Полный алгоритм заезда на станцию реализуется в три этапа. На поле по GPS задаются две точки — стартовая (где-то в середине рабочей области), и точка перед станцией, а также угол поворота к станции. После того, как робот приедет от стартовой точки до второй и повернется на нужный угол в сторону шахматной доски на станции — вступает в дело модуль seeker, корректируя обороты моторов через PID-регулятор. Если какой-то из этапов не прошел, либо углы отклонения превышают заданные значения — робот отменяет заезд и снова возвращается в стартовую точку.
Ссылки и видео:
→ OMower SDK, библиотека для Arduino IDE и принципиальная схема с разводкой платы
→ Готовая прошивка с использованием SDK, реализующая как pfodApp/Modbus, так и подключение к ROS
→ Пакет omower_gateway для ROS
Автор: vasimv