7.6 Публикация твист-сообщений от узла ROS
Last updated
Last updated
До сих пор мы перемещали нашего робота из командной строки, но большую часть времени вы будете полагаться на узел ROS для публикации соответствующих сообщений Twist. В качестве простого примера, предположим, что вы хотите запрограммировать робота, чтобы он перемещался на 1,0 метра вперед, поворачивался на 180 градусов, а затем возвращался к начальной точке. Мы попытаемся выполнить эту задачу несколькими различными способами, которые хорошо иллюстрируют различные уровни управления движением в ROS.
Нашей первой попыткой будет использование синхронизированных команд Twist, чтобы переместить робота на определенное расстояние вперед, повернуть на 180 градусов, а затем снова продвинуться вперед в течение того же времени и на той же скорости, где, как мы надеемся, он окажется там, где и начался. Наконец, мы повернем робота еще на 180 градусов, чтобы соответствовать исходной ориентации.
Сценарий можно найти в файле timed_out_and_back.py в подкаталоге rbx1_nav / node. Прежде чем смотреть на код, давайте попробуем его в симуляторе ArbotiX.
Чтобы убедиться, что поддельный Turtlebot перемещен в начальную точку, используйте Ctrl-C, чтобы завершить запуск файла поддельного Turtlebot, если он уже запущен, а затем снова вызовите его с помощью команды:
(При желании замените файл fake_turtlebot.launch файлом для робота Pi или вашего собственного робота. Это не повлияет на результаты.)
Если RViz еще не запущен, запустите его сейчас:
или нажмите кнопку «Сброс», чтобы удалить все стрелки одометрии из предыдущего раздела.
Наконец, запустите узел timed_out_and_back.py:
Надеемся, что RViz покажет, как ваш робот выполняет маневр в обратном направлении, и конечный результат будет выглядеть примерно так:
Большие стрелки представляют положение и ориентацию робота в различных точках вдоль его траектории, о чем сообщает внутренняя (поддельная) внутренняя одометрия робота. Мы узнаем, как использовать эту информацию об одометрии в следующих нескольких разделах.
Пока что все выглядит довольно хорошо в идеальном симуляторе. Но прежде чем попробовать это на реальном роботе, давайте посмотрим на код.
Вот полный скрипт для тайм-аута и обратного узла. После листинга мы будем разбивать его на более мелкие части.
Ссылка на источник: timed_out_and_back.py
Так как это наш первый скрипт, давайте посмотрим на него построчно, начиная сверху:
Если вы делали Учебники для начинающих ROS в Python, вы уже знаете, что все наши узлы ROS начинаются с этих двух строк. Первая строка гарантирует, что программа будет работать как скрипт Python, а вторая импортирует основную библиотеку ROS для Python.
Здесь мы позаботимся о любом другом импорте, который нам нужен для скрипта. В этом случае нам понадобится тип сообщения Twist из пакета ROS geometry_msgs и константа pi из математического модуля Python. Обратите внимание, что общий источник ошибок при импорте - забыть включить необходимую строку ROS в файл package.xml вашего пакета. В этом случае наш файл package.xml должен содержать строку:
<run_depend>geometry_msgs</run_depend>
так что мы можем импортировать Twist из geometry_msgs.msg.
Здесь мы начинаем основную часть нашего узла ROS, определяя его как класс Python вместе со стандартной линией инициализации класса.
Каждый узел ROS требует вызова rospy.init_node (), и мы также устанавливаем обратный вызов для функции on_shutdown (), чтобы мы могли выполнить любую необходимую очистку, когда сценарий завершается, например когда пользователь нажимает Ctrl-C. В случае мобильного робота самая важная задача очистки - остановить робота! Мы увидим, как это сделать позже в скрипте.
Здесь мы определяем нашего издателя ROS для отправки команд Twist в раздел / cmd_vel. Мы также устанавливаем скорость, с которой мы хотим обновить движение робота, 50 раз в секунду, а параметр queue_size равным 5.
Параметр queue_size был введен в ROS Hydro и будет обязательным в ROS Jade. В ROS Indigo ваш код выдаст предупреждение, если издатель инициализируется без этого параметра. Вы можете узнать больше о параметре queue_size в ROS Wiki. Самый важный факт, который нужно иметь в виду, это то, что если этот параметр не указан или не установлен в значение «Нет», издатель будет вести себя синхронно. Это означает, что если имеется несколько подписчиков на тему издателя, и один из подписчиков зависает - например, он находится на другом конце ненадежного беспроводного соединения - тогда публикация будет блокировать всех подписчиков этой темы, пока подписчик не зависнет возвращается к жизни. Как правило, это нежелательный результат. Установка для параметра queue_size числового значения приводит к тому, что издатель ведет себя асинхронно, так что каждый подписчик получает сообщения в отдельном потоке без подписчика и блокирует всю систему.
Мы инициализируем скорость движения вперед относительно безопасную 0,2 метра в секунду и целевое расстояние до 1,0 метра. Затем мы вычисляем, сколько времени это займет.
Аналогично, мы устанавливаем скорость вращения 1,0 радиан в секунду, а целевой угол - 180 градусов или Pi радиан.
Это петля, которая фактически перемещает робота - один цикл для каждой из двух ног. Напомним, что некоторые роботы требуют, чтобы сообщение Twist постоянно публиковалось, чтобы оно продолжало двигаться. Поэтому, чтобы продвинуть робота вперед метры linear_distance со скоростью метра linear_speed в секунду, мы публикуем сообщение move_cmd каждые 1 раз в секунду в течение соответствующей продолжительности. Выражение r.sleep () является сокращением для rospy.sleep (1 / скорость), так как мы определили переменную r = rospy.Rate (скорость).
Во второй части цикла мы вращаем робота со скоростью angular_speed радиан в секунду в течение соответствующей продолжительности (в данном случае Pi секунд), которая должна дать 180 градусов.
Когда робот завершил обратный путь, мы останавливаем его, публикуя пустое сообщение Twist (все поля равны 0).
Это наша функция обратного вызова выключения. Если выполнение сценария прекращается по какой-либо причине, мы останавливаем робота, публикуя пустое сообщение Twist.
Наконец, это стандартный блок Python для запуска скрипта. Мы просто создаем экземпляр класса OutAndBack, который запускает скрипт (и робота).
Если у вас есть такой робот, как TurtleBot, вы можете попробовать скрипт timed_out_and_back.py в реальном мире. Помните, что мы используем только время и скорость для оценки расстояния и углов поворота. Таким образом, мы ожидаем, что инерция робота вызовет изменения по сравнению с идеальной симуляцией ArbotiX (которая, как вы помните, не моделирует физику).
Во-первых, прекратите любые беговые симуляции. Затем убедитесь, что у вашего робота достаточно места для работы - по крайней мере, на 1,5 метра впереди и на метр с каждой стороны. Затем откройте файл запуска запуска вашего робота. Если у вас есть оригинальный TurtleBot (база iRobot Create), вставьте ssh в ноутбук робота и запустите:
Или используйте свой собственный файл запуска, если вы создали его для хранения параметров калибровки.
Мы также будем использовать вспомогательный скрипт, чтобы видеть комбинированную рамку одометрии TurtleBot в RViz. (Это станет понятнее в следующем разделе.) Вы можете пропустить это, если не используете TurtleBot. Этот файл запуска должен быть запущен на ноутбуке TurtleBot с помощью другого ssh-терминала:
Далее мы собираемся настроить RViz для отображения комбинированных данных одометрии (кодеры + гироскоп), а не / odom, которые только показывают кодовые данные. Если вы уже работали с предыдущим тестом, вы можете просто отменить проверку дисплея Odometry и проверить экран EKF Odometry, а затем пропустить следующий шаг.
Если RViz еще не запущен, запустите его сейчас на рабочей станции с помощью файла конфигурации nav_ekf. Этот файл просто предварительно выбирает тему / odom_ekf для отображения комбинированных данных одометрии:
Наконец, мы запускаем скрипт out и back, как и раньше. Обратите внимание, что самому сценарию не важно, выполняем ли мы симуляцию или управляем реальным роботом. Он просто публикует два сообщения в / cmd_veltopicforany, которые могут быть изменены. Это один из примеров того, как ROS позволяет абстрагироваться от нижних уровней иерархии управления движением. Вы можете запустить следующую команду на своей рабочей станции или на ноутбуке робота после входа в систему с помощью ssh:
Вот результат для моего собственного TurtleBot при работе на ковре с низким слоем:
Как видно из рисунка, робот не оказался очень близко к исходной позиции. Прежде всего, он не прошел достаточно далеко, прежде чем развернуться (квадраты сетки находятся на расстоянии 0,5 метра). Затем он не повернул на 180 градусов, прежде чем отправиться назад. В результате робот находится примерно в 0,5 м слева от начальной точки и ориентирован в неправильном направлении.
К счастью, данные, которые нам нужны, чтобы исправить проблему, смотрят нам прямо в глаза. Большие стрелки одометрии на изображении выше указывают положение и ориентацию робота в соответствии с его внутренней одометрией. Другими словами, робот «знает», что он испортил, но мы несправедливо помешали ему, не используя данные одометрии в нашем скрипте. Хотя данные одометрии не будут точно соответствовать реальному движению, они должны дать нам лучший результат, если мы их используем.