Разработка графического интерфейса для робота с использованием Qt и Python

Разработка графического интерфейса для робота с использованием Qt и PythonИ наконец, наша серия статей подходит к концу, и в этой завершающей статье мы обсудим аппаратную сборку, интеграцию компонентов роботизированного оборудования и программные комплексы для выполнения задач автономной навигации. Далее необходимо будет создать графический интерфейс для управления роботом. Мы создадим графический интерфейс, который сможет действовать как триггер для базовых команд ROS. Вместо выполнения всех команд в терминале пользователь сможет управлять роботом с помощью графических кнопок. Графический интерфейс, который мы собираемся разработать, предназначен для типичного гостиничного номера с девятью столами. Пользователь сможет установить положение стола на карте гостиничного номера и командовать роботом для доставки еды к определенному столу. После того как еда будет доставлена, робот получит команду для возвращения в исходное положение.

Серия статей на тему: «Создание с нуля автономного мобильного обслуживающего робота с использованием Python»

  1. Начало работы с операционной системой для робота (ROS)
  2. Основные понятия роботов с дифференциальным приводом
  3. Моделирование робота с дифференциальным приводом
  4. Моделирование дифференциального привода робота, управляемого операционной системой ROS
  5. Проектирование оборудования и схем ChefBot
  6. Согласование приводов и датчиков с контроллером робота
  7. Согласование датчиков зрения с ROS
  8. Создание аппаратного обеспечения ChefBot и интеграция ПО программного обеспечения
  9. Разработка графического интерфейса для робота с использованием Qt и Python

В этой статье будут рассмотрены следующие темы:

  • установка Qt на Ubuntu;
  • введение в PyQt и PySide;
  • введение в Qt Designer;
  • сигналы и слоты Qt;
  • преобразование файла Qt UI в файл Python;
  • работа с ChefBot из графического интерфейса;
  • введение в rqt и его особенности.

Технические требования

Для тестирования приложения и кода вам понадобится Ubuntu 16.04 LTS PC/laptop с установленным ROS Kinetic.

Вы должны знать, как установить Qt, PyQt и rqt.

