Добрый день, уважаемые читатели Хабра!
Я продолжаю серию статей о практическом использовании ROS на Raspberry Pi (первая статья, вторая статья).
В данной статье мы будем использовать пакет teleop_twist_keyboard из стека ros-teleop для управления роботом с помощью нажатия клавиш на клавиатуре. Стек ros-teleop включает помимо данного пакета еще несколько пакетов для различных способов управления, например с помощью джойстика. Кто готов приступить к изучению teleop_twist_keyboard, прошу под кат.
Между делом, я вам хочу рассказать об одном приеме, который позволяет работать удаленно на Raspberry Pi через SSH одновременно в нескольких терминалах. Для этого на RPi нужно установить утилиту tmux.
После этого запускаем утилиту:
Внизу окна терминала должна появиться зеленая полоса с номером окна — 0.
tmux — это очень удобный менеджер терминальных окон, который позволяет создать в одном окне терминала любое число окон, размещая их несколькими различными способами (отдельное окно-терминал (window), панель окна (pane)) и удобно переключаться между ними.
Нажмите на клавиатуре Ctrl + B и C. Должно открыться еще одно окно с номером 1. Также попробуйте комбинацию Ctrl + B и %. Текущее окно терминала будет разделено посередине вертикальной зеленой полосой на два окна (pane). Если нажать комбинацию Ctrl + B,: и ввести “split window”, то окно будет разделено горизонтально на два одинаковых окна. Чтобы удалить панель (pane) воспользуйтесь комбинацией Ctrl + B, X и затем нажмите Y. Чтобы переключиться на другую панель в том же окне, используйте комбинацию Ctrl + B, O. Чтобы переключиться между окнами-терминалами по номеру окна, используйте комбинацию Ctrl + B, <номер окна>.
Теперь добавим запуск программы в файл ~/.bashrc для автоматического запуска при открытии нового терминала. Добавьте следующие строки в файл:
Теперь познакомимся с пакетом teleop_twist_keyboard.
Запустим скрипт teleop_twist_keyboard.py из пакета teleop_twist_keyboard как обычный узел ROS:
Мы получим вывод такого вида:
Выведем список всех активных на данный момент топиков:
Топик /cmd_vel должен появиться в списке. На этот топик узел teleop_twist_keyboard публикует сообщения каждый раз, когда была нажата клавиша на клавиатуре.
Покажем вывод сообщений, публикуемых в топик /cmd_vel:
Запустим rqt_graph для представления вычислительного графа ROS в графическом виде. Схема вычислительного графа показывается все активные узлы и топики, которые их связывают.
Здесь мы видим, что узел teleop_twist_keyboard публикует собщения в топик /cmd_vel, а узел rostopic подписывается на этот топик (команда rostopic echo).
Давайте узнаем какого типа сообщения публикуются на топик /cmd_vel:
Команда выведет строку:
Это означает, что сообщения имеют тип Twist из стандартного ROS пакета geometry_msgs.
Мы также можем получить информацию о структуре сообщения командой rosmsg:
Поле ‘linear’ отвечает за линейную скорость, ‘angular’ — за угловую скорость.
Нажмите клавишу ‘i’, вывод будет таким (ассоциируется с движением вперед):
Нажмите клавишу ‘k’, вывод будет таким (остановка):
Нажмите клавишу ‘u’, вывод будет таким (поворот влево):
И наконец при нажатии на клавишу ‘o’ получим такой вывод (поворачиваем вправо):
Клавиши ‘j’ и ‘l’ отвечают за повороты влево и вправо на месте (без движения вперед).
У меня уже написан скетч rosserial для управления роботом посредством нажатия клавиш. Мы просто подписываемся на топик /cmd_vel и в зависимости от получаемого значения каждой из скоростей отдаем необходимую команду контроллеру движения (двигаться вперед, остановиться, повернуть влево или вправо). Скетч можно скачать отсюда.
Разберем подробнее код скетча.
В начале файла подключаем помимо стандартного заголовочного файла ros.h два дополнительных файла с типами сообщений geometry_msgs/Twist.h и geometry_msgs/Vector3.h:
Мы объявляем обработчик узла ros::NodeHandle:
Основное значение имеет метод messageCb:
В этом методе мы производим обработку получаемого сообщения из топика cmd_vel. В переменной forward_vel мы сохраняем линейную скорость, в переменной angular — угловую. Линейная скорость нам позволяет отследить команду остановки (значение 0). Угловая скорость определяет направление поворота (если больше 0, то поворачиваем влево, меньше 0 — вправо, если 0 — двигаемся вперед).
Создаем подписчика на топик /cmd_vel:
со указанием ссылки на метод обработки сообщений (messageCb) и типа принимаемого сообщения — geometry_msgs::Twist.
В конце скрипта следуют стандартные методы скетча для rosserial_arduino:
Запустите rosserial_arduino сервер:
и загрузите скетч на плату Arduino.
Переключитесь на терминал, где запущен узел teleop_twist_keyboard, попробуйте нажатие клавиш ‘u’, ‘i’, ‘o’ и ‘k’ и проверьте в терминале вывод сервера rosserial.
Таким образом, используя пакет teleop_twist_keyboard мы теперь можем выполнять простое удаленное управление роботом передавая команды движения: двигаться вперед, остановиться, повернуть влево или вправо. В дальнейшем мы научимся управлять роботом с помощью джойстика, что значительно удобнее, с применением уже другого пакета в ROS. Но об этом в следующей статье.
Я продолжаю серию статей о практическом использовании ROS на Raspberry Pi (первая статья, вторая статья).
В данной статье мы будем использовать пакет teleop_twist_keyboard из стека ros-teleop для управления роботом с помощью нажатия клавиш на клавиатуре. Стек ros-teleop включает помимо данного пакета еще несколько пакетов для различных способов управления, например с помощью джойстика. Кто готов приступить к изучению teleop_twist_keyboard, прошу под кат.
Мультитерминал с tmux
Между делом, я вам хочу рассказать об одном приеме, который позволяет работать удаленно на Raspberry Pi через SSH одновременно в нескольких терминалах. Для этого на RPi нужно установить утилиту tmux.
$ sudo apt-get install tmux
После этого запускаем утилиту:
$ tmux
Внизу окна терминала должна появиться зеленая полоса с номером окна — 0.
tmux — это очень удобный менеджер терминальных окон, который позволяет создать в одном окне терминала любое число окон, размещая их несколькими различными способами (отдельное окно-терминал (window), панель окна (pane)) и удобно переключаться между ними.
Нажмите на клавиатуре Ctrl + B и C. Должно открыться еще одно окно с номером 1. Также попробуйте комбинацию Ctrl + B и %. Текущее окно терминала будет разделено посередине вертикальной зеленой полосой на два окна (pane). Если нажать комбинацию Ctrl + B,: и ввести “split window”, то окно будет разделено горизонтально на два одинаковых окна. Чтобы удалить панель (pane) воспользуйтесь комбинацией Ctrl + B, X и затем нажмите Y. Чтобы переключиться на другую панель в том же окне, используйте комбинацию Ctrl + B, O. Чтобы переключиться между окнами-терминалами по номеру окна, используйте комбинацию Ctrl + B, <номер окна>.
Теперь добавим запуск программы в файл ~/.bashrc для автоматического запуска при открытии нового терминала. Добавьте следующие строки в файл:
[[ $TERM != "screen" ]] && exec tmux
Работа с пакетом teleop_twist_keyboard
Теперь познакомимся с пакетом teleop_twist_keyboard.
Запустим скрипт teleop_twist_keyboard.py из пакета teleop_twist_keyboard как обычный узел ROS:
$ roscore
$ rosrun teleop_twist_keyboard teleop_twist_keyboard.py
Мы получим вывод такого вида:
Reading from the keyboard and Publishing to Twist!
---------------------------
Moving around:
u i o
j k l
m , .
q/z : increase/decrease max speeds by 10%
w/x : increase/decrease only linear speed by 10%
e/c : increase/decrease only angular speed by 10%
anything else : stop
CTRL-C to quit
Выведем список всех активных на данный момент топиков:
$ rostopic list
Топик /cmd_vel должен появиться в списке. На этот топик узел teleop_twist_keyboard публикует сообщения каждый раз, когда была нажата клавиша на клавиатуре.
Покажем вывод сообщений, публикуемых в топик /cmd_vel:
$ rostopic echo cmd_vel
Запустим rqt_graph для представления вычислительного графа ROS в графическом виде. Схема вычислительного графа показывается все активные узлы и топики, которые их связывают.
$ rosrun rqt_graph rqt_graph
Здесь мы видим, что узел teleop_twist_keyboard публикует собщения в топик /cmd_vel, а узел rostopic подписывается на этот топик (команда rostopic echo).
Давайте узнаем какого типа сообщения публикуются на топик /cmd_vel:
$ rostopic type /cmd_vel
Команда выведет строку:
geometry_msgs/Twist
Это означает, что сообщения имеют тип Twist из стандартного ROS пакета geometry_msgs.
Мы также можем получить информацию о структуре сообщения командой rosmsg:
$ rosmsg info geometry_msgs/Twist
geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z
Поле ‘linear’ отвечает за линейную скорость, ‘angular’ — за угловую скорость.
Нажмите клавишу ‘i’, вывод будет таким (ассоциируется с движением вперед):
linear:
x: 0.5
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.0
---
Нажмите клавишу ‘k’, вывод будет таким (остановка):
linear:
x: 0.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.0
---
Нажмите клавишу ‘u’, вывод будет таким (поворот влево):
linear:
x: 0.5
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 1.0
---
И наконец при нажатии на клавишу ‘o’ получим такой вывод (поворачиваем вправо):
linear:
x: 0.5
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: -1.0
---
Клавиши ‘j’ и ‘l’ отвечают за повороты влево и вправо на месте (без движения вперед).
Управление роботом с клавиатуры с teleop_twist_keyboard
У меня уже написан скетч rosserial для управления роботом посредством нажатия клавиш. Мы просто подписываемся на топик /cmd_vel и в зависимости от получаемого значения каждой из скоростей отдаем необходимую команду контроллеру движения (двигаться вперед, остановиться, повернуть влево или вправо). Скетч можно скачать отсюда.
Разберем подробнее код скетча.
В начале файла подключаем помимо стандартного заголовочного файла ros.h два дополнительных файла с типами сообщений geometry_msgs/Twist.h и geometry_msgs/Vector3.h:
#include <geometry_msgs/Twist.h>
#include <geometry_msgs/Vector3.h>
Мы объявляем обработчик узла ros::NodeHandle:
ros::NodeHandle nh;
Основное значение имеет метод messageCb:
void messageCb(const geometry_msgs::Twist& message)
{
geometry_msgs::Vector3 linear = message.linear;
float forward_vel = float(linear.x);
if(forward_vel == 0) { stop(); return; }
geometry_msgs::Vector3 angular = message.angular;
float ang_vel = float(angular.z);
if(ang_vel > 0) { turnLeft(); }
else if(ang_vel < 0) { turnRight(); }
else { goForward(); }
}
В этом методе мы производим обработку получаемого сообщения из топика cmd_vel. В переменной forward_vel мы сохраняем линейную скорость, в переменной angular — угловую. Линейная скорость нам позволяет отследить команду остановки (значение 0). Угловая скорость определяет направление поворота (если больше 0, то поворачиваем влево, меньше 0 — вправо, если 0 — двигаемся вперед).
Создаем подписчика на топик /cmd_vel:
ros::Subscriber<geometry_msgs::Twist> sub("/cmd_vel", &messageCb);
со указанием ссылки на метод обработки сообщений (messageCb) и типа принимаемого сообщения — geometry_msgs::Twist.
В конце скрипта следуют стандартные методы скетча для rosserial_arduino:
nh.initNode();
nh.subscribe(sub);
Serial.begin(57600);
Запустите rosserial_arduino сервер:
$ rosrun rosserial_python serial_node _port:=/dev/ttyACM0
и загрузите скетч на плату Arduino.
Переключитесь на терминал, где запущен узел teleop_twist_keyboard, попробуйте нажатие клавиш ‘u’, ‘i’, ‘o’ и ‘k’ и проверьте в терминале вывод сервера rosserial.
Таким образом, используя пакет teleop_twist_keyboard мы теперь можем выполнять простое удаленное управление роботом передавая команды движения: двигаться вперед, остановиться, повернуть влево или вправо. В дальнейшем мы научимся управлять роботом с помощью джойстика, что значительно удобнее, с применением уже другого пакета в ROS. Но об этом в следующей статье.
Комментарии (5)
vubdub
03.03.2016 01:14+1Кстати, вышла новая версия платы:
www.raspberrypi.org/blog/raspberry-pi-3-on-salevovaekb90
05.03.2016 19:34Спасибо за сообщение. Описание впечатляет, в частности модуль LAN и Bluetooth
Hellsy22
С интересом ознакомился со всем циклом статей.
К сожалению, я не совсем понимаю область применения комбинации ROS и RPI. В конкретном примере с роботом куда проще (и дешевле) было бы взять смартфон с USB OTG и воткнуть в него Arduino Uno/Mini, получив камеру и возможность управлять роботом дистанционно, хоть через wifi, хоть с помощью GSM. Да и ROS под андроид тоже есть.
Было бы замечательно услышать какие-нибудь примеры, в которых использование ROS+RPI оправдано задачей.
iliasam
Там вроде бы пока многое еще не доделано.
RPI хорошо подходит для прямого управления периферийными устройствами (там есть UART, SPI, I2С, GPIO), камера на шлейфе, которую можно закрепить как угодно.
В случае с телефоном придется писать отдельную прошивку под Arduino, изобретать протокол связи межу ними и.т.д.
vovaekb90
Меня заинтересовала связка ROS и RPi в связи с давней идеей добавить возможности компьютерного зрения своему роботу на Arduino. Также хотелось "отвязать" робота от лаптопа и сделать его полностью автономным. rosserial оказался подходящим выбором для связки Arduino и RPi. Управление со смартфона я не рассматривал. У меня уже были на руках Arduino и RPi, поэтому решил попробовать с ними.