Files
clover/docs/arduino.md
2018-03-19 14:15:49 +03:00

231 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Управление коптером с Arduino
===
Для взаимодействия с ROS-топиками и сервисами на Raspberry Pi можно использовать библиотеку [rosserial_arduino](http://wiki.ros.org/rosserial_arduino).
Основной туториал по rosserial: http://wiki.ros.org/rosserial_arduino/Tutorials
Arudino необходимо установить на Клевер и подключить по USB-порту.
Настройка Arduino IDE
---
Необходимо скачать и скопировать [библиотеку ROS-сообщений Клевера](https://github.com/CopterExpress/clever_bundle/blob/master/deploy/clever_arudino.tar.gz?raw=true) (`ros_lib`) в `<папку скетчей>/libraries`.
Настройка Raspberry Pi
---
Чтобы единоразово запустить программу на Arduino, можно воспользоваться командой:
```
roslaunch clever arduino.launch
```
Чтобы запускать связку с Arduino при старте системы автоматически, необходимо установить аргумент `arudino` в launch-файле Клевера (`~/catkin_ws/src/clever/clever/launch/clever.launch`):
```xml
<arg name="arduino" default="true"/>
```
При изменении launch-файла необходимо перезапустить пакет `clever`:
```bash
sudo systemctl restart clever
```
Задержки
---
При использовании `rosserial_arduino` микроконтроллер Arduino не должен быть заблокирован больше чем на несколько секунд (например, с использованием функции `delay`); иначе связь между Raspberry Pi и Arduino будет разорвана.
При реализации долгих циклов `while` обеспечьте периодический вызов функции `hn.spinOnce`:
```cpp
while(/* условие */) {
// ... Произвести необходимые действия
nh.spinOnce();
}
```
Для огранизации долгих задержек используйте задержки в цикле с периодическим вызовом функции `hn.spinOnce()`:
```cpp
// Задержка на 8 секунд
for(int i=0; i<8; i++) {
delay(1000);
nh.spinOnce();
}
```
Работа с Клевером
---
Набор сервисов и топиков аналогичен обычному набору в [simple_offboard](simple_offboard.md) и [mavros](mavros.md).
Пример программы, контролирующей коптер по позиции, с использованием сервисов `navigate` и `set_mode`:
```cpp
// Подключение библиотек для работы с rosseral
#include <ros.h>
// Подключение заголовочных файлов сообщений пакета Clever и MAVROS
#include <clever/Navigate.h>
#include <mavros_msgs/SetMode.h>
using namespace clever;
using namespace mavros_msgs;
ros::NodeHandle nh;
// Объявление сервисов
ros::ServiceClient<Navigate::Request, Navigate::Response> navigate("/navigate");
ros::ServiceClient<SetMode::Request, SetMode::Response> setMode("/mavros/set_mode");
void setup()
{
// Инициализация rosserial
nh.initNode();
// Инициализация сервисов
nh.serviceClient(navigate);
nh.serviceClient(setMode);
// Ожидание подключение к Raspberry Pi
while(!nh.connected()) nh.spinOnce();
nh.loginfo("Startup complete");
// Пользовательская настройка
// <...>
// Тестовая программа
Navigate::Request nav_req;
Navigate::Response nav_res;
SetMode::Request sm_req;
SetMode::Response sm_res;
// Взлет на 2 метра:
nh.loginfo("Take off");
nav_req.auto_arm = false;
nav_req.x = 0;
nav_req.y = 0;
nav_req.z = 2;
nav_req.frame_id = "fcu_horiz";
nav_req.speed = 0.5;
navigate.call(nav_req, nav_res);
// Ждем 5 секунд
for(int i=0; i<5; i++) {
delay(1000);
nh.spinOnce();
}
nav_req.auto_arm = false;
// Пролет вперед на 3 метра:
nh.loginfo("Fly forward");
nav_req.auto_arm = true;
nav_req.x = 3;
nav_req.y = 0;
nav_req.z = 0;
nav_req.frame_id = "fcu_horiz";
nav_req.speed = 0.8;
navigate.call(nav_req, nav_res);
// Ждем 5 секунд
for(int i=0; i<5; i++) {
delay(1000);
nh.spinOnce();
}
// Полет в точку 1:0:2 по маркерному полю
nh.loginfo("Fly on point");
nav_req.auto_arm = false;
nav_req.x = 1;
nav_req.y = 0;
nav_req.z = 2;
nav_req.frame_id = "aruco_map";
nav_req.update_frame = true;
nav_req.speed = 0.8;
navigate.call(nav_req, nav_res);
// Ждем 5 секунд
for(int i=0; i<5; i++) {
delay(1000);
nh.spinOnce();
}
// Посадка
nh.loginfo("Land");
sm_req.custom_mode = "AUTO.LAND";
setMode.call(sm_req, sm_res);
}
void loop()
{
}
```
Получение телеметрии
---
С Arduino можно использовать [сервис](simple_offboard.md) `get_telemetry`. Для этого надо объявить его по аналогии с сервисами `navigate` и `set_mode`:
```cpp
#include <ros.h>
// ...
#include <clever/GetTelemetry.h>
// ...
ros::ServiceClient<GetTelemetry::Request, GetTelemetry::Response> getTelemetry("/get_telemetry");
// ...
nh.serviceClient(getTelemetry);
// ...
GetTelemetry::Request gt_req;
GetTelemetry::Response gt_res;
// ...
gt_req.frame_id = "aruco_map"; // фрейм для значений x, y, z
getTelemetry.call(gt_req, gt_res);
// gt_res.x - положение коптера по x
// gt_res.y - положение коптера по y
// gt_res.z - положение коптера по z
```
Проблемы
---
При использовании Arudino Nano может не хватать оперативной памяти (RAM). В таком случае в Aruino IDE будут появляться сообщения, типа:
```
Глобальные переменные используют 1837 байт (89%) динамической памяти, оставляя 211 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
```
Можно сократить использование оперативной памяти уменьшив размер выделяемых буферов для передачи и приема сообщений. Для этого **в самое начало** программы следует поместить строку:
```cpp
#define __AVR_ATmega168__ 1
```
Можно уменьшить количество занятой памяти еще сильнее, если вручную настроить количество publisher'ов и subscriber'ов, а также размеры буферов памяти, выделяемой для сообщений, например:
```cpp
#include <ros.h>
// ...
typedef ros::NodeHandle_<ArduinoHardware, 3, 3, 100, 100> NodeHandle;
// ...
NodeHandle nh;
```