В настоящее время наиболее популярны два GUI-фреймворка: Qt (http://qt.digia.com) и GTK+ (http://www.gtk.org/). QT и GTK+ имеют открытые исходные коды, кроссплатформенные наборы инструментов пользовательского интерфейса и платформы разработки. Эти две программные платформы широко используются в настольных средах Linux, в оболочках GNOME и KDE.

В этой статье для реализации GUI мы будем использовать привязку Python к платформе Qt. Это объясняется тем, что привязка Python Qt более стабильна, чем другие привязки UI Python. Мы рассмотрим, как разработать графический интерфейс с нуля и запрограммировать его с помощью Python. После обсуждения основы программирования на Python и Qt мы обсудим интерфейсы ROS Qt, которые уже доступны в ROS. Но вначале следует познакомиться с QT UI framework и как его установить на ПК.

Установка Qt на Ubuntu 16.04 LTS

Qt – это кроссплатформенный фреймворк приложений, широко использующийся для разработки прикладного обеспечения с интерфейсом GUI и инструментов командной строки. Qt доступен почти во всех операционных системах, таких как Windows, macOS X, Android и т. д. Основной язык программирования, используемый для разработки приложений QT, – C++. Но есть привязки, доступные для таких языков, как Python, Ruby, Java и т. д. Давайте посмотрим, как установить QT SDK на Ubuntu 16.04. Мы установим Qt со средством предварительной упаковки (APT) в Ubuntu. APT входит в репозиторий Ubuntu. Итак, для установки Qt/Qt SDK мы можем просто использовать следующую команду, которая установит QT SDK и все необходимые зависимости из репозиториев
Ubuntu. Мы, используя следующую команду, установим Qt версии 4:

$ sudo apt-get install qt-sdk

Эта команда установит весь QT SDK и его библиотеки, необходимые для нашего проекта. Пакеты, доступные в репозиториях Ubuntu, могут быть не самыми последними версиями. Получить самую последнюю версию Qt можно, загрузив онлайн- или автономный установщик Qt для различных платформ ОС по следующей ссылке: http://qt-project.org/downloads.

После установки Qt в вашей системе мы рассмотрим, как с помощью Qt и Python можно разработать графический интерфейс.

Взаимодействие Python и Qt

Давайте посмотрим, как мы можем взаимодействовать с Python и Qt. В общем, есть два модуля, доступных в Python для подключения к пользовательскому интерфейсу Qt. Это два наиболее популярных фреймворка:

  • PyQt;
  • PySide.

PyQt

PyQt является одним из самых популярных привязок Python для кроссплатформенной Qt. PyQt разработан и поддерживается Riverbank Computing Limited. Обеспечивает привязку для Qt 4 и Qt 5 и поставляется с GPL (версия 2 или 3) вместе с коммерческой лицензией. PyQt доступен для Qt версий 4 и 5 и называется PyQt4 или PyQt5 соответственно. Эти два модуля совместимы с Python версий 2 и 3. PyQt содержит более 620 классов, охватывающих пользовательский интерфейс, XML, сеть сообщений, веб и т. д.

PyQt доступен в Windows, Linux и Mac OS X. Это обязательное условие для установки Qt SDK и Python и установки PyQt. Бинарники для Windows и Mac OS доступны по следующей ссылке: http://www.riverbankcomputing.com/software/pyqt/download.

Теперь можно рассмотреть, как установить PyQt4 на Ubuntu 16.04 с помощью Python 2.7.

Установка PyQt в Ubuntu 16.04 LTS

Для установки PyQt на Ubuntu/Linux используется следующая команда, которая установит библиотеку PyQt, ее зависимости и инструменты Qt:

$ sudo apt-get install python-qt4 pyqt4-dev-tools

PySide

PySide – это проект программного обеспечения с открытым исходным кодом, который предоставляет привязку Python для фреймворка Qt. Проект PySide был инициирован Nokia и предлагает полный набор Qt c привязкой к нескольким платформам. Техника, используемая в PySide для переноса библиотеки Qt, отличается от PyQt, но API обоих похож. PySide в настоящее время не поддерживается на Qt 5. PySide доступен для Windows, Linux и Mac OS X. Следующая ссылка поможет вам настроить PySide на Windows и Mac OS X: http://qt-project.org/wiki/Category:LanguageBindings::PySide::Downloads.

Предварительные настройки для PySide такие же, как и для PyQt. Давайте посмотрим, как мы можем установить PySide на Ubuntu 16.04 LTS.

Установка PySide в Ubuntu 16.04 LTS

Пакет PySide доступен в репозиториях пакетов Ubuntu. Следующая команда установит модуль PySide и инструменты Qt на Ubuntu:

$ sudo apt-get install python-pyside pyside-tools

Давайте начнем работу с этими модулями, чтобы увидеть различия между ними.

Установка PyQt в Ubuntu 16.04 LTS

Если вы хотите установить PyQt в Ubuntu/Linux, используйте следующую команду. Эта команда установит библиотеку PyQt, ее зависимости и некоторые инструменты Qt:

$ sudo apt-get install python-qt4 pyqt4-dev-tools

Работа с PyQt и PySide

После установки пакетов PyQt и PySide мы увидим надпись Hello World. Основное различие между PyQt и PySide только в некоторых командах; большинство шагов тождественно. Давайте посмотрим, как сделать графический интерфейс Qt и преобразовать его в код Python.

Представляем Qt Designer

Qt Designer – это инструмент для проектирования и вставки элементов управления в QT GUI. Графический интерфейс Qt – в основном это XML-файл, который содержит информацию о его компонентах и элементах управления. Первый шаг для работы с графическим интерфейсом – это его проектирование. Инструмент Qt Designer предоставляет различные варианты для качественного проектирования приложения.

Запустите Qt Designer, введя в терминал команду designer-qt 4. На следующем рисунке показано, что появится на экране после выполнения данной команды.

Qt 4 Designer
Qt 4 Designer

На предыдущем рисунке показан интерфейс QT Designer. Выберите в окне New Form опцию Widget и нажмите на кнопку Create (Создать). Будет создан новый пустой виджет. Мы можем перетащить в окно нового виджета расположенные в левой части окна QT 4 Designer различные элементы управления GUI. Виджеты Qt являются основными строительными блоками графического интерфейса Qt.

На следующем рисунке показана форма с кнопкой, которую перетащили из набора элементов управления в левой части окна Qt Designer.

Форма виджета Qt Designer
Форма виджета Qt Designer

Приложение Hello World содержит кнопку PushButton. При нажатии на эту кнопку в терминале появится сообщение Hello World. Прежде чем создать приложение Hello World, нам нужно понять, что такое сигналы и слоты Qt, так как эти функции будут использованы для создания приложения Hello World.

Сигналы и слоты Qt

В Qt события GUI обрабатываются с помощью сигналов и слотов. Когда происходит событие, GUI генерирует сигнал. Виджеты Qt имеют много ранее определенных сигналов, и пользователи могут добавлять пользовательские сигналы для событий GUI. Слот – это функция, вызываемая в ответ на конкретный сигнал. В этом примере мы используем сигнал clicked() для PushButton и создадим для него слот. Можно написать свой собственный код для этой пользовательской функции. Давайте посмотрим, как мы можем создать кнопку, подключить сигнал к слоту и преобразовать весь GUI в Python.

Вот шаги, связанные с созданием приложения Hello World GUI.

  1. Перетащите и создайте кнопку PushButton из Qt Designer в пустую форму.
  2. Назначьте слот для события нажатия кнопки, которое выдает clicked().
  3. Сохраните разработанный файл пользовательского интерфейса с расширением .ui.
  4. Конвертируйте файлы интерфейса в Python.
  5. Напишите определение пользовательского слота.
  6. Распечатайте сообщение Hello World внутри определенного слота/функции.

Мы уже перетащили кнопку из Qt Designer в пустую форму. Нажмите клавишу F4 для вставки слота на кнопку. При нажатии клавиши F4 редактируемая кнопка становится красной, и мы можем перетащить линию от кнопки и поместить символ земли (ground symbol) в основном окне. Этот процесс показан на следующем рисунке.

Назначение слотов и сигналов в Qt 4 Designer
Назначение слотов и сигналов в Qt 4 Designer

Выберите с левой стороны сигнал clicked() и нажмите кнопку Edit… для создания нового пользовательского слота. При нажатии кнопки Edit… появится еще одно окно для создания пользовательской функции. Пользовательскую функцию можно создать, щелкнув мышью на символе +.

Мы создали пользовательский слот под названием message(), как показано на расположенном ниже рисунке.

Назначение слотов и сигналов в Qt 4 Designer1
Назначение слотов и сигналов в Qt 4 Designer

Нажмите на кнопку OK и сохраните в файл UI как ***.ui, выйдите из QT Designer. После сохранения файла UI давайте посмотрим, как мы можем преобразовать файл QT UI в файл Python.

Преобразование UI-файла в код Python

После проектирования UI-файла мы можем его преобразовать в эквивалент Python-кода. Преобразование выполняется с помощью компилятора pyuic. Мы уже установили этот инструмент при установке PyQt/PySide. Ниже приведены команды для преобразования пользовательского интерфейса Qt-файла в файл Python. Необходимо использовать разные команды для PyQt и PySide.

Следующая команда преобразует UI в его PyQt-эквивалентный файл:

$ pyuic4 -x hello_world.ui -o hello_world.py

pyuic4 – это компилятор UI, который преобразовывает файл UI в его эквивалент в Python-коде. Мы должны упомянуть имя интерфейса после аргумента-х и отметить на выходе filename после аргумента -o.

В команде PySide не так много изменений. Вместо pyuic4 PySide использует pyside-uic для преобразования файлов UI в файлы Python. Остальные аргументы одинаковы:

$ pyside-uic -x hello_world.ui -o hello_world.py

Предыдущая команда создаст эквивалентный код Python для UI-файла. Если мы запустим этот код Python, появится пользовательский интерфейс, разработанный в Qt Designer. Созданный скрипт не будет содержать функции message(). Мы должны добавить эту пользовательскую функцию для генерации кода. Следующая процедура поможет добавить функцию. И когда вы нажмете на кнопку, созданная функция message() запустится.

Определение и добавление слота в код PyQt

Ниже приведен сгенерированный из PyQt код Python. Коды, сгенерированные pyuic4 и pyside-uic, не отличаются друг от друга, за исключением импорта имен модулей. Все другие части одинаковы. Объяснение кода, сгенерированного с помощью PyQt, также применимо и к коду PySide. Код, сгенерированный из приведенного выше преобразования, выглядит следующим образом. Код, структура и параметры могут меняться в зависимости от созданного вами UIфайла:

from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8(«Form»))
Form.resize(514, 355)
self.pushButton = QtGui.QPushButton(Form)
self.pushButton.setGeometry(QtCore.QRect(150, 80, 191, 61))
self.pushButton.setObjectName(_fromUtf8(«pushButton»))
self.retranslateUi(Form)
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8(«clicked()»)),
Form.message)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate(«Form», «Form», None, QtGui.
QApplication.UnicodeUTF8))
self.pushButton.setText( QtGui.QApplication.translate(«Form», «Press», None, QtGui.
QApplication.UnicodeUTF8))
if __name__ == «__main__»:
import sys
app = QtGui.QApplication(sys.argv)
Form = QtGui.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())

