Rosserial — связь двух Arduino через ROS


Начал изучать ROS по этим материалам >> (спасибо за перевод — по английским мануалам точно бы не смог )

Есть задумка с платформой iRobot, пока iRobot в пути поупражняюсь в простеньком.
Решил наладить передачу между двумя платами Arduino через ROS.
Библиотека rosserial (см. топик) устанавливает соединение точка-точка (point-to-point connection) через последовательный порт с недорогими контроллерами (типа Arduino) так, что вы можете посылать сообщения ROS туда и обратно.

ROS установлена на нетбуке ASUS (простенький, слабенький), Ubuntu 11.10, дистрибутив Electric
Для начала устанавливаем библиотеку rosserial.
Пробовал как рекомендовано на сайте ros.org —

hg clone https://kforge.ros.org/rosserial/hg rosserial
rosdep install rosserial_arduino
rosmake rosserial_arduino

Сразу возникли проблемы — ошибки — проблема общая как показал поиск по google
Решил так

sudo apt-get install ros-electric-rosserial
rosdep install rosserial_arduino
rosmake rosserial_arduino

Все получилось

Rosserial состоит из общего p2p-протокола, библиотеки для работы с Arduino и узлов для ПК.
Библиотека для работы с Arduino находится в папке проекта serial, в каталоге serial_arduino/libraries. Копируем папку ros_lib в библиотечную директорию (libraries) Arduino IDE.

Две платы Arduino подключены по двум последовательным портам к нетбуку с ROS.

К одной плате Arduino (один узел ROS ) подключен датчик температуры DS18B20. Показания температуры будем отправлять будем публиковать в ROS (в тему temperature), другая плата Arduino (еще один узел ROS) будет получать показания температуры из темы temperature и отображать на дисплее WH0802.
В ROS создаем два узла serial_node.py пакета rosserial_python, который соединяет наши Arduino платы с остальной частью ROS (необходимо выставить используемый последовательный порт):
Создается узел так:

rosrun rosserial_python serial_node.py /dev/порт

Запустить два узла serial_node с одним именем не получится. Одна из особенностей ROS состоит в том, что вы можете переназначить имена (Names) узлов из командной строки:

$ rosrun rosserial_python serial_node.py /dev/ttyUSB0 __name:=serial1
$ rosrun rosserial_python serial_node.py /dev/ttyACM0 __name:=serial2

Теперь необходимо написать скетчи на Arduino для узла publisher (отправляющего показания температуры в тему temperature) и узла subscriber (получающего показания из темы отображающего их на дисплее WH0802)
Используем библиотеку ros_lib

Скетч для publisher
В рамках каждой программы ROS Arduino необходимо включить заголовочный файл ros.h и файлы заголовков для всех типов сообщений, которые мы будем использовать, в нашем случае std_msgs/Float32.h:
#include <ros.h>
#include <std_msgs/Float32.h>
Далее, нам необходимо создать экземпляр объекта узла serial_node, что позволяет нашей программе выступать в качестве подписчика(subscriber), либо публиковать сообщения (publisher):
ros::NodeHandle nh;
Создаем экземпляр publisher для нашего узла serial_node, публикующий сообщения типа std_msgs::Float32 в тему temperature:
std_msgs::Float32 float32_msg;
ros::Publisher chatter(«temperature», &float32_msg);

В подпрограмме setup() необходимо инициализировать узел и объявить о роли узла chatter в качестве publisher:
nh.initNode();
nh.advertise(chatter);
В цикле loop() после считывания данных с датчика температуры публикуем сообщение в тему и вызываем ros::spinOnce(), где обрабатываются все функции обратного вызова соединения.
chatter.publish( &float32_msg );
nh.spinOnce();

Добавляем код для считывания данных с датчика температуры, и получается так:

#include <OneWire.h>
OneWire  ds(10);  // линия 1-Wire будет на pin 10

#include <ros.h>
#include <std_msgs/Float32.h>

ros::NodeHandle  nh;
std_msgs::Float32 float32_msg;
ros::Publisher chatter("temperature", &float32_msg);

void setup(void)
{
  nh.initNode();
  nh.advertise(chatter);
}
void loop(void)
{
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];

  if ( !ds.search(addr)) {
      ds.reset_search();
      return;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // запускаем конвертацию
  delay(1000);     // скорее всего достаточно 750ms
  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // считываем ОЗУ датчика

  for ( i = 0; i < 9; i++) {           // обрабатываем 9 байт
    data[i] = ds.read();
  }
  Serial.print(" CRC=");
  Serial.print( OneWire::crc8( data, 8), HEX);
  Serial.println();
  // высчитываем температуру
  int HighByte, LowByte, Temp;
  float Tempf1,Tempf2;
  LowByte = data[0];
  HighByte = data[1];
  Temp = (HighByte << 8) + LowByte;
  Tempf1=Temp/16;
  Tempf2=(Temp%16)*100/16;
  float32_msg.data=Tempf1+Tempf2/100;
  // публикуем сообщение
  chatter.publish( &float32_msg );
  nh.spinOnce();
}

Скетч для subscriber

Включаем заголовочный файл ros.h и файлы заголовков для всех типа сообщений, которые мы будем использовать, в нашем случае std_msgs/Float32.h
#include <ros.h>
#include <std_msgs/Float32.h>
Далее, нам необходимо создать экземпляр объекта узла serial_node, что позволяет нашей программе выступать в качестве подписчика(subscriber), либо публиковать сообщения (publisher):
ros::NodeHandle nh;
Создаем экземпляр subscriber для нашего узла, получающийй сообщения типа std_msgs::Float32.h из темы temperature:
ros::Subscriber sub("temperature", &messageCb );

Создаем функцию обратного вызова messageCb для нашего узла. Функция обратного вызова должна постоянно получать сообщение в качестве аргумента. В нашем messageCb обратного вызова, тип сообщения std_msgs::Float32.
void messageCb( const std_msgs::Float32& toggle_msg){
digitalWrite(13, HIGH-digitalRead(13)); // blink the led
lcd.setCursor(0, 0);
lcd.print("Temp=");
lcd.setCursor(0, 1);
lcd.print(toggle_msg.data);}

В подпрограмме setup() необходимо инициализировать узел и объявить о роли узла в качестве подписчика на сообщения:
nh.initNode();
nh.subscribe(sub);
И наконец, в цикле loop() и вызываем ros::spinOnce(), где обрабатываются все функции обратного вызова соединения.

nh.spinOnce();
Добавляем код вывода сообщений на дисплей и получаем:

// подключить библиотеку LiquidCrystal
#include <LiquidCrystal.h>
// создание экземпляра объекта LiquidCrystal
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// rosserial
#include <ros.h>
#include <std_msgs/Float32.h>

ros::NodeHandle  nh;
void messageCb( const std_msgs::Float32& toggle_msg){
  digitalWrite(13, HIGH-digitalRead(13));   // blink the led
  lcd.setCursor(0, 0);
  lcd.print("Temp=");
  lcd.setCursor(0, 1);
  lcd.print(toggle_msg.data);}

ros::Subscriber sub("temperature", &messageCb );

void setup() {
  lcd.begin(8, 2);
  pinMode(13, OUTPUT);
  nh.initNode();
  nh.subscribe(sub);
}

void loop() {
  nh.spinOnce();
  delay(1000);
}

Теперь проверяем как все работает:

$ roscore
$ rosrun rosserial_python serial_node.py /dev/ttyUSB0 __name:=serial1
$ rosrun rosserial_python serial_node.py /dev/ttyACM0 __name:=serial2

Проверяем список активных узлов

$ rosnode list

Ответ должен быть

/rosout
/serial1
/serial2

Зупускаем утилиту rxgraph

$ rxgraph

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

Можно посмотреть публикацию сообщений узлом serial1

rostopic echo temperature

И видим


0 комментариев на «“Rosserial — связь двух Arduino через ROS”»

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

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна конкурс манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение