Создание аппаратного обеспечения ChefBot и интеграция ПО программного обеспечения

Создание аппаратного обеспечения ChefBotВ третьей статье «Моделирование робота с дифференциальным приводом с помощью ROS и URDF» мы рассмотрели конструкцию шасси ChefBot. В этой же статье мы расскажем, как, используя эти детали, данный робот собрать. Также мы рассмотрим окончательное сопряжение датчиков и других электронных компонентов робота с микропроцессором Tiva-C LaunchPad. После подключения мы объясним, как настроить взаимодействие робота с ПК и с помощью SLAM и AMCL осуществить автономную навигацию.

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

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

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

  • оборудование для создания ChefBot;
  • настройка ChefBot ПК и пакетов;
  • взаимодействие датчиков ChefBot с Tiva-C LaunchPad;
  • встроенный код для ChefBot;
  • понимание пакетов ROS ChefBot;
  • реализация SLAM на ChefBot;
  • автономная навигация в ChefBot.

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

Для тестирования приложения и кодов в этой статье вам понадобится Ubuntu 16.04 LTS, ПК/ноутбук с установленным пакетом Ros Kinetic.

Вам для сборки робота понадобятся изготовленные ранее детали шасси.

У вас должны быть все датчики и другие аппаратные компоненты, которые должны быть установлены в роботе.

Мы уже обсуждали взаимодействие отдельных компонентов робота и датчиков с микропроцессором Tiva-C LaunchPad. В этой статье мы настроим взаимодействие между компонентами робота и датчиками ChefBot. Далее запрограммируем робот так, чтобы он получал значения от всех датчиков и обменивался с ПК информацией, позволяющей управлять роботом. LaunchPad отправит все значения, получаемые от датчиков через серийный порт, бортовому персональному компьютеру и в ответ получит управляющую информацию (команды возврата, данные о скорости и т. д.) от ПК.

После получения значений датчиков с ПК узел Ros Python получит последовательные значения и преобразует его в ROS-темы. В инсталлированном в бортовом ПК программном обеспечении имеются узлы Python, записывающие данные датчиков и одометра. Чтобы вычислить одометрию робота, данные энкодеров колеса и значения IMU объединяются. Робот обнаруживает препятствия, подписавшись к ультразвуковой теме датчика и развертке лазера и используя узел PID, контролирует скорость вращения двигателя колеса. Этот узел преобразует команду линейной скорости в команду дифференциальной скорости колеса. После запуска этих узлов мы запустим SLAM-отображения карты помещения, а после запуска SLAM будут запущены узлы AMCL для локализации и автономной навигации.

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

Сборка ChefBot из ранее изготовленных деталей и комплектующих

Нижнее основание робота представляет собой круглую плиту с вырезами для колес. На основании закреплены два ведущих двигателя, к валам редукторов которых через ступицы прикреплены ведущие колеса. Кроме этого, к основанию прикреплены два опорных колеса и стойки для крепления средней плиты. На следующем рисунке показан вид плиты основания сверху и снизу с установленными комплектующими.

Опорная плита с двигателями, ведущими и опорными колесами
Опорная плита с двигателями, ведущими и опорными колесами

Как уже упоминалось в третьей статье «Моделирование робота с дифференциальным приводом с помощью ROS и URDF», радиус опорной плиты – 150 мм. Двигатели постоянного тока со встроенными редукторами закреплены с противоположных сторон опорной плиты. Под ведущие колеса в опорной плите предусмотрены вырезы. Опорные колеса установлены по краям опорной пластины, по оси, проведенной между центрами опорных колес по отношению к линии оси вращения ведущих колес под углом в 90°. Такое расположение опорных колес обеспечит хороший баланс и поддержку робота. Как уже упоминалось, опорные колеса могут быть разных конструкций: шариковые опоры или поворотные колеса с резиновой поверхностью качения. Провода от двух двигателей и энкодеров выводятся наверх через отверстие в центре опорной плиты. Наш робот трехуровневый и состоит из опорной плиты, средней и верхней плит. Средняя плита соединяется с опорной плитой через четыре опорные стойки. В третьей статье «Моделирование робота с дифференциальным приводом» были предложены конструкция и чертеж стоек из цельного алюминиевого прутка с резьбовыми отверстиями на торцах. Такая же конструкция у стоек, соединяющих среднюю и верхнюю плиты. Чтобы соединить пакет, состоящий из верхней части нижних опорных стоек – средней плиты – нижней части верхних опорных стоек, предлагается в верхнее резьбовое отверстие нижних стоек вкрутить резьбовые шпильки, надеть на них среднюю опорную плиту и на выступающую часть шпильки накрутить верхние опорные стойки. Вместо цельных опорных стоек можно использовать полые трубки с запрессованными втулками, в центре которых – резьбовое отверстие. Ниже показаны: средняя плита (без отверстия в центре для прокладывания проводов от датчика Kinnect или Astra); полые трубки; полые трубки с запрессованными резьбовыми втулками. В левом нижнем углу показана собранная конструкция, состоящая из опорной плиты, стоек, средней плиты, двигателей с ведущими колесами и опорными колесами.

Средняя плита и опорные стойки
Средняя плита и опорные стойки
Полностью собранный корпус робота
Полностью собранный корпус робота

На основании крепятся печатная плата (PCB) и аккумулятор. На среднюю плиту устанавливается блок датчиков Kinect/Orbecc и Intel NUC. При необходимости можно установить динамик и микрофон. Верхняя плита предназначена для полезной нагрузки. На следующем рисунке показан прототип печатной платы робота. На этой плате установлена плата микроконтроллера Tiva C LaunchPad, драйвера двигателя, линейных переключателей, компонентов для обеспечения управления двумя двигателями, ультразвуковым датчиком и IMU.

Прототип PCB ChefBot
Прототип PCB ChefBot

Плата запитывается напряжением в 12 В, которое подается с аккумулятора, расположенного на опорной плите. Двигатели подключаются к разъемам Двигатель 1 и Двигатель 2. Бортовой ПК и датчики Kinect размещены на средней плите. Плата микроконтроллера LaunchPad и датчики Kinect подключаются ПК через USB. ПК и Kinect питаются от того же аккумулятора напряжением 12 В. Можно использовать свинцово-кислотный или литий-полимерный аккумулятор. В конструкции был использован свинцово-кислотный аккумулятор. Литий-полимерный аккумулятор более эффективен, и в дальнейшем им можно заменить свинцово-кислотную батарею. На следующем рисунке показана полностью собранная конструкция робота ChefBot.

Полностью собранный робот
Полностью собранный робот

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

Конфигурирование бортового компьютера ChefBot и установка пакетов ChefBot ROS

Как уже говорилось ранее, в ChefBot в качестве бортового компьютера был использован компьютер NUC Intel. Его назначение – получение и обработка данных с датчиков и выработка команд управления роботом при движении. После того как будет куплен персональный компьютер NUC Intel, следует установить на него операционную систему Ubuntu 16.04.LTS. После установки Ubuntu установите полный дистрибутив ROS и его пакеты, о которых мы упоминали в предыдущих статьях. Компьютер устанавливается на среднюю плиту робота и подключается к его электронным компонентам после предварительной настройки отдельно от робота. Ниже приведены процедуры для установки пакетов ChefBot на ПК NUC.

Скопируйте программные пакеты ChefBot из GitHub, используя следующую команду:

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

Этот код можно клонировать на вашем компьютере, после чего скопировать папку chefbot на бортовой ПК Intel NUC. Папка chefbot состоит из пакетов ROS ChefBot. Создайте в бортовом ПК NUC рабочее пространство ROS catkin, скопируйте папку chefbot и переместите ее в каталог src рабочей области catkin.

Создайте и установите исходный код ChefBot, используя нижеприведенную команду. Команда должна быть выполнена в созданном нами рабочем пространстве catkin:

$ catkin_make

Если все зависимости в бортовом компьютере NUC установлены правильно, то пакеты ChefBot будут собраны и установлены в этой системе. После установки пакетов ChefBot на бортовом ПК NUC мы можем переключиться на встроенный код для ChefBot. После этого подключите все датчики в LaunchPad. После загрузки кода в LaunchPad мы можем снова рассмотреть запуск пакетов ROS. Скопированный код из GitHub содержится в микропроцессоре Tiva C LaunchPad. Этот код мы рассмотрим в следующей части статьи.

Согласование датчиков ChefBot с Tiva C LaunchPad

Мы обсудили взаимодействие отдельных датчиков, которые будут использованы в ChefBot. В этой части мы обсудим, как подключить и настроить датчики с микроконтроллером Tiva C LaunchPad. Код Energia для программирования Tiva C LaunchPad доступен на клонированных файлах в GitHub. Схема подключения микроконтроллера LaunchPad Tiva C с датчиками показана на следующем рисунке.

Читать также:  Структура данных стека в C++

Диаграмма сопряжения датчиков ChefBot
Диаграмма сопряжения датчиков ChefBot

На показанной схеме M1 и M2 обозначают два двигателя дифференциального привода. Это коллекторные двигатели постоянного тока со встроенными энкодерами и редуктором от Pololu. Двигатели подключены к драйверу VNH2SP30 от Pololu. Один из двигателей подключен к схеме в обратной полярности по отношению к другому двигателю, так как в дифференциальном управлении направлением движения один двигатель по отношению к другому вращается в противоположную сторону. Драйвер двигателя подключен к Tiva C LaunchPad через 3,3–5 В двунаправленный преобразователь уровня напряжения. Один из преобразователей, который будет использован, доступен по адресу: https://www.sparkfun.com/products/12009.

Два канала каждого энкодера соединены с LaunchPad через преобразователь уровней. В настоящее время мы используем один ультразвуковой датчик для обнаружения препятствий. В будущем число датчиков при необходимости можно увеличить. Чтобы получить качественные данные одометрии, необходимо подключить датчик MPU 6050 IMU через интерфейс I2C. Данный датчик сразу подключается к LaunchPad, так как питание MPU6050 равно 3,3 В. Для сброса в LaunchPad узлов ROS в первоначальное состояние мы выделим один вывод в качестве выхода и подключимся к контакту reset микроконтроллера. Когда определенный символ отправляется в LaunchPad, он установит на этом контакте значение HIGH и сбросит устройство. В некоторых ситуациях может накапливаться ошибка, что может повлиять на навигацию робота. Чтобы сбросить эту ошибку, требуется выполнить сброс LaunchPad.

Еще один контакт будет выделен для контроля уровня заряда батареи. Пока эта функция в Energia не реализована.

Код, загруженный с GitHub, состоит из встроенного кода. Здесь мы можем рассмотреть основной раздел кода. Объяснять все его разделы нет необходимости, так как это уже было рассмотрено ранее.

Встроенный код для ChefBot

Основные разделы кода LaunchPad будут обсуждаться здесь. Ниже приведены заголовочные файлы, используемые в коде:

// Библиотека для связи с устройствами I2C
#include «Wire.h»
//I2C-библиотека связи для MPU6050
#include «I2Cdev.h»
// Библиотека для взаимодействия MPU6050
#include «MPU6050_6Axis_MotionApps20.h»
// Обработка входящих последовательных данных
#include <Messenger.h>
// Содержит определение максимальных пределов различных типов данных
#include <limits.h>

Основные библиотеки, используемые в этом коде, предназначены для связи с MPU 6050 и обрабатывают входящие в LaunchPad последовательные данные. MPU 6050 может обеспечить ориентацию в значениях кватерниона или Эйлера с помощью встроенного Digital Motion Processor (DMP). Функции доступа к DMP записываются в MPU6050_6_MotionApps 20.h. Эта библиотека имеет зависимости, такие как I2Cdev.h и Wire.h. Эти две библиотеки используются для I2C-коммуникации. Библиотека Messenger.h позволяет обрабатывать поток текстовых данных из любого источника и помогает извлечь из него данные. Библиотека limits.h содержит определения максимальных пределов различных типов данных.

После включения заголовочных файлов необходимо с помощью класса Messenger создать объект для обработки MPU6050 и входящих последовательных данных:

// Создание объекта MPU6050
MPU6050 accelgyro(0x68);
// Сообщение объекта
Messenger Messenger_Handler = Messenger();

После объявления объекта messenger основной раздел должен назначить контакты для драйвера мотора, энкодера, ультразвукового датчика, MPU 6050, reset и контакты для батареи. После назначения контактов из кода мы переходим к функции setup(). Определение функции setup() приведено здесь:

// Функции по заданию последовательного порта, энкодеров, ультразвука, MPU6050 и Reset
void setup()
{
// Иницилизируем последовательную связь со скоростью передачи 115200
Serial.begin(115200);
// Запуск энкодеров
SetupEncoders();
// Запуск моторов
SetupMotors();
// Запуск ультразвука
SetupUltrasonic();
// Запуск MPU 6050
Setup_MPU6050();
// Запуск пина Reset
SetupReset();
// Настройка обработчика объектов Messenger
Messenger_Handler.attach(OnMssageCompleted);
}

Предыдущая функция содержит пользовательскую процедуру для настройки и выделения контактов для всех датчиков. Эта функция инициализирует последовательную связь со скоростью передачи данных 115 200 бод и назначает контакты для энкодера, драйвера, ультразвукового датчика и MPU6050. Функция SetupReset() назначит pin-код для сброса устройства, как показано в схеме соединений. Мы уже в предыдущих статьях рассматривали процедуры настройки каждого датчика. Поэтому повторно объяснять определение каждой функции нет никакой необходимости. Обработчик класса Messenger привязан к функции Onmessagecomplete(), которая будет вызываться при вводе данных в Messenger_Handler.

Ниже, в коде, приводится функция loop(). Основная цель этой функции – прочитать и обработать серийные данные и отправить доступные значения датчика:

void loop()
{
// Чтение с порта Serial
Read_From_Serial();
// Отправьте данные по времени через последовательный порт
Update_Time();
// Отправьте значения энкодера через последовательный порт
Update_Encoders();
// Отправьте значения ультразвукового датчика через последовательный порт
Update_Ultra_Sonic();
// Обновите значения скорости двигателя с соответствующей скоростью, полученной от ПК,
// и отправьте значения скорости через последовательный порт
PC and send speed values through serial port
Update_Motors();
// Отправьте значения MPU 6050 через последовательный порт
Update_MPU6050();
// Отправьте значения аккумулятора через последовательный порт
Update_Battery();
}

Функция Read_From_Serial() предназначена для считывания последовательных данных с бортового ПК и данных с Messenger_Handler для их обработки. Функция Update_Time() уточняет время после каждого действия на плате управления. Мы можем взять это значение времени для обработки в бортовой ПК или вместо этого значения времени использовать внутреннее время ПК.