Предыдущий код является эквивалентным скриптом Python UI файла Qt, который мы разработали в приложении QT designer. Ниже приведена пошаговая процедура работы данного кода.

1. Выполнение кода начнется с if __name__ == «__main__»:. Первый в коде PyQt создает объект QApplication. Класс QApplication содержит основной цикл обработки событий, в котором обрабатываются и отправляются все события из системы Windows и других источников. Он также обрабатывает инициализацию и завершение приложения. Класс QApplication находится внутри модуля QtGui. Этот код создает объект QApplication с именем app. Основной код мы должны добавить вручную.

2. Строка Form = QtGui.QWidget() создает объект с именем Form из класса QWidget, который присутствует внутри модуля QtGui. Класс QWidget – это базовый класс всех объектов пользовательского интерфейса Qt. Он может получить события мыши и события клавиатуры от основной системы Windows.

3. Строка ui = Ui_Form() создает объект с именем ui из класса Ui_Form(), определяемый в данном коде. Объект Ui_Form() может принимать класс QWidget, который мы создали в предыдущей строке. Он может добавлять кнопки, текст, кнопку управления и другие компоненты пользовательского интерфейса в объекте QWidget. В классе Ui_Form() содержатся две функции: setupUi() и retranslateUi(). Можно передать объекту QWidget функции setupUi(). Эта функция добавит такие компоненты пользовательского интерфейса для этого объекта виджета, как кнопки, назначение слотов для сигналов и т.д. При необходимости в функции retranslateUi() будет переводиться язык UI на другие языки. Например, если нам нужно перевести с английского на испанский, можно в этой функции отметить соответствующее испанское слово.

