На настоящий момент мы знаем уже достаточно много о ROS. Мы понимаем,
что такое рабочее пространство, что такое ROS-пакеты. Мы умеем создавать
узлы ROS, умеем программировать издателей и подписчиков и связывать их
через систему сообщений ROS. Также мы знаем ещё один механизм связи в
ROS – сервисы. Мы познакомились с сервером параметров ROS и со средством
журналирования ROS. Также на одном из уроков мы работали с симулятором
черепашки – мобильного псевдоробота.
Пришла пора познакомиться с системой симуляции Gazebo и
симулятором реального мобильного робота, вернее, целого семейства
роботов – TurtleBot3. Этим мы и займёмся сегодня.
6.2 Немного о симуляторах
роботов
Некоторое время назад мы с вами работали с симулятором черепашки –
однако, тот симулятор можно назвать симулятором очень условно. Там не
было ничего, кроме движения некоего подобия мобильного робота в
ограниченном краями окна пространстве, и всё это работало без учёта
того, что наша жизнь – это физика не меньше, чем математика. У черепашки
не было окружения, в котором она движется, её “колёса” не
проскальзывали, да и колёс у неё не было, на её движение не влияло
трение, этот список можно продолжать, но не нужно. Нужно перейти к среде
Gazebo – отличному инструменту симулирования роботов с очень мощным
физическим движком, который может помочь разрабатывать вам проекты без
использования реального оборудования, при этом, результат будет очень
похож на то, что происходит в реальной жизни.
В принципе, моделирующие системы – очень полезная штука. Вы можете
спокойно разрабатывать программное обеспечение для робота, находясь
дома, вам не нужно занимать очередь на эксперимент в лаборатории, если
робот один, а желающих несколько. Более того, вы можете разрабатывать
роботы, которые в принципе не могут работать в земных условиях – космические манипуляторы,
например.
В принципе, такой способ создания программного обеспечения для роботов
сейчас является доминирующим. Вы можете спокойно разрабатывать и
отлаживать свои программные модули, запуская робот в симуляторе, а затем
передавать их для подключения в некий общий программный продукт.
Немаловажным плюсом разработки в симуляторе является и защита
повреждения оборудования в случае ошибок в коде, которые неизбежно
возникнут на этапе разработки. Конечно, нужно учитывать, что мы не можем
создать идеальную симуляцию реальных роботов в реальной среде, но в
большинстве случаев нам будет достаточно такой не совсем совершенной
симуляции.
Итак, что такое Gazebo? Gazebo – это система симулирования, которая
может моделировать не только кинематику робота, но и его массы, силы и
моменты инерции, воздействующие на робот, скорости, ускорения и тому
подобное. Также Gazebo – это ещё и немножечко редактирование окружающей
среды, средство 3D-визуализации и другие функции, с которыми мы
постараемся сегодня познакомиться. Знакомится с Gazebo мы сегодня будем,
моделируя работу мобильного робота TurtleBot3. TurtleBot3 – это
семейство мобильных роботов, которое включает в себя “Бургер” и “Вафлю
Пи”.
6.3 Установка
ROS-пакета TurtleBot3 не по написанному
Давайте перейдём по адресу TurtleBot3 в интернете, который я уже
указывал выше и найдём там в меню пункт 6. Simulation и далее
пункт 6.1 Gazebo
Simulation.
Здесь мы видим инструкцию по установке пакета симуляции, которая
предлагает нам сначала настроить наш компьютер для того, чтобы он был
готов к установке симуляционного пакета, а затем склонировать сам пакет
в наше рабочее пространство ROS.
Хорошо, давайте попробуем воспользоваться apt-ом и
установить то, что нам предлагают в пункте меню 3.1 PC
Setup. Так как Ubuntu и ROS у нас уже установлены, начнём с
пункта 3.1.3. Кстати, не забудьте сверху выбрать версию ROS Noetic,
иначе симулятор не будет работать.
Итак, в пункте 3.1.3 нам предлагают установить пакеты, от которых
зависит работа нашего симулятора и это мне категорически не нравится.
Зачем нам в системе пакеты, которые мы не будем использовать в
дальнейшем, так как у нас нет “железного” TurtleBot3 и его симуляция
нужна только в качестве учебного пособия на пару часов? Они нам не
только не нужны, они могут ещё и привести к проблемам зависимостей
Ubuntu.
Что же я предлагаю сделать? Вы, вероятнее всего, слышали про так
называемые программные виртуальные машины – программы, эмулирующие
аппаратное обеспечение компьютера на другом компьютере. Это хорошее
решение для экспериментов над операционными системами (естественно,
применение виртуальных машин гораздо шире, но сейчас нас интересует
только эта возможность), но уж больно велики “накладные расходы” –
фактически, мы должны отнять у хоста, основной машины, на которой мы
работаем, часть памяти, часть процессорной мощности и часть дискового
пространства без гарантии того, что мы всё это будем использовать. Есть
ещё вариант – развёрнутая на нескольких компьютерах “среда
виртуализации” Proxmox VE, к виртуальным машинам которой можно
подключаться с помощью браузера, но в этом случае тоже есть проблемы,
большинство из которых общие с проблемами виртуальной машины на вашем
рабочем компьютере. Не будем говорить о том, что у вас должен быть
доступ к “среде виртуализации”, это очевидно. При установке симулятора
TurtleBot3, да и любого другого ROS-пакет, с которым мы хотим
познакомиться, нам потребуется установить в виртуальную машину ОС
Ubuntu, ROS, настроить рабочее пространство и тому подобное, то есть,
повторить урок 1 нашего курса как минимум.
Фактически, сейчас мы поняли, что нам нужно. Нам нужна возможность
установить некое приложение со всеми зависимостями в Linux так, чтобы
быть располагать всеми возможностями, которое нам даёт ядро операционной
системы, но при этом изолироваться от файловой системы. Если вы дадите
такой запрос поиску Гугла, где-то на первой странице выдачи вы
наткнётесь на chroot – возможность “подмены” корня файловой системы, а
там уже один шаг до “виртуализация
на уровне операционной системы” и наиболее популярной его реализации
на данный момент – Docker.
6.3.1 Контейнеризация с
помощью Docker
Для самостоятельного изучения Docker я бы рекомендовал начать со
статьи “Docker
самый простой и понятный туториал. Изучаем докер, так, если бы он был
игровой приставкой” Если говорить совсем кратко, Docker позволяет
нам создавать образы Docker Images, которые мы можем переносить с одного
компьютера на другой и запускать их без необходимости устанавливать
какое-либо дополнительное программное обеспечение, кроме Docker. Эти
образы прежде всего нужны для того, чтобы мы могли отдать разработанное
нами приложение заказчику, который просто запустит экземпляр этого
образа без необходимости задумываться о том, все ли зависимости есть у
него в системе, с помощью средств Docker.
С установки Docker мы и начнём.
К сожалению, мы не можем установить GUI-приложение Docker Desktop, так
как оно требует Ubuntu версии не ниже 22.04, у нас установлена версия
20.04, которая требуется для ROS Noetic. Значит будем устанавливать
средства Docker с CLI-интерфейсом по инструкции.
Добавим официальный ключ Docker:
Если мы всё сделали правильно, получим такой вывод в терминал:
Теперь давайте загрузим готовый образ и посмотрим, что с ним можно
делать. Для загрузки готового образа используем команду docker
pull <имя образа>. Загрузим образ Ubuntu 23.10, например:
docker pull ubuntu:23.10
В имени образа можно проследить некоторую систему – две части имени
разделены двоеточием, слева от которого непосредственно имя образа, а
справа так называемый тег – метка, помощью которой можно различать
версии образов. Хорошо, если у нас есть интернет, образ Ubuntu 23.10
загружен. Проверим для надёжности ещё и с помощью субкоманды
images:
Отлично, у нас есть образ Ubuntu 23.10 размером 71.1 МБ, что совсем не
много, теперь хотелось бы запустить Ubuntu 23.10 на нашем Ubuntu 20.04.
Если говорить корректно, то мы должны запустить Docker-контейнер –
запущенный в Docker экземпляр образа. Для запуска контейнера
предназначена субкоманда run формата docker run
<имя образа> [<команда, которая выполняется в
контейнере>]. Поприветствуем себя из контейнера, запустим
контейнер командой:
docker run ubuntu:23.10 echo 'hello from ubuntu 23.10'
Что у нас получилось? Мы запустили контейнер, получили в терминал
надпись “hello from ubuntu 23.10” и снова находимся в своём
приглашении терминала. Здорово, но непонятно, как нам это может помочь с
симулятором Turtlebox3, если мы даже в командную строку в контейнере не
попали. Давайте доберёмся до командной строки. У docker
run мы можем посмотреть справку с помощью ключа –help, как
делали раньше для команд ROS, я её посмотрел, и ответственно заявляю,
что если мы запустим контейнер с ключами -it
(интерактивный режим с псевдотелетайпом) и выберем /bin/bash в качестве
командной оболочки:
docker run -it ubuntu:23.10 /bin/bash
Теперь мы видим приглашение суперпользователя на компьютере со
странным именем из цифр и букв, но всё ещё не можем быть уверены, что
работаем в какой-то изолированной среде. Давайте посмотрим список
каталогов, найдём домашний и выведем его содержимое на экран. Вы умеете
это делать. __ У меня получилось вот так:
Очевидно, что это файловая система не нашего компьютера. Уже хорошо, а
теперь давайте узнаем версию ОС, в которой мы работаем. Подадим команду
lsb_release -a Неожиданно нам ответили ”bash:
lsb_release: command not found”_. То есть, команды в системе нет, что
неудивительно, если вспомнить крошечный размер образа. А давайте
попробуем её установить:
apt-get update &&apt-get install -y lsb-release &&apt-get clean all
И ещё раз:
lsb_release-a
Теперь завершим работу оболочки и тем самым выйдем из контейнера, подав
команду exit и повторим запуск контейнера и вновь подадим
команду lsb_release -a, после чего вновь увидим “bash:
lsb_release: command not found”. Всё правильно, мы запустили новый
экземпляр контейнера из образа, в котором нет
lsb_release. Вопрос, если в виртуальных машинах мы
могли один раз всё установить и пользоваться, ну а если ОС пришла в
негодность, удалить её и установить всё заново, то тут мы должны
устанавливать всё, кроме ОС, при каждом запуске контейнера? И ответ на
это – да. Неожиданно обидно… было бы, если бы не одно “но”. Мы должны
устанавливать в контейнере всё, что нам понадобилось, если этого нет в
образе, но! Но мы можем сами создавать образы с нужными нам наборами
программ, используя файлы Dockerfile – конфигурационные файлы,
описывающие пошаговое создание среды вашего приложения.
Давайте напишем Dockerfile, в котором уже будет установлен
lsb_release. В домашней папке создадим каталог
dockerfiles, перейдем в него и создадим каталог turtlebot3, перейдём в
свою очередь в этот каталог и создадим файл Dockerfile со
следующим текстом:
FROM ubuntu:23.10
RUN apt-get update && apt-get install -y lsb-release && apt-get clean all
ENTRYPOINT [ "lsb_release" ]
CMD [ "-a" ]
Разберём текст файла. Директивой FROM мы определяем
образ, который будем использовать в качестве базового. Здесь мы взяли
тот, с которым работали ранее.
Директива RUN нам нужна, чтобы запустить в образе
какую-либо команду. Здесь мы используем команду установки пакета
lsb_release. Обратите внимание, что последовательность
команд apt начинается с подкоманд
update и upgrade, а заканчивается
подкомандой clean. Рекомендуется так делать всегда при
использовании команд apt в Docker-файле в директиве
RUN. Директив RUN, кстати, в одном
файле может быть несколько.
Последними идут директивы управления выполняемыми в контейнере
командами, фактически, это директивы запуска вашего приложения. Здесь
директива ENTRYPOINT задаёт приложение, которое мы
хотим запустить, а директива CMD – параметры этого
приложения.
Давайте теперь для создания нашего образа подадим команду
docker с субкомандой build с
параметрами:
docker build . --tag myubuntu
Точка здесь – это путь к Dockerfile, так как мы запускаем команду
постройки образа из каталога с Docker-файлом, здесь можно обойтись
точкой, как обозначением текущего каталога. Ключ –tag
даёт нам возможность дать имя нашему образу.
Мы построили образ и можно запускать контейнер. Но прежде, чем запускать
контейнер, давайте посмотрим список контейнеров, который хранит Docker.
Их мы можем запустить снова по идентификатору контейнера. Это удобно
тогда, когда мы используем отлаженный образ, но для нас сейчас это
приведёт к размножению остановленных контейнеров, на которые Docker
тратит ресурсы. Подадим команду docker с субкомандой ps
и ключом -a, чтобы Docker показал нам не только те
контейнеры, что сейчас выполняются docker ps -a и
ужаснёмся:
Чтобы удалить все запущенные контейнеры, подадим команду
docker container prune и далее, чтобы автоматически удалять
контейнер после запуска, будем использовать ключ –rm, а
ключи -it и оболочку мы использовать не будем, так как
выполнять команды в контейнере вручную нам не понадобится. Давайте
запустим контейнер:
docker run --rm myubuntu
Отлично, мы создали образ, запустили контейнер и получили результат.
Кстати, если мы сейчас запустим контейнер с параметром
–help, то получим подсказку по команде
lsb_release, так как параметр –help
будет подставлен в команду вместо параметра по умолчанию, который мы
задали директивой CMD.
docker run --rm myubuntu --help
Здесь я отмечу только, что связь директив ENTRYPOINT и
CMD довольно сложная, и при написании собственного
Docker-файла надо разобраться, что вы хотите сделать и что вы написали в
файле.
6.3.2. Создание образа
для симуляции TurtleBot3
Прежде чем переходить к созданию образа, давайте разберёмся, зачем
нам нужен Docker.
Симуляция TurtleBot3 требует установки большого количества пакетов
ROS, Gazebo и других зависимостей. Установка всего этого “напрямую” в
нашу систему возможна, но имеет свои минусы:
Можно легко “замусорить” систему лишними библиотеками.
Возможны конфликты версий (например, если вы работаете с разными
версиями ROS).
Нелегко делиться таким окружением с другими или переносить его на
другие компьютеры.
Docker позволяет изолировать всё необходимое для симуляции в
отдельном образе , который можно легко запускать,
копировать и передавать другим, не затрагивая основную систему. Это
удобно как для обучения, так и для разработки.
Теперь, зная это, приступим к созданию Docker-образа для симуляции
TurtleBot3.
Удалите Dockerfile из каталога turtlebot3 и создайте его заново со
следующим текстом:
Наш Docker-файл сталь больше и в нём появились новые директивы,
первая из которых WORKDIR. Эта директива даёт указание
на рабочий каталог, который должен использовать Docker при постройке
образа на данном этапе, так называемом слое. О слоях и кэшировании
образов можете прочитать самостоятельно в статье, которую я приводил
ранее. Так вот, каждая из директив – это слой построения, скажем сейчас
так, хотя это не совсем правильно. И каждый слой, задаваемый директивой
RUN “не помнит”, что было на предыдущем таком слое, то
есть, если вы подали команду смены директории в директиве
RUN, то в следующей директиве RUN это
никак не отразиться, мы опять будем в корне файловой системы или
каталоге, назначенном директивой WORKDIR.
Вторая директива – COPY. Директива копирует файл из
файловой системы хоста в файловую систему контейнера. Также надо
отметить команду git clone системы управления версиями
Git. Эта команда загружает из
git-репозиториев необходимые нам для симуляции TurtleBot3 проекты. Git –
мощная и сложная система, которая заслуживает отдельного курса. Если
есть желание, можно потренироваться в
интерактивном курсе или почитать учебник. В наших
занятиях мы в основном будем пользоваться лишь возможностью загрузки из
уже созданных репозиториев.
Давайте теперь разберёмся, что в этом файле написано и как это
соотносится с инструкцией, с которой мы и начинали установку симулятора
TurtleBot3 в этом уроке. Как мы и говорили, сперва надо подготовить
компьютер в соответствии с п. 3.1. Пойдём по шагам:
Шаг 1. Нам предложили установить Ubuntu.
Шаг 2. Нам предложили установить ROS.
За эти два шага в Docker-файле отвечает строка
FROM osrf/ros:noetic-desktop-full
Здесь мы берём готовый образ Ubuntu 20.04 с установленным ROS Noetic
и строим свой образ на его основе. Шаг 3. Нам предлагают установить
пакеты, от которых зависят пакеты TurtleBot3, выполнив команду
apt-get (apt и
apt-get сейчас мы будем считать одной и той же
командой, хотя они имеют некоторые отличия). Мы используем для этого
директиву RUN, директиву выполнения команды Linux, в
которой не забываем каждое использование подкоманды
install предварять подкомандами update
и upgrade. Кроме зависимостей мы также устанавливаем
git, чтобы потом склонировать пакет симуляции. Для
того, чтобы установка выполнялась автоматически, без вопросов в
процессе, с подкомандой install используем ключ
-y. Обратный слэш в конце строки показывает, что
команда не прерывается, а продолжается на следующей строке.
Теперь переходим к установке симулятора. Для установки симулятора мы
должны выполнить следующие действия. Перейти в каталог /src
рабочего пространства, скачать
ветку noetic-devel из репозитория, вернуться в корневой
каталог рабочего пространства и построить его. Давайте, кстати, перейдём
по этому адресу. Мы попадём в репозиторий симулятора TurtleBot3 на GitHub, в котором находятся файлы
симулятора для различных версий ROS, подробный файл с описанием
симулятора, интерфейс, позволяющий, в котором мало что понятно, кроме
возможности скачать этот репозиторий в виде архива. GitHub, если вы о
нём не знаете, можете воспринимать как некий облачный диск,
ориентированный на работу с ним через утилиту git. На
самом деле, как мы видели, и без использования git он может принести
достаточно пользы.
Хорошо, репозиторий склонирован и мы должны вернуться в корень рабочего
пространства и построить его. Для построения рабочего пространства
используется команда catkin_make, а не catkin build,
как мы привыкли, – это макрос для сборки рабочего пространства, который
не требует установки catkin tools, но обладает меньшей
функциональностью.
cd ~/catkin_ws/src/git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3_simulations.gitcd ~/catkin_ws &&catkin_make
Перепишем это с помощью директив Docker.
Для начала используем директиву изменения рабочего каталога
WORKDIR, которая не только даст нашим нижележащим
директивам команду работать с каталогом /home/catkin_ws/src, но
и создаст его, если он не существует. Дальше мы запустим команду
клонирования, а после этого снова изменим каталог, чтобы построить
рабочее пространство и подадим команду
catkin_make.
Команда catkin_make у нас выполняется через вызов
bash для того, чтобы предварить её загрузкой настроек
среды (точкой можно подменять команду source), делать
так приходится, так как в образе команды запускаются не в оболочке,
соответственно, настройки ROS команда catkin_make не увидит.
WORKDIR /home/catkin_ws/src
RUN git clone https://github.com/ROBOTIS-GIT/turtlebot3_simulations.git
WORKDIR /home/catkin_ws
RUN /bin/bash -c '. /opt/ros/noetic/setup.bash; catkin_make'
Далее мы должны:
отправить настройки рабочей среды в .bashrc,
скопировать файл скрипта в образ, который будет запускать симулятор
в контейнере,
сделать скрипт исполняемым,
настроить вход в контейнер на запуск этого скрипта, который выполнит
roslaunch с нужными параметрами,
и дать по умолчанию параметры для roslaunch. Вот
так мы это сделаем:
Хорошо, представление о Docker-файле мы получили, теперь построим
образ:
docker build --no-cache . --tag turtlebot3
Возможно, вы заметили ключ –no-cache. Я использовал
его для подстраховки, ведь сейчас мы работаем в том же каталоге и Docker
может решить, что это тот же самый файл, что мы использовали ранее, и
начать его кэшировать. Слои и кэширование – это замечательное умение
Docker, про которое, как я говорил ранее, вы можете прочитать сами.
Скажу только, что Docker не строит образ “с нуля”, если есть такая
возможность, а использует построенные ранее варианты образа для
ускорения. Скорее всего, всё прошло бы корректно, но я однажды запутал
Docker или запутался сам, поэтому решил проявить осторожность. Что это
там у нас в выводе? Ошибка:
В этом месте мы копируем файл launch.sh в образ, но там, откуда
мы его копируем, этого файла нет. Фактически, этот файл для нас
автоматизирует пункт 6.1.2
Launch Simulation World. В каталоге turtlebot3 создадим файл
launch.sh, текст которого ниже. С первого взгляда текст этого
скрипта может вызвать у вас недоумение, так как это явно не текст на
питоне. Совершенно верно, это bash-скрипт, скрипт, который позволяет
автоматизировать выполнение команд оболочки Linux. О том, что
интерпретировать скрипт будет bash, нам говорит шебанг. Строки ниже я
постарался подробно прокомментировать:
#!/usr/bin/env bash# Скрипт для запуска launch-файла симулятора TurtleBot3# На вход могут быть поданы два параметра:# -- мир, в котором работает робот - параметр $1,# -- тип робота - параметр $2.# Мир может быть задан тремя способами:# -- empty - пустой мир,# -- turtle - мир в виде логотипа TurtleBot3,# -- house - мир с обставленным домом.# Роботов может быть два типа:# -- burger,# -- waffle.# Загрузить настройки ROS и рабочего пространства. /opt/ros/noetic/setup.bash. /home/.bashrc# Вывести сообщение, какой мир для какого робота мы запускаемecho"Launching $1 world for $2 bot"# Зададим переменную Linux, по которой симулятор определит, какой робот работает в симуляции# Если параметр $2 waffle или burgerif[$2=="waffle"]||[$2=="burger"]then# Присвоить переменной TURTLEBOT3_MODEL значение параметра $2exportTURTLEBOT3_MODEL=$2else# Иначе по умолчанию будет burgerexportTURTLEBOT3_MODEL=burgerfi# Для запуска программного рендеринга. Может понадобиться на компьютере с интегрированным видеоexportLIBGL_ALWAYS_SOFTWARE=1# Выберем, какой мир будет использовать симулятор по значению параметра $1case$1inempty)# Значение empty - запускаем пустой мирroslaunch turtlebot3_gazebo turtlebot3_empty_world.launch;;turtle)# Значение turtle - запускаем мир-черепахуroslaunch turtlebot3_gazebo turtlebot3_world.launch;;house)# Значение house - запускаем мир с домомroslaunch turtlebot3_gazebo turtlebot3_house.launch;;# Отличное от empty, turtle или house значение - запускаем пустой мир по умолчанию*)roslaunch turtlebot3_gazebo turtlebot3_empty_world.launch;;esac
Теперь снова попытаемся построить образ:
docker build --no-cache . --tag turtlebot3
Вот теперь, после продолжительной “постройки”, образ готов. Кстати,
посмотрите на его размер, он занимает около 4 ГБ, что неудивительно, так
как там теперь и ROS и пакеты TurtleBot3.
6.3.3 Запуск контейнера Docker с
GUI
Контейнеры Docker по умолчанию не используют графический интерфейс.
Если мы сейчас запустим контейнер
docker run -it --rm turtlebot3 empty burger, то ничего
хорошего не выйдет, так как у нашего контейнера не настроена графическая
оболочка. Давайте настроим её по указаниям ROS
Wiki из раздела “1. The simple way.”
Для начала надо подать команду xhost +local:root, которая
разрешит всем доступ к X-серверу, так как сейчас такой доступ запрещён в
целях безопасности. В ROS Wiki эта команда помечена “для ленивых и
безрассудных”, но в нашем случае цель – запустить Gazebo в
контейнере Docker, про паранойю требования безопасности Linux
мы на время забудем. Ну а если очень страшно, можно после завершения
работы контейнера выполнить команду
xhost -local:root.
Теперь скопируем команду запуска rqt в ROS Indigo:
docker run -it\--env="DISPLAY"\--env="QT_X11_NO_MITSHM=1"\--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw"\ osrf/ros:indigo-desktop-full \ rqt
и модифицируем её под наши нужды:
docker run -it--rm--env="DISPLAY"--env="QT_X11_NO_MITSHM=1"--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" turtlebot3 empty waffle
Отличная получилась команда, длинная и красивая. С её помощью можно
не только контейнеры запускать, но и память тренировать. А можно не
тренировать, а спрятать всё эту красоту в ещё один файлик, который будет
использован ещё одним инструментом Docker. Давайте попробуем запустить
несколько вариантов, а потом поговорим о Docker
Compose. Пустой мир с Вафлей: Черепаший мир и Бургер
docker run -it --rm --env="DISPLAY" --env="QT_X11_NO_MITSHM=1" --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" turtlebot3 turtle burger:
И,
наконец, очень долго загружающийся Дом и опять Вафля
docker run -it --rm --env="DISPLAY" --env="QT_X11_NO_MITSHM=1" --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" turtlebot3 house waffle:
Теперь
давайте всё-таки облегчим жизнь нашим потенциальным потребителям и дадим
возможность запускать сложные команды более простым путём.
6.3.4 Docker Compose и
запуск симуляции с GUI
Сразу скажу, Docker
Compose – это совсем не средство запуска графики в контейнере,
Docker Compose управляет наборами контейнеров, запускает их вместе, в
нужной последовательности, необходимой для вашего приложения. Пока у нас
только одно приложение, но его достаточно для знакомства с Docker
Compose. В каталоге с Docker-файлом создадим новый файл
docker-compose.yml. Файл написан в формате YAML, про который
уже мы говорили ранее, со следующим текстом:
version:'2' # Версия файла. Версия 2 устаревшая, но с ней примеры в ROS Wikiservices: # Приложения, которые мы будем запускать, перечисляются ниже. У каждого есть произвольное имя и некоторый список параметровtbot3sim: # Назовём раздел с нашей симуляцией так, а можно было и по другому. Главное, чтобы было понятно, что этоimage: # Образ контейнера turtlebot3 # тот, который мы собрали в процессе урокаenvironment: # Настроим окружение для графики, как сказано в ROS Wiki-"DISPLAY"-"QT_X11_NO_MITSHM=1" #fix some QT bugsvolumes: # Подключение томов Docker, #в том числе, устройства графического интерфейса (В Linux всё есть файл!).- /tmp/.X11-unix:/tmp/.X11-unix:rw
По тексту файла я попытался в меру своего понимания объяснить в
комментариях, за что отвечают строки. Давайте теперь попробуем
“поднять”. У Docker Compose есть четыре команды управления
работой контейнеров:
up – развёртывает сервисы (приложения), создаёт контейнеры, сети,
тома и прочее,
stop – останавливает все сервисы, но не удалят контейнеры и их тома
и сети,
start – перезапускает остановленные с помощью stop контейнеры,
down – останавливает все сервисы, также удаляет все контейнеры и
внутренние сети, не удаляет тома. Давайте запустим нашу “композицию”.
Кстати, так как нам не нужна интерактивность в оболочке контейнера, так
как мы запускаем приложение с GUI, мы можем запустить приложение с
ключом -d и приложение будет запущено в фоновом режиме,
то есть терминал останется доступным для нас. Подадим команду:
docker compose up -d
Отлично, симулятор запущен, терминал свободен. Теперь подадим
последовательно команды:
docker compose stopdocker compose startdocker compose down
Gazebo закрылась, потом снова запустилась и снова закрылась.
Попробуйте использовать start снова. Что получится? ___
А получится фальсстарт, так сказать. У сервис, который можно было
запустить заново, теперь нет контейнера.
Теперь ещё пара слов про Docker Compose и перейдём к Gazebo и симуляции.
Вы, вероятно, заметили, что мы упростили запуск до такого состояния, что
у нас запускается теперь только Пустой мир и Бургер. Как же нам
исправить эту ситуацию? Передавать команде docker
compose параметры мы не умеем, да это и логично, так как мы
запускаем “композицию” из нескольких контейнеров и не понятно, кому
передавать параметры. Давайте создадим в том же каталоге с Docker-файлом
новый файл turtle-waffle-dc.yml с тем же текстом, что и в
docker-compose.yml, только дополним его, чтобы получился такой
текст:
version: '3' #Эээээксперимент!
services: # Приложения, которые мы будем запускать, перечисляются ниже. У каждого есть произвольное имя и некоторый список параметров
tbot3sim: # Назовём раздел с нашей симуляцией так, а можно было и по другому. Главное, чтобы было понятно, что это
image: # Образ контейнера
turtlebot3 # тот, который мы собрали в процессе урока
environment: # Настроим окружение для графики, как сказано в ROS Wiki
- "DISPLAY"
- "QT_X11_NO_MITSHM=1" #fix some QT bugs
volumes: # Подключение томов Docker,
#в том числе, устройства графического интерфейса (В Linux всё есть файл!).
- /tmp/.X11-unix:/tmp/.X11-unix:rw
command: # Это мы передадим контейнеру
turtle waffle # Черепаший мир и Вафля
Теперь поднимем “композицию” для этого файла. А поможет нам в этом
ключ -f или –file, который задаёт имя
файла для docker compose:
docker compose --file ~/dockerfiles/turtlebot3/turtle-waffle-dc.yml up -d
Получилось: На этом пока с Docker Compose
закончим и перейдём к симулятору. Но перейдём уже во второй части нашего
урока.
6.4 Обзор ROS-пакета
симулятора TurtleBot3
Когда мы скачивали симулятор TurtleBot3 из репозитория GitHub, мы
скачивали ROS-пакет. Давайте посмотрим, что в этом пакете есть
интересного из понятного.
6.4.1 Подключение терминала
к контейнеру
Для начала давайте запустим нашу “композицию”, так как мы будем
исследовать файлы контейнера, а затем подключимся к уже запущенному
контейнеру. Фактически, мы откроем ещё одну оболочку для машины, которая
работает в контейнере. Для того, чтобы подключиться к уже запущенному
контейнеру, мы должны знать, как Docker этот контейнер называет. Не
образ, имя которого нам известно, а именно контейнер. Для этого подадим
команду docker ps, которая выдаст такую таблицу: CONTAINER
ID – это и есть “название”, а вернее, идентификатор контейнера для
Docker. Я выделил его жёлтым. ВАЖНО: У вас он будет другим! Теперь
подключимся к контейнеру командой:
docker exec -it 20f4240ca659 bash
ВАЖНО: Замените мой идентификатор на свой! А теперь давайте облегчим
нашу жизнь в терминале и поставим текстовый файловый менеджер Midnight
Commander, так как ни штатного файлового менеджера nautilus, ни
редактора gedit в контейнере нет, да и запустить так просто мы бы их не
смогли. Итак, устанавливаем и запускаем.
sudo apt updatesudo apt install mc -ymc
Вот с таким результатом: Отлично, теперь у нас в контейнере есть MC.
Именно в контейнере, не в образе. Если вы остановите контейнер через
docker compose down, то после запуска MC придется
установить заново. Так что есть смысл останавливать “композицию” с
помощью stop. К сожалению, при выключении или
перезагрузке контейнеры будут “задаунены”.
6.4.2 Структура пакета
симуляции TurtleBot3
Хорошо, давайте теперь посмотрим на подкаталоги, которые есть в
каталоге src. Там мы видим подкаталог
turtlebot3_simulations, в котором мы можем увидеть файлы из
репозитория GitHub.
Подкаталог launch
Так как мы работаем с Gazebo, давайте перейдем в каталог с
ROS-пакетом turtlebot3_gazebo и увидим старого знакомого –
папку launch, в которой действительно лежат launch-файлы. С
тремя из этих файлов мы работали в первой части урока. Если вы вспомните
скрипт launch.sh, там мы запускали с помощью
roslaunch пакет turtlebot3_gazebo с одним из
трёх launch-файлов: turtlebot3_empty_world.launch,
turtlebot3_world.launch или
turtlebot3_house.launch.
Давайте посмотрим, как написан launch-файл для запуска симуляции
Gazebo:
Мы видим, что первым аргументом в этом файле выступает имя робота,
которой берётся из переменной среды TURTLEBOT3_MODEL,
назначенной нами, а далее идут координаты начального положения робота в
системе координат мира. Следующий фрагмент текста – подключение файла
пустого мира Gazebo с аргументами:
world_name – файл с моделью мира (поговорим о них дальше), который
мы будем использовать,
paused – запуск симуляции в приостановленном состоянии,
use_sim_time – публиковать время моделирования для ROS-узлов,
gui – запустить окно графического интерфейса,
headless (устаревшее наименование, сейчас – recording)– писать
журнал состояния Gazebo,
debug – запустить сервер Gazebo в режиме отладки.
Фактически, все аргументы здесь заданы значениями по-умолчанию, поэтом я
не совсем понимаю, зачем их задали вообще. С другой стороны, ну задали и
задали. Дальше у нас идёт строка, в которой подгружается описание робота
из основных пакетов TurtleBot3 в формате xacro с именем из аргумента
name. Последняя строка – это запуск ROS-узла симуляции робота с
именем модели, положением в мире, другие параметры.
Здесь я хочу отвлечься на xacro и его “родителя” urdf. Хотя сейчас
они нам и не понадобятся, хотелось бы, чтобы вы имели представление о
том, что это.
Xacro
– удобный инструмент для создания моделей роботов в ROS.
Представьте, что вы хотите создать модель робота в системе ROS. Робот
состоит из множества частей: корпуса, колёс, сенсоров, сочленений между
звеньями. Чтобы описать всё это, нужен особый файл, который будет
содержать полную информацию об устройстве робота.
Такой файл обычно пишется в формате XML и называется
URDF – Unified Robot Description Format.
Это стандартный способ описания структуры робота в ROS и мы обязательно
посвятим ему отдельный урок.
Однако, если робот сложный или имеет повторяющиеся части (например,
два одинаковых колеса), писать такой файл становится сложно и неудобно.
Вот здесь и появляется xacro.
Что такое xacro? Xacro — это язык макросов, основанный на XML. Он позволяет:
- Использовать переменные вместо повторяющихся
значений. - Создавать макросы, которые можно
использовать несколько раз, как шаблоны. - Подключать другие
файлы, чтобы модель состояла из нескольких частей. - Упрощать
работу с длинными и сложными конструкциями.
Как это работает?
Вы пишете файл с расширением .urdf.xacro — это ваш
“черновик” модели робота, написанный с использованием возможностей
xacro: переменных, макросов, условий и подключаемых
файлов.
В ROS вы можете напрямую использовать этот .xacro-файл,
например, в launch-файле, с помощью специальной команды внутри параметра
command:
ROS (или точнее, xacro) сам выполнит обработку этого
файла и предоставит результат в виде корректного URDF,
который затем используют такие инструменты, как
robot_state_publisher, gazebo_ros, или другие
компоненты системы.
Таким образом, вам не нужно вручную запускать команду
xacro > urdf, если вы работаете в ROS — достаточно
правильно настроить вызов через command.
Фактически, .xacro — это более удобная форма записи
.urdf. В ROS вы можете использовать
.xacro-файлы напрямую, без предварительной конвертации,
просто передав их в нужный параметр launch-файла.
Пример: Можно определить переменную wheel_radius, а
потом использовать её в описании левого и правого колеса. Если радиус
изменится — достаточно поменять значение переменной один раз.
Также можно создать макрос wheel, и использовать его
дважды — для каждого колеса.
Зачем это нужно?
Когда вы начинаете работать с реальными проектами в ROS и Gazebo, модели
роботов становятся большими и сложными. Использование xacro
помогает: - Сделать модель понятнее и
читабельнее, - Легко изменять
параметры, - Делать код повторно используемым
и структурированным.
Таким образом, xacro — это мощный помощник при работе с
описанием роботов в ROS. Он упрощает создание и поддержку моделей,
особенно когда робот становится больше и сложнее.
Подкаталог models
Давайте перейдём теперь в папку models, в которой мы найдём
несколько подкаталогов с моделями физических объектов. Из знакомого
здесь мы можем найти модели роботов Бургера и Вафли, а также модели
Мира-черепахи и Дома. Давайте заглянем в папку с моделью Бургера. Здесь
мы видим три файла, один из которых конфигурационный, если судить по
расширению, а два других с расширением sdf. Simulation
Description Format или SDF – это формат описания моделей и сцен в
Gazebo, аналогичный URDF в ROS. Это и есть файлы с моделями для Gazebo.
Несмотря на расширение, файлы эти создаются в формате
XML, в чём мы можем узнать, если посмотрим на
содержимое файла. Файл в MC мы можем открыть для просмотра клавишей
F3. Начинается наш файл с используемой версии
XML, но это нам не очень интересно и версии
sdf, что сейчас для нас не очень важно. Во втором уроке
мы говорили, что у xml-файла есть корневой элемент, вот элемент с тегом
sdf и будет здесь корневым. А вот дальше в файле можно
прочитать структуру модели робота, которая содержится внутри элемента с
тегом model и атрибутом имени со значением “turtlebot3_burger”.
Элемент следующего уровня иерархии – link, то есть, звено. Если
мы посмотрим весь файл до самого низа, то на этом уровне иерархии есть
элементы link (звенья) и элементы joint (шарниры), что
вполне естественно для робота, даже, как оказывается, и для мобильной
платформы. Нажмем F7 и поищем строку link name
(нажимайте Shift+F7 для продолжения поиска). Всего нашли
четыре звена:
base – основание,
lidar – лидар,
left_wheel – левое колесо,
right_wheel – правое колесо. Так же поищем и шарниры:
left_wheel_joint – шарнир левого колеса,
right_wheel_joint – шарнир правого колесо,
lidar_joint – шарнир лидара.
Как вы можете видеть, у каждого звена есть ещё элементы со сложной
структурой. Эти элементы, судя по названию, определяют масс-инерционные
характеристики звена – inertial, модель для проверки на
столкновения – collision, визуализацию звена – visual. У
шарниров есть элементы, определяющие, к чему крепится шарнир –
parent, что крепится к шарниру – child, расположение
шарнира – pose, систему координат шарнира – axis. Так
как структуру чужого робота разбирать сложно, давайте не будем этого
делать, но чуть позже попробуем создать свой простой робот с нуля и
разобраться со структурой в процессе создания. Так что закончим пока с
sdf-файлом. Конфигурационный файл – это тоже файл в формате
XML. В нём мы можем найти имя модели, версию модели,
какой sdf-файл использовать в зависимости от версии
sdf, данные об авторе модели и описание модели. Теперь
давайте посмотрим на модели окружения. Возьмём ту, которая попроще –
модель окружения для Мира-черепахи, которая лежит в подкаталоге
turtlebot3_world в файле model.sdf. В этом файле в
единственном звене описан целый набор пар параметров, отвечающих как за
визуализацию объектов, так и за проверку столкновений с ними. Ещё в
файле есть интересный тег static, который говорит нам, что
масс-инерционные характеристики этого объекта необходимо
проигнорировать, так как это модель, которая не будет перемещаться от
взаимодействия с другими моделями.
Подкаталог worlds
Перейдем теперь в ещё один каталог – worlds. Из названия
понятно, что здесь задаются параметры мира, в котором работает наш
робот. Вопрос, только что мы исследовали модель окружения, так зачем нам
ещё какой-то мир? Посмотрим на самый простой мир – Пустой. Он задан в
файле empty.world, который хоть и не имеет расширения
sdf, всё же является sdf-файлом. В файле присутствуют настройки
освещения сцены под тегом scene и настройки физических свойств,
которые задают параметры решения физических уравнений (частоту и
длительность каждого шага и коэффициент реального времени), настройки
блока решателя физики и настройки блока ограничений. Также здесь,
подобно подключению модулей в питоне, можно подключить модули
sdf, за что отвечает тег include. Например, в
Пустом мире подключены модель земной плоскости (Лоза одобряет) и модель
солнца. Построенную своими силами модель окружения мы также можем
подключить к файлу, описывающему мир.
Хорошо, по каталогам мы пробежались, теперь давайте перейдём к самому
Gazebo с симуляцией и рассмотрим его интерфейс.
6.4.3 Интерфейс Gazebo
У основной панели Gazebo, той, в которой отображается 3D-модель
симуляции, есть набор инструментов.
Перечислим их слева направо:
выбор объекта для редактирования,
перемещение сцены, которое также работает по нажатию левой кнопке
мыши,
вращение сцены, средняя кнопка мыши,
масштабирование сцены, правая кнопка мыши или вращение
колёсика,
отменить действие,
повторить действие,
вставить в сцену куб,
вставить в сцену шар,
вставить в сцену цилиндр,
добавить точечный светильник,
добавить фонарь,
добавить направленный свет (ниже будет поясняющая картинка для всех
трёх типов освещения),
копировать выбранный объект,
вставить скопированное,
выравнять несколько объектов,
привязать одну модель к другой,
установка разных углов зрения (также ниже будет рисунок),
группа сохранения данных:
сохранить картинку,
журналировать,
создать график,
записать видео.
Обещанный рисунок про свет:
И про углы зрения:
Надо добавить, что если мы захотим дополнить сцену каким-либо телом
из предлагаемых, а потом решим выйти из Gazebo, то нам
предложат сохранить нашу модель, что не может не радовать, так как
править модели в sdf-файлах мы пока умеем плохо.
У панели модели есть ещё и нижняя управляющая панель, которая
позволяет нам запускать, приостанавливать и перезапускать симуляцию.
Также нижняя панель даёт информацию о времени, прошедшем внутри
симуляции и реально прошедшем времени и их соотношении, которое
показывает, насколько симуляция близка к реальному времени. Также там
можно увидеть количество шагов, выполненных с начала симуляции и
количество кадров в секунду пир отображении 3D-модели.
Слева от окна 3D-модели у Gazebo панель редактирования сцены, где на
вкладке World мы можем работать с устройством всей сцены,
которая оформлена в виде дерева. Если выбрать модель turtlebot3_waffle
на панели редактирования сцены и раскрыть это дерево, а потом открыть
sdf-файл с моделью этого робота, можно увидеть очевидную взаимосвязь.
Также, переключившись на вкладку Insert, мы можем вставлять
различные модели из известных Gazebo каталогов.
6.4.4 Взаимодействие с
симуляцией в ROS
Работа робота в симуляции – это, конечно, не самоцель.
Предполагается, что к роботу мы можем подключаться для управления. Также
и к модели робота мы должны иметь доступ. Так как мы всё ещё говорим про
ROS, этот доступ должен осуществляться средствами ROS. Давайте посмотрим
для начала, какие темы ROS у нас сейчас есть в системе. Если у вас в
терминале всё ещё открыт Midnight Commander, можно его
“свернуть” прямо в терминале, нажав сочетание клавишь Ctrl+o.
Давайте подадим команду, которая выдаст нам список тем. ___
rostopic list
Надеюсь, все получили сообщение “bash: rostopic: command not
found” и все его уже устранили. ___ Если нет, то вам
двойка введите команды:
. /opt/ros/noetic/setup.bash. /home/.bashrc
Список тем впечатляет. Давайте найдём что-то, чьё название нам более
или менее понятно, тему /clock, например. Для начала в
симуляторе клавишей Reset Time сбросим время моделирования, а потом
выведем на экран содержимое нужной нам темы. ___
rostopic echo /clock
Я постарался захватить и кусочек терминала и кусочек интерфейса
симулятора с данными о времени, чтобы получить картинку:
И там и там получилось одно и то же время – 1 минута 59 секунд или 119
секунд. Наносекунды и миллисекунды сравнивать не будем, в данном случае,
то есть, при выводе данных на экран, да ещё и не в операционной системе
Hard Real Time, в этом нет смысла.
Давайте посмотрим, какие ещё знакомые топики мы можем найти. Например,
топик /cmd_vel нам знаком из урока с симулятором черепашки.
Посмотрим информацию о ней.
rostopic show /cmd_vel
Паблишера нет, подписчик /gazebo, тип Twist из набора
геометрических сообщений. Очевидно, здесь это тоже задаваемая нами
скорость перемещения, но с одним нюансом – это заданная скорость
перемещения, а реальная, пусть и в симуляции, скорость перемещения будет
зависеть от физических параметров моделей.
Посмотрим теперь на очень интересную тему, которая называется
/imu. IMU – это Inertial
measurement unit, устройство, измеряющее силы, воздействующие на
тело, ускорения тела, его ориентацию. Его публикует для нас /gazebo, а
тип этой темы Imu из набора sensor_msgs:
Здесь ориентация задана кватернионом, а угловые и линейные ускорения
векторами. Мы не будем здесь разбирать математический аппарат
кватернионов, если он вам неизвестен. А у меня вообще с математикой
плохо, я засыпаю ещё на перемножении комплексных чисел. Если интересно
узнать про кватернионы, можно подстеречь Уильяма Гамильтона на
мосту и спросить почитать главу 8.5 книги 3D
Math Primer for Graphics and Game Development или здесь.
У каждого из этих элементов сообщения есть ещё ковариационная матрица,
которая даёт нам информацию, насколько можно доверять показаниям
датчика.
Числа на диагонали говорят нам, насколько шумный каждый датчик. Чем
больше число — тем менее точное измерение и наоборот, чем меньше число —
тем более точное измерение. Числа вне диагонали говорят нам, зависит ли
одно измерение от другого. Если там ноль — то нет зависимости, если же
там ненулевое значение – это значит, что движение в одном направлении
немного влияет на измерение по другому направлению.
Кроме рассмотренных параметров, у сообщения есть ещё заголовок, который
содержит идентификатор посылки, время с начала работы и систему
координат, связанную с датчиком. Давайте выведем на экран содержимое
топика rostopic echo /imu:
Наш робот находится в неподвижном состоянии, поэтому любые отклонения
значений линейного ускорения от нуля можно считать шумом — такими же,
как в реальных датчиках. Такой шум часто моделируется в симуляторах для
более реалистичного представления работы оборудования.
Однако ковариационная матрица измерений IMU равна нулю, то есть
симулятор не предоставляет информацию о погрешностях датчика. Это
не значит , что датчик идеальный — просто уровень шума
явно не задан. В реальных роботах или более точных симуляциях там стоят
ненулевые значения, которые помогают системам навигации и фильтрам
оценивать достоверность данных.
В то же время значения ориентации показывают текущее положение робота
в пространстве относительно выбранной системы координат.
Теперь ещё один топик, который называется /joint_states и
имеет формат sensor_msgs/JointState:
Это сообщение содержит информацию о наборе шарниров модели. В нём мы
опять видим заголовок, который уже видели ранее. Далее идёт массив
названий положение шарнира, измеряемое, если посмотреть в документации,
в метрах или радианах в зависимости от типа шарнира. Далее массив
скоростей в метрах в секунду или радианах в секунду. Последними данными
будет массив сил в Ньютонах или моментов в Ньютонах на метр,
воздействующих на шарнир. Выведем значения сообщения на экран
rostopic echo /joint_states:
Здесь мы видим имена двух шарниров правого и левого и их положения.
Скорости и усилия значений не имеют, а значит, такой информации
симулятор не имеет. Если бы информация была, но значение было бы
нулевым, мы бы увидели нули.
Посмотрим теперь ещё на топик одометрии /odom формата
nav_msgs/Odometry:
Вы видели одометры в автомобиле, скорее всего. Там это просто общий
счётчик километража, пройденного автомобилем, посчитанный по показаниям,
снятым с колёс автомобиля. Здесь хранится информация, сколько по
датчикам колёс робота прошёл робот, только в расширенном виде. Как в
случае автомобиля, так и в случае робота эта информация полезна, но не
совсем точна. Например, если вы поедете в лес и там застрянете в грязной
луже, то побуксовав, можете обнаружить, что по одометру прошли гораздо
больше, чем на самом деле. С роботом может быть так же, колёса могут
проскальзывать или датчики могут быть неточными. То есть, если ходить с
закрытыми глазами, можно оказаться в весьма неожиданном для себя
месте.
Посмотрим на данные, которые симулятор передаёт в тему одометрии
rostopic echo /odom:
Ух! Мы видим наборы данных для положения и ориентации, заданные
положением и ориентацией. Пока не будем разбираться с этими данными.
Единственно, отмечу, что ковариационная матрица для положения впечатляет
огромными числами – видимо, нам предлагают сомневаться в датчике!
На это пока давайте закончим с разбором ROS-пакета симулятора и
отдохнём, двигая модель робота по сцене.
6.5 Телеуправление роботом
TurtleBot3
В названии раздела нет ошибки. Для ROS-пакета, который мы сейчас
запустим, нет никакой разницы, управлять реальным роботом или
симуляцией, ведь он только общается с другими программами по
ROS-протоколам и знать не знает, чем он управляет. Он вообще был
установлен на этапе установки, когда симуляции ещё не предполагалось.
Хорошая симуляция должна быть такой, что сторонним пакетам не должно
быть до её проблем никакого дела. Итак, запустим телеуправление:
А вот информацией о том, каким типом робота надо управлять,
этому пакету нужна. Устраните, пожалуйста, возникшую проблему: ___
Напишем в терминале:
exportTURTLEBOT3_MODEL=waffle
И проблемы нет. Снова запускаем. На этот раз всё хорошо, мы видим
такую подсказку, какие клавиши управляющие и на какое значение для
каждого типа робота однократное нажатие увеличит скорость. Попробуем
сейчас перемещать робот, как нам предлагают:
Итак, не забудьте перейти в терминал, где запущен пакет телеуправления и
поехали:
Всё работает. Я нажимаю клавиши, тем самым увеличиваю, уменьшаю или
сбрасываю скорость до нуля, а робот реагирует на это перемещениями.
Обратите внимание, когда робот упёрся в столб, скорость для него была
установлена, я сбросил её только после того, как робот упёрся и скользя
одними колёсами и цепляясь другими не начал поворачиваться, хотя задана
была только скорость “вперёд” во внутренней системе координат.
Давайте под конец этого урока не поленимся, подключим ещё один
терминал к контейнеру и посмотрим на значения IMU и шарниров в процессе
управления роботом.
docker psdocker exec -it???????????? bash
В контейнере:
. /opt/ros/noetic/setup.bash. /home/.bashrcrostopic echo /imu#Тут мы погоняем робот по оси X и посмотрим на значения линейного ускоренияrostopic echo /joint_states#Теперь доедем до стены и посмотрим, крутятся ли колёса.
Так я и думал. Именно это я и полагал
Робот движется вперед, ускорение по оси X выросло. Упёрлись в стену, а
колёса крутятся. Всё логично.
6.5.1
Добавление контейнера для телеуправления в Docker Compose
🔍 !!!ЭТО НЕПРОВЕРЕННЫЙ ПОДРАЗДЕЛ!!!
На предыдущем этапе мы запускали управление роботом TurtleBot3
внутри того же контейнера, где работает симуляция. Это
удобно на начальном этапе, но не соответствует реальной практике
разработки, где разные части системы (например, симулятор, навигация,
телеуправление) могут работать в отдельных
контейнерах.
Чтобы показать этот подход, мы добавим второй сервис в файл
docker-compose.yml, который будет представлять
собой контейнер с пакетом
turtlebot3_teleop. Такой способ позволит нам: -
Разделить логику симуляции и управления, - Продемонстрировать работу
нескольких ROS-контейнеров, - Показать, как между ними организуется
связь через сеть.
Шаг 1:
Создание Dockerfile для контейнера телеуправления
В каталоге ~/dockerfiles/turtlebot3 создайте новый
подкаталог, например, teleop, и перейдите в него:
Создайте файл Dockerfile со следующим содержанием:
FROM osrf/ros:noetic-desktop-full# Установка необходимого пакета для телеуправленияRUNapt update -y&&\apt install -y ros-noetic-turtlebot3-teleop &&\apt clean &&\rm-rf /var/lib/apt/lists/*# Рабочая директорияWORKDIR /home/user# Команда по умолчанию (временно отключена)CMD ["echo", "Телесервис готов к запуску"]
Этот образ содержит только нужный нам пакет
turtlebot3_teleop. Запуск самого управления мы будем
выполнять из терминала контейнера, чтобы явно показать, как он
взаимодействует с основной симуляцией.
Шаг 2: Обновление
файла docker-compose.yml
Откройте ваш docker-compose.yml и измените его так,
чтобы он включал общую сеть, а также два сервиса: один
для симуляции, второй — для
телеуправления:
После этого вы можете управлять роботом с помощью клавиатуры, как и
раньше.
Преимущества такого подхода
Разделение ответственности: симуляция и управление
работают в разных контейнерах.
Масштабируемость: можно добавить RViz, SLAM или
другие модули в виде отдельных сервисов.
Изоляция ошибок: если одно приложение сломается,
другое продолжит работать.
Удобство тестирования: легко менять параметры
одного из контейнеров без перезапуска всей системы.
Добавив второй контейнер с телеуправлением в
docker-compose.yml, мы сделали нашу систему более гибкой и
близкой к реальным условиям. Это позволяет лучше понять, как строить
распределённые ROS-приложения и использовать Docker для масштабируемой
разработки.
⚠️ Важно: Не забудьте перед запуском контейнеров
выполнить в терминале:
xhost +local:root
Иначе Gazebo не сможет отобразить графический интерфейс.
Давайте на этом сегодняшний урок закончим, только вспомним, что мы из
урока узнали.
6.6 Заключение
Сегодня вы прошли важный этап в освоении робототехники: вы не просто
запустили симуляцию TurtleBot3 в Gazebo, но и научились управлять ею
через ROS, используя контейнеризацию Docker и удобство Docker Compose
для организации нескольких сервисов.
Мы начали с того, что подготовили рабочее окружение с помощью Docker,
создав собственный образ, содержащий всё необходимое для работы
TurtleBot3. Это дало вам возможность абстрагироваться от сложностей
установки пакетов и зависимостей и сосредоточиться именно на задачах
моделирования и управления роботом.
Вы узнали, как использовать docker-compose.yml, чтобы
запускать несколько сервисов одновременно, и даже добавили второй
контейнер — для телеуправления роботом. Это позволило разделить логику
симуляции и управления, приблизив вас к реальной практике разработки
распределённых систем на базе ROS. Мы также разобрались, как обеспечить
связь между контейнерами с помощью пользовательских сетей Docker и
переменных окружения ROS.
В ходе урока вы познакомились с интерфейсом Gazebo — мощного
симулятора, способного воспроизводить физическое поведение роботов и их
взаимодействие с окружающей средой. Вы научились читать данные с
датчиков, таких как IMU и шарниры, а также анализировать сообщения из
топиков /imu и /joint_states. Особенно важно,
что вы поняли значение ковариационной матрицы в сообщениях — она говорит
нам, насколько мы можем доверять данным с датчика.
Но это ещё не всё. Вы не только наблюдали за работой системы, но и
активно взаимодействовали с ней: управляли роботом с клавиатуры,
подключались к контейнерам через терминал, следили за изменением
параметров в режиме реального времени и даже сталкивались с ситуацией,
когда робот упирается в стену, а колёса продолжают вращаться — то есть,
вы наблюдали за реакцией системы на внешние воздействия.
Также вы углубились в структуру ROS-пакетов, узнали о форматах
SDF и URDF, и познакомились с инструментом
xacro, который позволяет строить более гибкие и удобные
описания роботов. Это особенно важно, если вы планируете создавать свои
собственные модели или модифицировать существующие.
На этом этапе вы уже можете: - Создавать и запускать Docker-образы
для ROS-приложений, - Управлять несколькими контейнерами через Docker
Compose, - Использовать Gazebo и ROS вместе для моделирования и
тестирования роботов, - Читать и интерпретировать данные с датчиков
через ROS-топики.
Но самое главное — вы научились мыслить масштабно:
видеть систему целиком, разделять её на части, правильно организовывать
взаимодействие между компонентами и применять современные подходы DevOps
и контейнеризации в области робототехники.
С каждым таким уроком вы становитесь ближе к тому, чтобы
самостоятельно создавать сложные роботизированные системы, будь то
автономные транспортные средства, мобильные роботы, дроны или
промышленные манипуляторы.
В следующих уроках мы будем двигаться дальше: знакомиться с системой
навигации, строить карты местности, обучать робота двигаться по
заданному маршруту и взаимодействовать с объектами в окружающей среде.
Так что продолжайте в том же духе — ведь вы уже на пути стать настоящими
специалистами в области робототехники!