Голосовое управление освещением X10. Часть 3

Продолжение. Начало — Часть1 и Часть 2

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

Для начала устанавливаем библиотеку rosserial.

 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.

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

 $ rosrun rosserial_python serial_node.py /dev/ttyUSB0

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

Скетч для subscriber

В рамках каждой программы ROS Arduino необходимо включить заголовочный файл ros.h и файлы заголовков для всех типов сообщений, которые мы будем использовать, в нашем случае std_msgs/X10.h:
 

 #include "ros.h" #include "std_msgs/X10.h"

Здесь возникает небольшая проблема. Для каждого типа сообщений ROS библиотека ros_lib содержит заголовочные файлы (находятся в папке ros_lib/std_msgs). Для сообщений в теме data_to_x10 мы создали пользовательский тип сообщений X10.

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

 rosrun rosserial_client make_library.py path_to_libraries your_message_package

В нашем случае:

 rosrun rosserial_client make_library.py ~/sketchbook vp_x10_voice

В папке ~/sketchbook/ros_lib созданы заголовочные файлы для отправки сообщений типа X10 в ROS. Переносим эти папки в папку /libraries IDE Arduino. Проблема решена — заголовочный файл создан. Далее, нам необходимо создать экземпляр объекта узла serial_node, что позволяет нашей программе выступать в качестве подписчика(subscriber), либо публиковать сообщения (publisher):

 ros::NodeHandle nh;

Создаем экземпляр subscriber для нашего узла serial_node, получающий сообщения типа vp_x10_voice::X10 в тему data_to_x10:

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

Создаем функцию обратного вызова messageCb для нашего узла. Функция обратного вызова должна постоянно получать сообщение в качестве аргумента. В нашем messageCb обратного вызова, тип сообщения std_msgs::X10.

 void messageCb( const vp_x10_voice::X10& toggle_msg){   int command1=toggle_msg.command1;   int command2=toggle_msg.command2;   int repeatTime=toggle_msg.repeatTime;   myHouse.write(command1, command2,repeatTime);                 }

В подпрограмме setup() необходимо инициализировать узел и объявить о роли узла в качестве подписчика на сообщения:

 nh.initNode(); nh.subscribe(sub); 

И наконец, в цикле loop() и вызываем ros::spinOnce(), где обрабатываются все функции обратного вызова соединения.

 nh.spinOnce();

Вот полный код скетча

 // include the X10 library files: #include "x10.h" #include "x10constants.h" #define zcPin 2 // the zero crossing detect pin #define dataPin 4 // the X10 data out pin #define repeatTimes 1 // how many times each X10 message should repeat // in an electrically noisy environment, you // can set this higher.  // set up a new x10 library instance: x10 myHouse = x10(zcPin, dataPin); // ros_lib libraries #include "ros.h" #include "vp_x10_voice/X10.h"   ros::NodeHandle  nh;   void messageCb( const vp_x10_voice::X10& toggle_msg){   digitalWrite(13, HIGH-digitalRead(13));   int command1=toggle_msg.command1;   int command2=toggle_msg.command2;   int repeatTime=toggle_msg.repeatTime;   myHouse.write(command1, command2,repeatTime);                 } ros::Subscriber sub_x10("data_to_x10", &messageCb );   void setup() {   Serial.begin(9600);   nh.initNode();   nh.subscribe(sub_x10);   nh.advertise(pub_x10); }  void loop() {   nh.spinOnce();   delay(1000); }

Архив — скетч Arduino + библиотеки ROS и X10 — x10_voice_arduino.zip

Архив — проект ROS — vp_x10_voice_ros.zip или скачать из репозитория

И далее — Часть 4 — запуск всей системы — пошаговое руководство и видео работы системы