4. Строка Form.show() отображает конечный результат – окно с кнопками и текстом. Далее нужно создать слот функции, которая печатает сообщение Hello World. Определение слота создается внутри класса Ui_Form(). Следующие шаги вставят слот с именем message() в класс Ui_Form().

Определение функции message() выглядит следующим образом:

def message(self):
print «Hello World»

Это должно быть вставлено как функция внутри класса Ui_Form(). Кроме того, измените следующую строку в функции setupUi() внутри класса Ui_Form():

QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8(«clicked()»)), Form.message)

Параметр Form.message должен быть заменен на параметр self.message. Предыдущая строка соединяет сигнал PushBbutton функции clicked() со слотом self.message(), который мы уже вставили в класс Ui_Form().

Работа с приложением Hello World GUI

После замены параметра Form.message параметром self.message мы можем выполнить код, и результат будет выглядеть следующим образом:

Запуск приложения Pyqt4
Запуск приложения Pyqt4

Когда мы нажимаем на кнопку Press, приложение будет печатать в терминале сообщение Hello world. Это все, что нужно знать о настройке GUI с Python и Qt.

В следующей части статьи мы рассмотрим GUI, который нужно разработать для робота.

ChefBot – управление с помощью графического интерфейса

После завершения работы приложения Hello World в PyQt обсудим графический интерфейс для управления ChefBot. Основное использование построения GUI – это создание более простого способа управления роботом. Человек, управляющий этим роботом, не должен знать комплекс команд для запуска и остановки этого устройства. Создание GUI для ChefBot облегчит управление роботом. Мы планируем создать графический интерфейс с помощью PyQt, ROS и интерфейса Python. Пакет Chef BotROS доступен на GitHub по следующей ссылке:

https://github.com/qboticslabs/Chefbot_ROS_pkg.git.

Если вы еще не скопировали код, то можете сделать это с помощью следующей команды:

$ git clone https://github.com/qboticslabs/Chefbot_ROS_pkg.git

Код GUI с именем robot_gui.py помещается в папку scripts, которая находится внутри пакета chefbot_bringup.

Следующий рисунок показывает интерфейс, который был разработан для ChefBot.

Запуск приложения Pyqt4
Запуск приложения Pyqt4

Графический интерфейс имеет следующие функции:

  • контроль состояния батареи робота. В поле Robot status (Состояние робота) будут показаны обнаруженные роботом ошибки;
  • в поле ввода Table (Стол) указывается номер стола, к которому требуется подвезти еду. В данном приложении предусмотрено наличие девяти столов, но это значение можно изменить, исходя из фактического количества столов в помещении. После ввода номера стола дается команда на движение по маршруту от фактического положения робота к целевому столу. Для этого достаточно нажать кнопку Go (Ехать). Чтобы вернуть робота в исходную позицию, следует нажать кнопку Home (Домой). Для отмены команды нажмите кнопку Отмена (Canсel).

Это приложение работает следующим образом.

Прежде всего необходимо создать карту помещения. После создания карту следует сохранить в памяти бортового ПК. Робот создает карту один раз. Далее запускаются процедуры локализации и навигации. Пакет ChefBot ROS поставляется с картой и имитационной моделью помещения гостиницы. Теперь, чтобы протестировать GUI, мы можем запустить моделирование и локализацию. Позже обсудим, как управлять роботом с помощью графического интерфейса. Если вы установите пакеты ChefBot ROS местной системы, то сможете сымитировать окружающую среду и проверить работу GUI.

Для запуска имитации ChefBot в помещении используйте следующую команду:

$roslaunch chefbot_gazebo chefbot_hotel_world.launch

После запуска моделирования ChefBot мы можем запустить процедуры локализации и навигации, используя уже построенную карту. Карта находится внутри пакета карт chefbot_bringup. Мы воспользуемся этой картой для выполнения данного теста. Для загрузки программы локализации и навигации выполните следующую команду:

$ roslaunch chefbot_gazebo amcl_demo.launch map_file:=/home/lentin/catkin_ws/src/chefbot/chefbot_bringup/map/hotel1.yaml

В вашей системе путь к файлу карты может быть другим. Поэтому в вашей системе необходимо использовать фактический путь сохранения файла.

Если вы указали правильный путь, робот начнет выполнение стека ROSнавигации. Чтобы увидеть положение робота на карте или вручную установить начальное положение робота, запустите RViz, используя следующую команду:

$ roslaunch chefbot_bringup view_navigation.launch

В RViz с помощью кнопки 2D Nav Goal мы можем приказать роботу перейти к любым координатам карты.