Мы можем скомпилировать код в ENERGIA IDE и записать его в LaunchPad. После загрузки кода можно обсудить узлы ROS для обработки значения датчиков в LaunchPad.

Написание драйвера Ros Python для ChefBot

После загрузки встроенного кода в LaunchPad следующий шаг – это обработка получаемых из LaunchPad последовательных данных и их конвертирование для дальнейшей обработки в темы ROS. Драйвер узла Launchpad_node.py взаимодействует с Tiva C LaunchPad через ROS. Файл launchpad_node.py находится внутри пакета ChefBot_bringup, в папке script. Далее последует объяснение важных разделов кода launchpad_node.py:

# Клиент ROS Python
import rospy
import sys
import time
import math
# Этот модуль python помогает получать значения из последовательного порта, которые
# выполняются в потоке
from SerialDataGateway import SerialDataGateway
# Импорт необходимых типов данных ROS для кода
from std_msgs.msg import Int16,Int32, Int64, Float32,String, Header, UInt64
# Импорт данных ROS для IMU
from sensor_msgs.msg import Imu

Файл Launchpad_node.py импортирует предыдущие модули. Основной модуль – SerialDataGateway. Это пользовательский модуль, написанный для получения последовательных потоковых данных с LaunchPad. Нам также понадобятся некоторые типы данных ROS, чтобы отрегулировать данные датчиков. Основная функция узла задается в следующем фрагменте кода:

if __name__ ==’__main__’:
rospy.init_node(‘launchpad_ros’,anonymous=True)
launchpad = Launchpad_Class()
try:
launchpad.Start()
rospy.spin()
except rospy.ROSInterruptException:
rospy.logwarn(«Error in main function»)
launchpad.Reset_Launchpad()
launchpad.Stop()

Основной класс этого узла называется Launchpad_Class(). Этот класс содержит все методы запуска, остановки и преобразования последовательных данных в разделы ROS. В главной функции мы создадим объект Launchpad_Class(). После создания объекта можно будет вызывать метод Start(), который запустит последовательную связь между Tiva C LaunchPad и бортовым ПК. Если мы с помощью комбинации клавиш Ctrl+C прервем узел драйвера, он будет сброшен в LaunchPad и остановит последовательную связь между
ПК и LaunchPad.

Следующий фрагмент кода содержит функции конструктора Launchpad_Class(). Здесь мы подключаемся к порту и настраиваем скорость передачи данных LaunchPad из параметров ROS и с помощью тех же параметров инициализируем SerialDateGateway. Объект _HandleReceivedLine() из SerialDataGateway – функция внутри этого класса, которая запускается при условии, когда любые входящие последовательные данные поступают на последовательный порт.

Эта функция будет обрабатывать каждую строку последовательных данных: извлекать, преобразовывать и вставлять ее в соответствующие заголовки каждого типа данных темы ROS:

# Получаем последовательный порт и скорость передачи данных Tiva C Launchpad
port = rospy.get_param(«~port», «/dev/ttyACM0»)
baudRate = int(rospy.get_param(«~baudRate», 115200))
#################################################################
rospy.loginfo(«Starting with serial port: » + port + «, baud rate: » + str(baudRate))
# Инициализация объекта SerialDataGateway с последовательным портом, скоростью передачи
# и функцией обратного вызова для обработки
self._SerialDataGateway = SerialDataGateway(port,baudRate, self._HandleReceivedLine)
rospy.loginfo(«Started serial communication»)
#################################################################
##Подписки и публикации
Publisher for left and right wheel encoder values
self._Left_Encoder = rospy.Publisher(‘lwheel’,Int64,queue_size = 10)
self._Right_Encoder = rospy.Publisher(‘rwheel’,Int64,queue_size = 10)
# Публикация уровня аккумулятора
self._Battery_Level = rospy.Publisher(‘battery_level’,Float32,queue_size = 10)
# Публикация расстояния до ультразвукового датчика
self._Ultrasonic_Value = rospy.Publisher(‘ultrasonic_distance’,Float32,queue_size = 10)
# Публикация значений кватерниона вращения от IMU
self._qx_ = rospy.Publisher(‘qx’,Float32,queue_size = 10)
self._qy_ = rospy.Publisher(‘qy’,Float32,queue_size = 10)
self._qz_ = rospy.Publisher(‘qz’,Float32,queue_size = 10)
self._qw_ = rospy.Publisher(‘qw’,Float32,queue_size = 10)
# Публикация последовательных данных целиком
self._SerialPublisher = rospy.Publisher(‘serial’, String,queue_size=10)

Мы создадим объект ROS publisher для таких датчиков, как энкодер, IMU и ультразвуковой датчик, а также совокупность последовательных данных для отладки. Кроме этого, подпишемся на скоростные команды для управления левым и правым двигателями робота. Когда скоростная команда поступает в тему, она создает соответствующие обратные вызовы для отправки команд скорости на микроконтроллер LaunchPad:

self._left_motor_speed = rospy.Subscriber (‘left_wheel_
speed’, Float32, self._Update_Left_Speed)
self._right_motor_speed = rospy.Subscriber (‘right_wheel_
speed’, Float32, self._Update_Right_Right)

После установки узла драйвера ChefBot нам нужно подключить робота к навигационному стеку ROS для выполнения автономной навигации. Базовое требование для выполнения автономной навигации состоит в том, чтобы узлы драйвера робота получали скоростные команды из навигационного стека ROS. Робот может управляться с помощью дистанционного управления. В дополнение к этим требованиям робот должен вычислять свое местоположение и одометрические данные и генерировать данные для отправки в навигационный стек. Чтобы контролировать скорость двигателя робота, нам потребуется регулятор пропорционального интегрального дифференциального регулирования (PID). Эти функции помогают выполнять пакет ROS под названием differential_drive, содержащий все необходимые узлы. Мы повторно используем эти узлы в нашем пакете для реализации данных функций. Ниже приведена ссылка для пакета differential_drive в ROS: http://wiki.ros.org/differential_drive.

Читать также:  Абстракция данных в C++

На следующем рисунке показано взаимодействие этих узлов друг с другом. Можно также обсудить использование других узлов.

Структурная схема робота, показывающая узлы ROS
Структурная схема робота, показывающая узлы ROS

Назначение каждого узла в пакете chefbot_bringup выглядит следующим образом.

twist_to_motors.py: этот узел преобразует команду Ros Twist или линейную и угловую скорости к угловой скорости колеса. Конечная скорость публикуется со скоростью ~rate (измеряется в герцах), и скорость публикации timeout_ticks времени после остановки твист-сообщения. Ниже приведены разделы и параметры, которые будут опубликованы и подписаны этим узлом.

Темы публикаций:

  • wheel_target (std_msgs/Float32) – это скорость левого колеса (м/с);
  • wheel_target (std_msgs/Float32) – это скорость правого колеса (м/с).

Темы подписки:

Twist (geometry_msgs/Twist) – это команда для поворота робота. Линейная скорость в направлении x и угловая скорость q использована в сообщении Twist этого робота.

Важные параметры ROS:

  • ~base_width (float, по умолчанию: 0.1): это расстояние между двумя колесами робота в метрах;
  • ~rate (int, по умолчанию: 50): это скорость, с которой опубликована конечная скорость (Гц);
  • ~timeout_ticks (int, по умолчанию: 2): это число сообщений о конечной скорости, опубликованной после сообщения Twist об остановке;
  • pid_velocity.py: это простой регулятор PID, предназначенный для контроля скорости каждого двигателя с помощью обратной связи от шифраторов колеса. В системе дифференциального привода нам нужен один регулятор PID для каждого колеса. Он считывает данные шифратора каждого колеса и контролирует скорость каждого колеса.

Темы публикаций:

  • motor_cmd (Float32) – это окончательный результат PID-регулятора, который направляется к двигателю. Мы можем изменить диапазон выходных данных PID с использованием параметров out_min и out_max ROS;
  • wheel_vel (Float32) – это текущая скорость колеса робота (м/с).

Темы подписки:

  • wheel (Int16) – это тема углового энкодера. Есть отдельные темы для каждого энкодера робота;
  • wheel_target (Float32) – конечная скорость (м/с).

Важные параметры:

  • ~Kp (float, по умолчанию: 10) – этот параметр пропорционален коэффициенту PID-регулятора;
  • ~Ki (float, по умолчанию: 10): этот параметр является интегралом коэффициента усиления PID-регулятора;
  • ~Kd (float, по умолчанию: 0.001): это производная коэффициента PID-регулятора;
  • ~out_min (float, по умолчанию: 255): это минимальный предел значения скорости двигателя. Этот параметр ограничивает значение скорости двигателя и называется темой wheel_vel;
  • ~out_max (float, по умолчанию: 255): это максимальный предел темы wheel_vel (Гц);
  • ~rate (float, по умолчанию: 20): это скорость публикации темы wheel_vel;
  • ticks_meter (float, по умолчанию: 20): это число импульсов энкодера колеса на метр. Это глобальный параметр, который используется и в других узлах;
  • vel_threshold (float, по умолчанию: 0.001): если скорость робота падает ниже этого параметра, мы рассматриваем колесо как неподвижное. Если скорость колеса меньше vel_threshold, то будем считать ее нулевой;
  • encoder_min (int, по умолчанию: 32768): это минимальное значение чтения энкодера;
  • encoder_max (int, по умолчанию: 32768): это максимальное значение чтения энкодера;
  • wheel_low_wrap (int, по умолчанию: 0.3 * (encoder_max – encoder_min) + encoder_min): эти значения определяют, находится ли одометрия в отрицательном или положительном направлении;
  • wheel_high_wrap (int, по умолчанию: 0.7 * (encoder_max – encoder_min) + encoder_min): эти значения решают, находится ли одометрия в отрицательном или положительном направлении;
  • diff_tf.py: этот узел вычисляет преобразование одометрии и передачу между блоком данных одометрии и базовым блоком данных робота.

Темы публикации:

  • odom (nav_msgs/odometry) – публикует одометрию (текущая поза и поворот) робота;
  • Tf – обеспечивает преобразование между блоком данных одометрии и базовой связью робота.

Темы подписки:

  • lwheel (std_msgs/Int16), rwheel (std_msgs/Int16) – значения выхода от левого и правого энкодеров робота;
  • chefbot_keyboard_teleop.py – этот узел передает команду Twist с клавиатуры.

Темы публикации:

  • cmd_vel_mux/input/teleop (geometry_msgs/Twist) – сообщения Twist публикуются с помощью команд клавиатуры.

После обсуждения узлов пакета chefbot_bringup мы рассмотрим функции запуска файлов.

Функции исполняемого файла ChefBot ROS

Теперь мы рассмотрим функции каждого из файлов запуска пакета ChefBot_bringup:

  • robot_standalone.launch. Основная функция этого исполняемого файла – запускать такие узлы, как launchpad_node, pid_velocity, diff_tf и twist_to_motor, чтобы получить значения датчика от робота и послать команду на управление скоростью робота;
  • keyboard_teleop.launch: запуск дистанционного управления с клавиатуры. Запускает узел chefbot_keyboard_teleop.py для дистанционного управления с клавиатуры;
  • 3dsensor.launch: этот файл запускает драйверы Kinect с поддержкой OpenNI и начинает публикацию потока RGB и глубины. Он также запустит узел лазерного сканирования глубины, который преобразует данные облака точек в данные лазерного сканирования;
  • gmapping_demo.launch: данный файл запуска запустит узлы Slam gmapping для составления карты местности, окружающей робота;
  • amcl_demo.launch: используя AMCL, робот может определить свое место на карте. После локализации робота на карте мы можем им управлять для перехода в требуемую позицию на карте. Затем робот может самостоятельно перемещаться из текущего положения в положение цели;
  • view_robot.launch: этот файл запуска отображает модель робота URDF в RViz;
  • view_navigation.launch: этот файл запуска отображает все датчики, необходимые для навигации робота.

Элементы Python ChefBot и запуск файлов

Мы уже установили пакеты CHEFBOT ROS в ПК Nuc Intel и загрузили встроенный код в LaunchPad. Следующим шагом мы установим бортовой ПК NUC на среднюю плиту робота, настроим удаленное подключение ноутбука к бортовому компьютеру робота, протестируем каждый узел и начнем работать с файлами запуска ChefBot, предназначенными для автономной навигации.

Следует заметить, что для работы с ChefBot потребуется беспроводной маршрутизатор. Бортовой компьютер робота и удаленный ноутбук или настольный компьютер необходимо подключить к одной сети. Если бортовой ПК робота и удаленный ноутбук или настольный компьютер находится в одной сети, удаленный ноутбук или настольный компьютер может подключиться к бортовому ПК через SSH, используя свой IP. Перед тем как установить бортовой ПК, необходимо подключить бортовой ПК к беспроводной сети. После первого подключения к сети бортовой ПК запомнит параметры подключения. При включении робота бортовой компьютер автоматически подключится к беспроводной сети. Ниже показана схема подключения робота и удаленного ПК.

Схема беспроводного подключения робота и удаленного ПК
Схема беспроводного подключения робота и удаленного ПК

Предыдущий рисунок предполагает, что IP ChefBot – 192.168.1.106, а IP удаленного ПК — 192.168.1.101.

Мы с помощью SSH можем удаленно открыть терминал ChefBot. Для входа в ChefBot используется следующая команда, где имя робота – ChefBot PC:

$ ssh robot@192.168.1.106

При подключении CHEFBOT PC будет запрашиваться пароль бортового ПК. После ввода пароля появится доступ к терминалу бортового ПК робота. Когда вход был выполнен, можно начать испытание узлов ROS ChefBot и проверить, сможем ли мы получать последовательные данные от платы управления LaunchPad ChefBot. Заметьте, если будет запущен новый терминал, придется снова войти в CHEFBOT PC через SSH.

Если пакет Chefbot_bringup правильно установлен на бортовом ПК и если микроконтроллер LaunchPad подключен, тогда перед запуском узла драйвера ROS мы можем запустить инструмент miniterm.py, чтобы проверить, приходят ли последовательные данные к бортовому ПК через USB. Имя последовательного устройства мы можем найти с помощью команды dmesg.

miniterm.py запускается с помощью следующей команды:

iter miniterm.py / dev / ttyACM0 115200

Если появится сообщение об отказе доступа, установите доступ к USBустройству, напишите правила для папки udev, как мы делали в пятой статье «Проектирование оборудования и схем ChefBot«. Мы предполагаем, что ttyACM0 – это имя запускаемого устройства. Если на вашем компьютере устройство названо по-другому, вместо ttyACM0 используйте фактическое имя устройства:

$ sudo chmod 777 /dev/ttyACM0

Если все работает нормально, мы получим значения, как показано на следующем рисунке.

Выход miniterm.py
Выход miniterm.py

Буква b используется для обозначения аккумулятора робота; в настоящее время эта функция не реализована и значение равно 0. Для измерения напряжения существуют различные методы, реализованные с помощью микроконтроллера. Один из подходов описывается здесь: http://www.instructables.com/id/Arduino-Battery-Voltage-Indicator/. Буква t указывает общее время (в микросекундах) после запуска роботом встроенного кода. Второе значение – это время, затраченное на выполнение одной операции в LaunchPad (измеряется в секундах). Мы можем использовать это значение, если выполняем вычисления параметров робота в реальном времени. На данный момент мы это значение не используем. Но можем использовать его в будущем. Буква e обозначает значения левого и правого энкодеров соответственно. Робот не движется, и эти значения равны нулю. Буква u указывает значения от ультразвукового датчика расстояния. Значение расстояния измеряем в сантиметрах. Буква s указывает текущую скорость вращения колеса робота. Это значение используется для проверки. На самом деле скорость – это контроль от самого PC.

Читать также:  Обработка переменных в языке программирования Паскаль

Чтобы преобразовать эти последовательные данные в темы ROS, необходимо управлять узлом двигателя, который называется launchpad_node.py. В следующем коде показано, как выполнить этот узел.

В первую очередь перед запуском всех узлов нам следует запустить roscore:

$ roscore

Далее выполните launchpad_node.py с помощью следующей команды:

$ rosrun chefbot_bringup launchpad_node.py

Если все работает нормально, мы получим следующий вывод в узле работающего терминала:

Выход launchpad_node.py
Выход launchpad_node.py

После запуска launchpad_node.py мы увидим следующие созданные темы, как показано на рисунке ниже.

Темы, созданные launchpad_node.py
Темы, созданные launchpad_node.py

Мы можем просмотреть последовательные данные, полученные узлом драйвера, подписавшись на /serial, и использовать эти данные для отладки. Если /serial показывает те же данные, что и miniterm.py, значит, узлы работают нормально. Следующий скриншот – это вывод /serial:

Вывод /serial topic, опубликованный узлом LaunchPad
Вывод /serial topic, опубликованный узлом LaunchPad

После установки пакета chefbot_bringup мы можем начать работу с автономной навигацией ChefBot. В настоящее время мы работаем только с терминалом бортового ПК ChefBot. Чтобы отобразить на экране модель робота, данные датчиков, карты и т. д., мы используем RViz, установленный в удаленном ПК (пользовательский компьютер). Следует отметить, что компьютер пользователя должен иметь ту же настройку программного обеспечения, что и компьютер ChefBot.

Первое, что нам нужно сделать, – это установить ПК ChefBot в качестве мастера ROS. Для этого необходимо установить значение ROS_MASTER_URI. ROS_MASTER_URI является обязательным параметром, он информирует узлы о едином идентификаторе ресурса (URI) ROS-мастера. Когда ROS_MASTER_URI будут установлены на бортовом ПК ChefBot и на удаленном компьютере, можно открыть темы ChefBot ПК в удаленном компьютере. Таким образом, если мы запустим локально RViz, то он будет визуализировать темы, создаваемые бортовым ПК CHEFBOT.

Предположим, у бортового ПК ChefBot PC IP-адрес 192.168.1.106, а IР-адрес удаленного компьютера – 192.168.1.101.

Для установки ROS_MASTER_URI в каждой системе следующая команда должна быть включена в файл .bashrc в домашнем каталоге. На следующей схеме показана настройка, необходимая для включения .bashrc в бортовом ПК и удаленном ПК.

Конфигурация сети для ChefBot
Конфигурация сети для ChefBot

Вместо указанных на рисунке IP-адресов внесите в строки ваши реальные IP-адреса и добавьте эти строки внизу .bashrc на каждом ПК.

После выполнения этих настроек запустите roscore в терминале бортового ПК ChefBot ПК и выполните команду rostopic list на удаленном компьютере.

Если появятся какие-то темы, значит, настройки выполнены. Используя дистанционное управление с клавиатуры, сначала запустим робот. Это делается, чтобы убедиться в работоспособности робота и получить значения с датчиков.

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

$ roslaunch chefbot_bringup robot_standalone.launch

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

$ roslaunch chefbot_bringup keyboard_teleop.launch

Для активации Kinect выполните команду, приведенную ниже. Эта команда выполняется в терминале бортового ПК ChefBot:

$ roslaunch chefbot_bringup 3dsensor_kinect.launch

Если вы используете блок датчиков Orbecc Astra, для его запуска используйте следующую команду:

$ roslaunch ChefBot_bringup 3d_sensor_astra.launch

Для просмотра данных, поступающих с Kinect или Astra, выполните следующую команду. После выполнения этой команды на экране удаленного компьютера, в RViz, появится изображение робота. Если мы на удаленном ПК настроим пакет ChefBot_bringup, то сможем получить доступ к следующей команде и визуализировать модель робота и данные датчиков с бортового ПК ChefBot:

$ roslaunch chefbot_bringup view_robot.launch

На расположенном ниже рисунке показана работа робота в RViz. Здесь приведены данные лазерного сканирования и карта облака точек.

Данные лазерного сканирования ChefBot в RViz
Данные лазерного сканирования ChefBot в RViz

На предыдущем рисунке показаны данные лазерного сканирования, отображенные в RViz. Для отображения этих данных установите в левой части окна RViz флажок напротив темы LaserScan. Данные лазерного сканирования показаны на экране. Для просмотра карты облака точек Kinnect в левом нижнем углу окна RViz нажмите кнопку Add. Появится всплывающее окно. Выберите в этом окне строку PointCloud2.

Выберите в списке Тема /camera/depth_registered. В окне RViz появятся данные облака точек, как показано на следующем рисунке.

Данные облака точек ChefBot
Данные облака точек ChefBot

Датчики работают. Теперь можно для отображения карты помещения запустить SLAM. Следующая процедура поможет нам запустить SLAM на этом роботе.

Построение карты комнаты с помощью SLAM в ROS

Чтобы запустить gmapping, мы должны выполнить следующие команды.

Следующая команда запускает драйвер робота в терминале ChefBot:

$ roslaunch chefbot_bringup robot_standalone.launch

Для запуска gmapping выполните нижеприведенную команду. Обратите внимание, команда должна выполняться в терминале бортового ПК ChefBot:

$ roslaunch chefbot_bringup gmapping_demo.launch

Gmapping будет работать только в случае, если данные одометрии будут получены без ошибок. Если значение одометра получено, появится следующее сообщение для предыдущей команды. Если это сообщение поступит, значит, gmapping работает нормально.

Данные облака точек Chefbot 1
Данные облака точек Chefbot

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

$ roslaunch chefbot_bringup keyboard_teleop.launch

С помощью показанной ниже команды запустите на удаленном ПК RViz:

$ roslaunch chefbot_bringup view_navigation.launch

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

$ rosrun map_server map_saver -f ~ / test_map

где test_map – имя карты, хранящейся в домашнем каталоге. На следующем рисунке показана созданная роботом карта комнаты.

Карта помещения
Карта помещения

Итак, карта сохранена. Далее можно с помощью ROS начать работу с автономной навигацией и определением положения робота на карте.

ROS: локализация и навигация

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

$ roslaunch chefbot_bringup robot_standalone.launch

Запустите с помощью следующей команды локализацию и навигацию по сохраненной карте:

$ roslaunch chefbot_bringup amcl_demo.launch map_file: = ~ / test_map.yaml

Начните с помощью команды, показанной ниже, просмотр работы робота на удаленном компьютере:

$ roslaunch chefbot_bringup view_navigation.launch

В RViz нам может потребоваться указать начальное положение робота. Для этого нажмите кнопку 2D Pose Estimate и укажите на карте положение робота на данный момент. Если у робота есть доступ к карте, кнопка 2D Nav Goal позволит переместить робот в нужное положение. В начале локализации, согласно алгоритму AMCL, вы увидите облако частиц вокруг робота.

Локализация робота с помощью AMCL
Локализация робота с помощью AMCL

Ниже приведен снимок экрана робота, когда он самостоятельно переходит из своего текущего положения в целевую позицию. Целевая позиция отмечена черной точкой.

Автономная навигация с помощью карты
Автономная навигация с помощью карты

Цветная линия от робота до черной точки – это планируемый путь робота в целевую позицию. Если карта роботу не доступна, потребуется точная настройка файлов параметров в папке chefbot_bringupparam. Для более точной настройки зайдите в ROS-пакет AMCL по адресу: http://wiki.ros.org/amcl?distro=indigo.

Итоги

Эта статья была посвящена сборке аппаратного обеспечения ChefBot и интеграции встроенного ROS-кода, с помощью которого выполняется автономная навигация. Мы рассмотрели отдельные части робота, которые были изготовлены с использованием конструкций, рассмотренных в шестой статье «Согласование приводов и датчиков с контроллером робота». Был собран отдельный узел робота и подключен разработанный для него прототип PCB. Этот узел состоит из микроконтроллера LaunchPad, драйвера двигателя, левого переключателя, ультразвукового датчика расстояния и IMU (гироскопа-акселерометра). Далее заменили встроенный код микропроцессора LaunchPad, благодаря чему микроконтроллер получил возможность взаимодействовать со всеми датчиками робота и обмениваться данными с бортовым ПК. После обсуждения встроенного кода мы написали узел драйвера Ros Python для сопряжения последовательных данных с LaunchPad. После согласования микроконтроллера LaunchPpad мы рассчитали данные одометрии и управления дифференциальным приводом. Для этого мы использовали узлы из пакета differential_drive, из репозитория ROS. Далее мы подключили робот к навигационному стеку ROS, что позволило выполнить SLAM и AMCL для автономной навигации. Мы также обсудили SLAM, AMCL, создание карты и выполнение автономной навигации робота.

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

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

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

Добавить комментарий