# Клиент clever-show

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

* `client.py` - основной модуль связи и управления дроном
* `failsafe.py` - модуль защиты дронов, который создает сервис `/emergency_land` и контролирует состояние дрона в соответствии с логикой, указанной в пунктах `[FAILSAFE]` и `[EMERGENCY LAND]` файла настроек `client.ini`

## Инструкции

* [Установка и запуск](start-tutorial.md#установка-и-запуск-клиента)
* [Настройка клиента](#настройка-клиента)

## Схема работы клиента в образе для Raspberry Pi

Клиент является сервисом `clever-show` в операционной системе коптера. Сервис запускает скрипт [client.py](../../drone/client.py) и автоматически запускается при загрузке операционной системы. В случае необходимости применения параметров обновлённой конфигурации клиента сервис может быть перезапущен. Сервис `clever-show` предназначен для управления и настройки коптера для группового полёта с помощью приложения сервера.

Вместе с клиентом в операционной системе зарегистрирован сервис экстренной защиты дрона `failsafe`. Данный сервис запускает скрипт [failsafe.py](../../drone/failsafe.py) и автоматически запускается при загрузке операционной системы. В случае необходимости применения параметров обновлённой конфигурации клиента сервис может быть перезапущен.

Сервис `failsafe` предназначен для автоматической посадки коптера в экстренных ситуациях:

* при отсутствии сообщений о позиции дрона из топика `/mavros/vision_pose/pose`
* при столкновении с объектами в полёте, когда расстояние между текущей точкой, где находится коптер, и точкой, где ему следует находиться по полётному заданию, превышает пороговое значение.

Также `failsafe` предоставляет ROS сервис `/emergency_land`, к которому может обратиться клиент по команде с сервера для экстренной посадки дрона.

Логи обоих сервисов записываются в файл `/var/log/syslog` операционной системы бортового компьютера Raspberry Pi на дроне. Логи текущего сеанса доступны для просмотра при выполнении команд `journalctl -u clever-show` для клиента и `journalctl -u failsafe` для сервиса экстренной защиты дрона в терминале, подключенном к Raspberry Pi. Логи могут быть полезны при анализе возникших нештатных или аварийных ситуаций при полёте коптера под управлением приложения клиента.

## Настройка клиента

### Файл конфигурации

Конфигурация клиента создаётся согласно [спецификации](../../drone/config/spec/configspec_client.ini), в ней можно посмотреть значения по умолчанию для любого параметра после ключевого слова `default`. Все изменения сохраняются в файл конфигурации `client.ini` в папке `clever-show/drone/config`. Доступно редактирование конфигурации клиента через GUI модуль `Config editor` в приложении сервера. Для редактирования конфигурации с сервера нужно выбрать строку с клиентом, для которого требуется изменение конфигурации, кликнуть левой кнопкой мыши по любой ячейке из строки и выбрать `Edit config` из контекстного меню.

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

Для централизованной загрузки конфигурации на все коптеры нужно использовать пункт меню `Send configurations` на [сервере](server.md#раздел-server). Допускается загрузка неполного файла параметров конфигурации, с отсутствующими разделами или параметрами относительно конфигурации по умолчанию. Также доступна опция загрузки конфигурации конкретного клиента на выделенные коптеры: для этого нужно в приложении сервера выбрать строку с клиентом, с которого требуется скопировать конфигурацию на выделенные клиенты, кликнуть левой кнопкой мыши по любой ячейке из строки и выбрать `Copy config to selected` из контекстного меню.

### Описание параметров

#### Основной раздел

* `config_name` - название конфигурации
* `config_version` - версия конфигурации
* `id` - имя коптера, отображаемое в таблице. Если значение `/hostname` - имя определяется из файла `/etc/hostname`.
* `clover_dir` - путь к директории с ROS пакетом [сlover](https://github.com/CopterExpress/clover). Необходим для загрузки файлов с картами aruco меток и launch файлов настройки запуска сервиса `clover`. Если значение `auto` - клиент пытается сам определить нужную директорию пакета `clover` (или `clever`) через `rospkg` при первом запуске. Если директорию с пакетом не удаётся определить, значение устанавливается в `error`, а файлы, специфичные для настройки ROS пакета `сlover` не передаются с сервера на клиент.

#### Раздел SERVER

В этом разделе задаются параметры сетевого взаимодействия клиента с сервером. Доступны следующие параметры:

* `port` - TCP порт, на который будут приниматься входящие соединения от сервера. При использовании настройки [use_broadcast](server.md#раздел-broadcast) на сервере, данный порт будет сконфигурирован у клиента автоматически. *Рекомендуется изменить значение по умолчанию в целях безопасности* (любое пятизначное и более число, если другое ПО не использует выбранный порт).
* `host` - IP адрес сервера.
* `buffer_size` - размер буфера при приёме и передаче данных. *Не рекомендуется изменять. Рекомендуется использовать единое значение у сервера и клиентов.*

#### Раздел BROADCAST

В этом разделе включается/выключается механизм получения broadcast пакетов по UDP с сервера.

* `use` - логическое значение, определяет, использовать или не использовать механизм получения broadcast пакетов по UDP с сервера.
* `port` - порт UDP для приёма broadcast сообщений.

#### Раздел TELEMETRY

В данном разделе настраивается поток передачи телеметрии на сервер.

* `transmit` - логическое значение, определяет, нужно ли передавать данные на сервер.
* `frequency` - частота передачи данных на сервер, целочисленное значение, количество раз в секунду.
* `log_resources` - логическое значение, определяет, будет ли записываться в лог сервиса клиента clever-show состояние бортового компьютера: загрузка процессора и оперативной памяти, температура процессора, состояние температуры, состояние системы питания (только для Raspberry Pi).

#### Раздел FLIGHT

В данном разделе находятся настройки, влияющие на процесс полёта коптера.

* `frame_id` - название системы координат, относительно которой будут публиковаться координаты точек для воспроизведения анимации. Если значение `floor` - клиент публикует статическую систему координат с названием `floor` и настройками из раздела [FLOOR_FRAME](#раздел-floor_frame). **Внимание!** Убедитесь, что коптер удерживает позицию в данной системе координат. Для этого вы можете воспользоваться командой [Takeoff](server.md#тестовые-команды) из серверного приложения. Коптер взлетит на высоту `takeoff_height` относительно текущей.
* `takeoff_height` - высота взлёта коптера, в метрах. Используется в начале воспроизведения анимации или при тестировании коптера с сервера.
* `takeoff_time` - максимальное время взлёта коптера, в секундах.
* `reach_first_point_time` - максимальное время полёта к первой точке анимации, в секундах.
* `land_time` - время зависания в конечной точке анимации перед посадкой, в секундах.
* `land_timeout` - время таймаута посадки, после которого происходит выключение моторов коптера, в секундах.

#### Раздел FLOOR FRAME

Данный раздел описывает смещение системы координат с названием `floor` и используется только при указании параметра `frame_id` как `floor` в разделе [COPTERS](#раздел-copters).

* `enabled` - логическое значение, определяет, нужно ли публиковать фрейм `floor`
* `parent` - название опорной системы координат, относительно которой будет располагаться система координат `floor`.
* `translation` - смещение системы координат `floor` по осям (x, y, z) относительно системы координат `parent`, в метрах.
* `rotation` - поворот системы координат `floor` на углы (roll, pitch, yaw) вокруг осей (x, y, z) относительно системы координат `parent`, в градусах.

**Внимание!** Повороты `roll`, `pitch`, `yaw` производятся последовательно в указанном порядке.

#### Раздел GPS FRAME

Данный раздел описывает создание системы координат с названием `gps`. Начальное положение этой системы координат лежит в точке с координатами `lat` (latitude, широта), `lon` (longitude, долгота). Угол поворота системы координат относительно севера задаётся значением `yaw` (в градусах, по часовой стрелке). Начальная высота системы координат настраивается параметром `amsl`: её можно оставить равной начальной высоте коптера (`current`), либо обозначить значением высоты над уровнем моря в формате [AMSL](https://ru.wikipedia.org/wiki/Высота_над_уровнем_моря).

* `lat` - широта в градусах в системе WGS 84
* `lon` - долгота в градусах в системе WGS 84
* `yaw` - угол поворота системы координат в градусах
* `amsl` - высота в метрах

#### Раздел ANIMATION

В данном разделе настраивается обработка анимации. За обработку анимации отвечает отдельный модуль [animation](../../drone/modules/animation.py). При загрузке анимации на коптер модуль производит разделение последовательности кадров анимации на 5 ключевых этапов:

1. Коптер неподвижен в начале анимации - `static_begin`
2. Коптер взлетает - `takeoff`
3. Коптер следует по маршруту анимации - `route`
4. Коптер выполняет посадку - `land`
5. Коптер неподвижен до завершения файла анимации - `static_end`

Кадр анимации - это набор данных, необходимых для позиционирования коптера и определения цвета его подсветки. В текущей версии ПО кадр анимации представлен последовательностью чисел `x y z yaw r g b` в строке `.csv` файла с анимацией, где:

* `x`, `y`, `z` - координаты коптера в текущем кадре в метрах
* `yaw` - рыскание коптера в радианах
* `r`, `g`, `b` - компоненты цвета подсветки коптера, целые числа от 0 до 255

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

* `start_action` - первое действие при запуске воспроизведения анимации. Доступные варианты:
  * `auto` - автоматический выбор действия между `takeoff` (взлёт) или `fly` (мгновенный полёт по точкам) на основе текущего уровня высоты коптера. Если (`z` в начальной точке анимации) > (уровень взлета `takeoff_level`), то значение устанавливается в `takeoff`, иначе значение устанавливается в `fly`.
  * `fly` - выполнение *логики немедленного полёта*
  * `takeoff` - выполнение *логики полёта к первой точке*.

  Если в файле анимации коптер взлетает с земли, при старте анимации будет применена **логика немедленного воспроизведения (fly)**: коптер с выключенными моторами воспроизводит цвет из анимации, пока неподвижен, включает двигатели перед моментом взлёта, затем через время `arming_time` начинает следовать точкам, указанным в анимации.

  Если в файле анимации коптер начинает полёт в воздухе, при старте анимации будет применена **логика полёта к первой точке (takeoff)**: коптер с выключенными моторами воспроизводит цвет из анимации, пока неподвижен, включает двигатели перед моментом взлёта, затем взлетает на высоту `takeoff_height` за время `takeoff_time`, затем перемещается к первой точке за время `reach_first_point_time`, и затем начинает следовать точкам, указанным в анимации.

* `takeoff_level` - уровень взлёта для автоматического определения первого действия коптера при старте анимации
* `ground_level` - уровень земли, используется для проверки, не попытается ли коптер улететь под землю при воспроизведении анимации. Доступные варианты настройки:
  * `current` - за уровень земли принимается текущий уровень высоты коптера перед стартом.
  * координата z в метрах
* `check_ground` - логическое значение, определяет, нужно ли производить проверку уровня земли в анимации.
* `frame_delay` - время воспроизведения одного кадра в секундах.
* `yaw` - поворот коптера при полёте по точкам, в градусах. Если значение `nan` - коптер сохраняет изначальную ориентацию в полёте. Если значение `animation` - коптер берёт поворот по yaw из файла с анимацией.
* `ratio` - масштаб анимации (ratio_x, ratio_y, ratio_z) по осям (x, y, z)
* `common_offset` - смещение анимации относительно текущей системы, общее для всех коптеров, в метрах. Список из 3 величин (x, y, z): каждая величина задаёт смещение по соответствующей оси.
* `private_offset` - смещение анимации относительно текущей системы, только для данного коптера, в метрах. Список из 3 величин (x, y, z): каждая величина задаёт смещение по соответствующей оси.
* `[[OUTPUT]]` - флаги, определяющие, какие этапы будут включены в выходную последовательность кадров.

#### Раздел LED

Настройки использования светодиодной ленты на коптере. Для настройки самой ленты необходимо настроить файл `led.launch`, подробная информация в [статье по работе с лентой в Клевере](https://clover.coex.tech/ru/leds.html).

* `use` - логическое значение, определяет, используется или нет светодиодная лента.
* `takeoff_indication` - логическое значение, определяет, использовать ли подсветку для обозначения взлёта
* `land_indication` - логическое значение, определяет, использовать ли подсветку для обозначения посадки

#### Раздел FAILSAFE

В данном разделе настраивается программа экстренной защиты коптера от потери позиции или столкновения с объектом. Модуль `failsafe` при запуске предоставляет сервис `/emergency_land`, его настройки находятся в следующем разделе [EMERGENCY LAND](#раздел-emergency-land).

* `enabled` - логическое значение, определяет, использовать или нет экстренную защиту при потере визуальной позиции или столкновении с объектом.
* `log_state` - логическое значение, определяет, будет ли записываться в лог сервиса состояние коптера: `armed: {} | mode: {} | vis_dt: {:.2f} | pos_delta: {:.2f} | pos_dt: {:.2f} | range: {:.2f} | watchdog_action: {}`.
* `action` - действие при срабатывании экстренной защиты. Доступные варианты: `land` - посадка коптера в режиме полётного контроллера AUTO.LAND, `emergency_land` - посадка коптера с постепенным уменьшением мощности моторов, `disarm`- выключение моторов. **Внимание!** Не рекомендуется использовать режим AUTO.LAND с выключенным барометром - при потере источника высоты в полёте, например показаний лазера или визуальной позиции, режим AUTO.LAND не гарантирует посадку коптера, так как ориентируется на показания высоты. Для посадки коптера при его позиционировании с использованием визуальной позиции или лазера и возможности потери данных с этих систем рекомендуется использовать режим `emergency_land`.
* `vision_pose_delay_after_arm` - время после взлёта коптера в секундах, которое требуется для получения визуальной позиции. В течение этого времени после взлёта защита по потере визуальной позиции не будет срабатывать. Этот параметр полезен при использовании модуля экстренной защиты совместно с системой позиционирования по aruco маркерам, расположенным на полу: при взлёте коптер какое-то время не имеет визуальной позиции.
* `vision_pose_timeout` - время в секундах после потери визуальной позиции, через которое срабатывает экстренная защита.
* `position_delta_max` - максимальная разница между текущим положением и точкой, в которой сейчас должен находиться коптер, в метрах. Требуется для проверки на столкновение коптера с объектом. Если расстояние между текущим положением коптера и положением, в котором он должен сейчас находиться, больше этого числа (в метрах), срабатывает экстренная защита.
* `disarm_timeout` - время, через которое коптер безусловно выключает моторы после срабатывания экстренной защиты, в секундах.

#### Раздел EMERGENCY LAND

Настройки параметров экстренной посадки при действии `emergency_land` экстренной защиты или при вызове ROS сервиса `/emergency_land`.

* `thrust` - начальная мощность, подаваемая на моторы в случае выбора действия `emergency_land` при срабатывании экстренной защиты. Безразмерная величина, от 0 (отсутствие мошности) до 1 (полная мощность). Для гарантированной посадки рекомендуется устанавливать в значение, меньшее по величине на 5-10 процентов, чем газ висения (параметр `MPC_THR_HOVER` в px4). **Внимание!** Неправильная настройка этого параметра может привести к взлёту коптера вверх вместо посадки!
* `decrease_thrust_after` - время, через которое мощность на моторах плавно начинает уменьшаться в случае выбора действия `emergency_land` при срабатывании экстренной защиты, в секундах.

#### Раздел SYSTEM

Системные настройки служебных команд клиента

* `change_hostname` - логический параметр, определяет, требуется ли смена hostname при переименовании `id` коптера.
* `restart_after_rename` - логический параметр, определяет, требуется ли перезагрузка коптера при переименовании его `id` удалённо с сервера.

#### Раздел NTP

Помимо синхронизации времени (с миллисекундной точностью) с помощью пакета chrony, предоставляется альтернатива - возможность использования внешних (при наличии соединения локальной сети с интернетом) или внутрисетевых NTP-серверов. **Внимание!** Для корректной работы системы, **и сервер, и клиенты** должны использовать единый способ синхронизации времени (набор параметров в этом разделе). Данный раздел полностью унифицирован и для сервера, и для клиентов.

* `use_ntp` - определяет, будет ли использоваться синхронизация времени с помощью NTP. (при значении `False` будет использовано локальное время ОС (синхронизируется автоматически при использовании chrony). *Рекомендуется использование chrony, а не NTP*
* `host` - имя хоста или IP адрес NTP сервера (локального или удаленного)
* `port` - порт, используемый NTP сервером