Мы можем приказать роботу перейти к любым координатам карты, используя инструменты программирования. Стек навигации ROS работает с помощью библиотеки ROS actionlib. Библиотека ROS actionlib предназначена для выполнения выделенных задач, это имитатор ROS Services. Преимущество над услугами ROS заключается в том, что мы можем отменить запрос в любое время.

В графическом интерфейсе мы можем приказать роботу перейти по карте по координатам, используя библиотеку actionlib Python. Применяя данный метод, мы можем получить положение требуемого стола на карте.

После запуска симулятора и узлов AMCL запустите удаленное управление и с помощью клавиатуры перемещайте робот рядом с каждым столом. Используйте следующую команду, чтобы перемещать и разворачивать робот:

$ rosrun tf tf_echo /map /base_link

После нажатия кнопки Go эта позиция подается в стек навигации. Робот планирует свой путь и достигает заданной цели. Задание можно отменить в любое время. Так, графический интерфейс ChefBot действует как клиент actionlib, который отправляет координаты карты на сервер actionlib, то есть как стек навигации.

Мы можем запустить GUI для управления роботом, используя следующую команду:

$ rosrun chefbot_bringup robot_gui.py

Можно выбрать номер стола и для перемещения робота нажать на кнопку Go.

Мы предполагаем, что файлы были скопированы, а файл robot_gui.py открыт. В этом случае мы можем обсудить главные слоты, которые были добавлены в класс Ui_Form() для клиента actionlib и получения значения уровня заряда батареи и состояния робота.

Для этого нам нужно импортировать следующие модули Python для GUIприложений:

import rospy
import actionlib
from move_base_msgs.msg import *
import time
from PyQt4 import QtCore, QtGui

Дополнительные модули мы вызываем из клиента ROS Python: rospy и actionlib для отправки значений в стек навигации. Модуль move_base_msgs содержит определение сообщения цели, которое должно быть отправлено в стек навигации.

Позиция робота возле каждого стола упоминается в словаре Python. Следующий код показывает значения hardcode позиции робота возле каждого стола:

table_position = dict()
table_position[0] = (-0.465, 0.37, 0.010, 0, 0, 0.998, 0.069)
table_position[1] = (0.599, 1.03, 0.010, 0, 0, 1.00, -0.020)
table_position[2] = (4.415, 0.645, 0.010, 0, 0, -0.034, 0.999)
table_position[3] = (7.409, 0.812, 0.010, 0, 0, -0.119, 0.993)
table_position[4] = (1.757, 4.377, 0.010, 0, 0, -0.040, 0.999)
table_position[5] = (1.757, 4.377, 0.010, 0, 0, -0.040, 0.999)
table_position[6] = (1.757, 4.377, 0.010, 0, 0, -0.040, 0.999)
table_position[7] = (1.757, 4.377, 0.010, 0, 0, -0.040, 0.999)
table_position[8] = (1.757, 4.377, 0.010, 0, 0, -0.040, 0.999)
table_position[9] = (1.757, 4.377, 0.010, 0, 0, -0.040, 0.999)

Мы можем получить доступ к позиции робота возле каждого стола, обратившись к этому словарю.

В настоящее время для демонстрации мы вставили только четыре значения. Вы можете добавить дополнительные значения, определив положение других столов.

Далее необходимо назначить некоторые переменные для обработки: номер стола, положение робота и клиента actionlib внутри класса Ui_Form().

#Номер стола
self.table_no = 0
#Сохраняет текущее положение робота у стола
self.current_table_position = 0
#Создание клиента Actionlib
self.client = actionlib.SimpleActionClient(‘move_base’,MoveBaseAction)
#Создание сообщения цели
self.goal = MoveBaseGoal()
#Запустите эту функцию для обновления состояния батареи и робота
self.update_values()

В следующем коде показаны назначение сигналов и слотов в этом коде для кнопок и счетчик виджета:

#Обработчик сигнала и назначение слота set_table_number()
QtCore.QObject.connect(self.spinBox, QtCore.SIGNAL(_fromUtf8(«valueChanged(int)»)), self.
set_table_number)
#Обрабатывать сигнал кнопки Home и назначить слот Home()
QtCore.QObject.connect(self.pushButton_3, QtCore.SIGNAL(_fromUtf8(«clicked()»)), self.Home)
#Обрабатывать сигнал кнопки Go и назначить слот Go()
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8(«clicked()»)), self.Go)
#Обрабатывать сигнал кнопки Cansel () и назначить слот Cancel()
QtCore.QObject.connect(self.pushButton_2, QtCore.SIGNAL(_fromUtf8(«clicked()»)), self.Cancel)

Следующий слот обрабатывает значение спин-бокса из пользовательского интерфейса и назначает номер стола. Также он преобразовывает номер стола в соответствующие координаты положения робота:

def set_table_number(self):
self.table_no = self.spinBox.value()
self.current_table_position = table_position[self.table_no]

Ниже дано определение слота Go для кнопки Go. Эта функция вставит в положение робота положение выбранного стола в заголовок сообщения цели и отправит его в стек навигации:

def Go(self):
#Присвоение X, Y и Z позиции и ориентации на target_pose сообщением self.goal.target_
pose.pose.position.x=float(self.current_table _position[0])
self.goal.target_pose.pose.position.y=float(self.current_table _position[1])
self.goal.target_pose.pose.position.z=float(self.current_table _position[2])
self.goal.target_pose.pose.orientation.x = float(self.current_table_position[3])
self.goal.target_pose.pose.orientation.y= float(self.current_table_position[4])
self.goal.target_pose.pose.orientation.z= float(self.current_table_position[5])
# ID фрейма
self.goal.target_pose.header.frame_id= ‘map’
# Отметка времени
self.goal.target_pose.header.stamp = rospy.Time.now()
# Отправка цели в стек навигации
self.client.send_goal(self.goal)

Приведенный ниже код является определением слота Cancel(). Он отменит всю задачу робота, которая планировалась к выполнению.

def Cancel(self):
self.client.cancel_all_goals()

Следующий код определяет функцию Home(). Данная функция обнуляет положение стола и вызывает функцию Go(). При этом текущим положением робота считается позиция обнуленного стола:

def Home(self):
self.current_table_position = table_position[0]
self.Go()

Следующие определения относятся к функциям update_values() и add(). Метод update_values() начнет обновление уровня заряда батареи и состояния робота в потоке. Функция add() извлекает параметры ROS состояния батареи и состояния робота и устанавливает их на индикаторе выполнения и индикаторе батареи:

def update_values(self):
self.thread = WorkThread()
QtCore.QObject.connect( self.thread, QtCore.SIGNAL(«update(QString)»), self.add )
self.thread.start()
def add(self,text):
battery_value = rospy.get_param(«battery_value»)
robot_status = rospy.get_param(«robot_status»)
self.progressBar.setProperty(«value», battery_value)
self.label_4.setText(_fromUtf8(robot_status))

Ниже приведен класс WorkThread(), используемый в предыдущей функции, Класс WorkThread() наследуется от QThread, предоставляемого Qt для организации многопоточности. Поток с определенной задержкой выдает обновление сигнала (Qstring). Предшествующая функция update_values() сигнала update(QString) подключена к слоту self.add(), и когда обновление сигнала (QString) испускается из потока, будет вызван слот add() и начнется обновление значения состояния аккумулятора:

class WorkThread(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
def __del__(self):
self.wait()
def run(self):
while True:
time.sleep(0.3) # artificial time delay
self.emit( QtCore.SIGNAL(‘update(QString)’), » » )
return

Мы обсудили, как сделать графический интерфейс для ChefBot, но этот GUI только для пользователя, управляющего роботом ChefBot. Для отладки и проверки данных робота следует применить другие инструменты. ROS предоставляет отличный инструмент отладки для визуализации данных робота.

Инструмент rqt – это популярный инструмент ROS. Он основан на Qt-based framework для GUI для ROS. Давайте обсудим инструмент rqt, процедуру установки и то, как мы можем проверить данные датчика от робота.

Установка и работа с rqt в Ubuntu 16.04 LTS

Инструмент rqt – это программный фреймворк в ROS, реализующий различные графические инструменты в виде подключаемых модулей. Мы можем добавить плагины в качестве закрепляемых окон в rqt.

Установка rqt в Ubuntu 16.04 может выполняться с помощью следующей команды. Перед установкой убедитесь, что у вас установлена полная версия ROS Kinetic.

$ sudo apt-get install ros-<ros_version>-rqt

После установки пакетов rqt мы можем получить доступ к реализации GUI rqt под названием rqt_gui, в котором мы можем закрепить плагины rqt в одном окне.

Перед запуском rqt_gui выполните в терминале команду roscore:

$ roscore

Выполните следующую команду, чтобы запустить rqt_gui:

$ rosrun rqt_gui rqt_gui

При правильной работе команд мы получим следующее окно:

Запуск rqt
Запуск rqt

Плагины мы можем загружать и выгружать во время выполнения. Для анализа сообщений ROS следует загрузить плагин Console из Plugins → Logging → Console. В следующем примере мы загружаем подключаемый модуль консоли и запускаем узел talker внутри rospy_tutorials, который отправит сообщение Hello World в тему (Topic) под названием /chatter.

Для запуска узла talker.py выполните следующую команду:

$rosrun rospy_tutorials talker.py

На расположенном ниже рисунке rqt_gui загружается с двух плагинов под именем Console и Topic Monitor. Плагин Topic Monitor загружается из Plugins → Topics → Topic Monitor. Плагин Console отслеживает печать сообщений на каждом узле и степень их важности. Это очень полезно для отладки. На этом рисунке левая часть rqt_gui загружается с плагином Console, а правая часть – с Topic Monitor. Topic Monitor перечислит доступные темы и проконтролирует их значения.

На расположенном ниже рисунке подключаемый модуль Console отслеживает узел сообщения talker.py и их уровень серьезности (важности), тогда как Topic Monitor отслеживает значение внутри темы /chatter.

Запуск rqt с различными плагинами
Запуск rqt с различными плагинами

Мы также можем визуализировать такие данные, как изображения и графики на rqt_gui. Для навигации и проверки робота существуют плагины для встраивания RViz в rqt_gui. Плагин Navigation viewer просматривает тему /map. Визуализация плагина доступна в Plugin → Visualization.

Итоги

Вот и закончилась наша серия статей о создании с нуля автономного мобильного обслуживающего робота. В этой статье мы обсудили создание GUI для управления ChefBot обычным пользователем, который не знает, как работает этот робот. Мы использовали привязку Python Qt под названием PyQt для создания данного графического интерфейса. Прежде чем мы перешли к проектированию GUI, мы, чтобы облегчить понимание PyQt, в качестве примера рассмотрели создание приложения Hello World. Пользовательский интерфейс создавался с помощью QT Designer, а файл UI с помощью компилятора UI Python был преобразован в эквивалентный скрипт Python. После проектирования основного GUI в QT Designer мы конвертировали файл UI в скрипт Python и вставили в него необходимые слоты. Для запуска робота следует в графическом интерфейсе задать номер стола, к которому должен переместиться робот, и отдать приказ на движение. В карте отмечено положение каждого стола. Карта зашита в скрипте Python и может быть использована для тестирования. После выбора целевого стола мы определяем положение робота на карте, и когда нажмем кнопку Go, робот начнет движение в целевую точку. Пользователь может отменить операцию в любое время, и робот после отмены должен вернуться в исходное положение. При необходимости GUI может в реальном времени получать данные о состоянии аккумуляторной батареи и самого робота. После обсуждения графического интерфейса был рассмотрен инструмент отладки GUI в ROS. Этот инструмент называется rqt. Также были рассмотрены некоторые плагины, используемые для отладки данных, получаемых от робота. 

За основу данной статьи взята книга Д. Лентина «Изучение робототехники с использованием Python» 

С Уважением, МониторБанк

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *