Files
clover/docs/ru/simple_offboard.md
2025-01-20 09:45:35 +03:00

369 lines
18 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
# Автономный полет
> **Note** Документация для версий [образа](image.md), начиная с версии **0.24**. Для более ранних версий см. [документацию для версии **0.23**](https://github.com/CopterExpress/clover/blob/v0.23/docs/ru/simple_offboard.md).
Модуль `simple_offboard` пакета `clover` предназначен для упрощенного программирования автономного полета дрона ([режим](modes.md) `OFFBOARD`). Он позволяет устанавливать желаемые полетные задачи и автоматически трансформирует [систему координат](frames.md).
`simple_offboard` является высокоуровневым способом взаимодействия с полетным контроллером. Для более низкоуровневой работы см. [mavros](mavros.md).
Основные сервисы [`get_telemetry`](#gettelemetry) (получение телеметрии), [`navigate`](#navigate) (полет в заданную точку по прямой), [`navigate_global`](#navigateglobal) (полет в глобальную точку по прямой), [`land`](#land) (переход в режим посадки).
## Использование из языка Python
Для использования сервисов, необходимо создать объекты-прокси к ним. Используйте этот шаблон для вашей программы:
```python
import rospy
from clover import srv
from std_srvs.srv import Trigger
rospy.init_node('flight')
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
navigate = rospy.ServiceProxy('navigate', srv.Navigate)
navigate_global = rospy.ServiceProxy('navigate_global', srv.NavigateGlobal)
set_altitude = rospy.ServiceProxy('set_altitude', srv.SetAltitude)
set_yaw = rospy.ServiceProxy('set_yaw', srv.SetYaw)
set_yaw_rate = rospy.ServiceProxy('set_yaw_rate', srv.SetYawRate)
set_position = rospy.ServiceProxy('set_position', srv.SetPosition)
set_velocity = rospy.ServiceProxy('set_velocity', srv.SetVelocity)
set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude)
set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)
land = rospy.ServiceProxy('land', Trigger)
```
Неиспользуемые функции-прокси можно удалить из кода.
## Описание API
> **Note** Незаполненные числовые параметры устанавливаются в значение 0.
### get_telemetry
Получить полную телеметрию коптера.
Параметры:
* `frame_id`  [система координат](frames.md) для значений `x`, `y`, `z`, `vx`, `vy`, `vz`. Пример: `map`, `body`, `aruco_map`. Значение по умолчанию: `map`.
Формат ответа:
* `frame_id` – система координат;
* `connected` есть ли подключение к <abbr title="Flight Control Unit, полетный контроллер">FCU</abbr>;
* `armed` состояние `armed` винтов (винты включены, если true);
* `mode` текущий [полетный режим](modes.md);
* `x, y, z` – локальная позиция коптера *(м)*;
* `lat, lon` широта, долгота *(градусы)*, необходимо наличие [GPS](gps.md);
* `alt` высота в глобальной системе координат (стандарт [WGS-84](https://ru.wikipedia.org/wiki/WGS_84), не <abbr title="Above Mean Sea Level, выше среднего уровня моря">AMSL</abbr>!), необходимо наличие [GPS](gps.md);
* `vx, vy, vz` скорость коптера *(м/с)*;
* `roll` угол по крену *(радианы)*;
* `pitch`  угол по тангажу *(радианы)*;
* `yaw` – угол по рысканью *(радианы)*;
* `roll_rate` – угловая скорость по крену *(рад/с)*;
* `pitch_rate` – угловая скорость по тангажу *(рад/с)*;
* `yaw_rate` – угловая скорость по рысканью *(рад/с)*;
* `voltage` общее напряжение аккумулятора *(В)*;
* `cell_voltage` напряжение аккумулятора на ячейку *(В)*.
> **Note** Недоступные по каким-то причинам поля будут содержать в себе значения `NaN`.
Вывод координат `x`, `y` и `z` коптера в локальной системе координат:
```python
telemetry = get_telemetry()
print(telemetry.x, telemetry.y, telemetry.z)
```
Вывод высоты коптера относительно [карты ArUco-меток](aruco.md):
```python
telemetry = get_telemetry(frame_id='aruco_map')
print(telemetry.z)
```
Проверка доступности глобальной позиции:
```python
import math
if not math.isnan(get_telemetry().lat):
print('Global position is available')
else:
print('No global position')
```
Вывод текущей телеметрии (командная строка):
```bash
rosservice call /get_telemetry "{frame_id: ''}"
```
### navigate
Прилететь в обозначенную точку по прямой.
Параметры:
* `x`, `y`, `z` координаты *(м)*;
* `yaw` угол по рысканью *(радианы)*;
* `speed` скорость полета (скорость движения setpoint) *(м/с)*;
* `auto_arm` перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
* `frame_id`  [система координат](frames.md), в которой заданы `x`, `y`, `z` и `yaw` (по умолчанию: `map`).
> **Note** Для полета без изменения угла по рысканью достаточно установить `yaw` в `NaN` (значение угловой скорости по умолчанию 0).
Взлет на высоту 1.5 м со скоростью взлета 0.5 м/с:
```python
navigate(x=0, y=0, z=1.5, speed=0.5, frame_id='body', auto_arm=True)
```
Полет по прямой в точку 5:0 (высота 2) в локальной системе координат со скоростью 0.8 м/с (рысканье установится в 0):
```python
navigate(x=5, y=0, z=3, speed=0.8)
```
Полет в точку 5:0 без изменения угла по рысканью:
```python
navigate(x=5, y=0, z=3, speed=0.8, yaw=float('nan'))
```
Полет вправо относительно коптера на 3 м:
```python
navigate(x=0, y=-3, z=0, speed=1, frame_id='body')
```
Полет влево на 2 м относительно последней целевой точки полета дрона:
```python
navigate(x=0, y=2, z=0, speed=1, frame_id='navigate_target')
```
Повернуться на 90 градусов по часовой:
```python
navigate(yaw=math.radians(-90), frame_id='body')
```
Полет в точку 3:2 (высота 2) в системе координат [маркерного поля](aruco.md) со скоростью 1 м/с:
```python
navigate(x=3, y=2, z=2, speed=1, frame_id='aruco_map')
```
Взлет на высоту 2 м (командная строка):
```bash
rosservice call /navigate "{x: 0.0, y: 0.0, z: 2, yaw: 0.0, speed: 0.5, frame_id: 'body', auto_arm: true}"
```
> **Note** При программировании миссии дрона в терминах "вперед-назад-влево-вправо" рекомендуется использовать систему координат `navigate_target` вместо `body`, чтобы не учитывать неточность прилета дрона в предыдущую целевую точку при вычислении следующей.
### navigate_global
Полет по прямой в точку в глобальной системе координат (широта/долгота).
Параметры:
* `lat`, `lon` широта и долгота *(градусы)*;
* `z` высота *(м)*;
* `yaw` угол по рысканью *(радианы)*;
* `speed` скорость полета (скорость движения setpoint) *(м/с)*;
* `auto_arm` перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
* `frame_id`  [система координат](frames.md), в которой заданы `z` и `yaw` (по умолчанию: `map`).
> **Note** Для полета без изменения угла по рысканью достаточно установить `yaw` в `NaN`.
Полет в глобальную точку со скоростью 5 м/с, оставаясь на текущей высоте (`yaw` установится в 0, коптер сориентируется передом на восток):
```python
navigate_global(lat=55.707033, lon=37.725010, z=0, speed=5, frame_id='body')
```
Полет в глобальную точку без изменения угла по рысканью:
```python
navigate_global(lat=55.707033, lon=37.725010, z=0, speed=5, yaw=float('nan'), frame_id='body')
```
Полет в глобальную точку (командная строка):
```bash
rosservice call /navigate_global "{lat: 55.707033, lon: 37.725010, z: 0.0, yaw: 0.0, speed: 5.0, frame_id: 'body', auto_arm: false}"
```
### set_altitude
Изменить целевую высоту полета. Сервис используется для независимой установки высоты (и системы координат для расчета высота) в режимах полета [`navigate`](#navigate) и [`set_position`](#setposition).
Параметры:
* `z` высота полета *(м)*;
* `frame_id` [система координат](frames.md) для расчета высоты полета.
Установить высоту полета в 2 м относительно пола:
```python
set_altitude(z=2, frame_id='terrain')
```
Установить высоту полета в 1 м относительно [маркерного поля](aruco.md):
```python
set_altitude(z=1, frame_id='aruco_map')
```
### set_yaw
Изменить целевой угол по рысканью (и систему координат для его расчета), оставив предыдущую команду в силе.
Параметры:
* yaw угол по рысканью *(радианы)*;
* frame_id  [система координат](frames.md) для расчета угла по рысканью.
Повернуться на 90 градусов по часовой (продолжая выполнять предыдущую команду):
```python
set_yaw(yaw=math.radians(-90), frame_id='body')
```
Установить угол по рысканью в ноль в системе координат [маркерного поля](aruco.md):
```python
set_yaw(yaw=0, frame_id='aruco_map')
```
Остановить вращение по рысканью (при использовании [`set_yaw_rate`](#setyawrate)):
```python
set_yaw(yaw=float('nan'))
```
### set_yaw_rate
Изменить целевую угловую скорость по рысканью, оставив предыдущую команду в силе.
Параметры:
* yaw_rate угловая скорость по рысканью *(рад/с)*.
Положительное направление вращения (при виде сверху) против часовой.
Начать вращение на месте со скоростью 0.5 рад/c против часовой (продолжая выполнять предыдущую команду):
```python
set_yaw_rate(yaw_rate=0.5)
```
### set_position
Установить цель по позиции и рысканью. Данный сервис следует использовать при необходимости задания продолжающегося потока целевых точек, например, для полета по сложным траекториям (круговой, дугообразной и т. д.).
> **Hint** Для полета на точку по прямой или взлета используйте более высокоуровневый сервис [`navigate`](#navigate).
Параметры:
* `x`, `y`, `z` координаты точки *(м)*;
* `yaw` угол по рысканью *(радианы)*;
* `auto_arm` перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
* `frame_id`  [система координат](frames.md), в которой заданы `x`, `y`, `z` и `yaw` (по умолчанию: `map`).
Зависнуть на месте:
```python
set_position(frame_id='body')
```
Назначить целевую точку на 3 м выше текущей позиции:
```python
set_position(x=0, y=0, z=3, frame_id='body')
```
Назначить целевую точку на 1 м впереди текущей позиции:
```python
set_position(x=1, y=0, z=0, frame_id='body')
```
### set_velocity
Установить скорости и рысканье.
* `vx`, `vy`, `vz` требуемая скорость полета *(м/с)*;
* `yaw` угол по рысканью *(радианы)*;
* `auto_arm` перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
* `frame_id`  [система координат](frames.md), в которой заданы `vx`, `vy`, `vz` и `yaw` (по умолчанию: `map`).
> **Note** Параметр `frame_id` определяет только ориентацию результирующего вектора скорости, но не его длину.
Полет вперед (относительно коптера) со скоростью 1 м/с:
```python
set_velocity(vx=1, vy=0.0, vz=0, frame_id='body')
```
### set_attitude
Установить тангаж, крен, рысканье и уровень газа (примерный аналог управления в [режиме `STABILIZED`](modes.md)). Данный сервис может быть использован для более низкоуровневого контроля поведения коптера либо для управления коптером при отсутствии источника достоверных данных о его позиции.
Параметры:
* `roll`, `pitch`, `yaw` – необходимый угол по тангажу, крену и рысканью *(радианы)*;
* `thrust` – уровень газа от 0 (нет газа, пропеллеры остановлены) до 1 (полный газ);
* `auto_arm` перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
* `frame_id`  [система координат](frames.md), в которой задан `yaw` (по умолчанию: `map`).
### set_rates
Установить угловые скорости по тангажу, крену и рысканью и уровень газа (примерный аналог управления в [режиме `ACRO`](modes.md)). Это самый низкий уровень управления коптером (исключая непосредственный контроль оборотов моторов). Данный сервис может быть использован для автоматического выполнения акробатических трюков (например, флипа).
Параметры:
* `roll_rate`, `pitch_rate`, `yaw_rate` – угловая скорость по тангажу, крену и рыканью *(рад/с)*;
* `thrust` уровень газа от 0 (нет газа, пропеллеры остановлены) до 1 (полный газ).
* `auto_arm` перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
Положительное направление вращения `yaw_rate` (при виде сверху) против часовой, `pitch_rate` вперед, `roll_rate` влево.
### land
Перевести коптер в [режим](modes.md) посадки (`AUTO.LAND` или аналогичный).
> **Note** Для автоматического отключения винтов после посадки [параметр PX4](parameters.md) `COM_DISARM_LAND` должен быть установлен в значение > 0.
Посадка коптера:
```python
res = land()
if res.success:
print('Copter is landing')
```
Посадка коптера (командная строка):
```bash
rosservice call /land "{}"
```
> **Caution** В более новых версиях PX4 коптер выйдет из режима LAND в ручной режим, если сильно перемещать стики.
### release
В случае необходимости приостановки отправки setpoint-сообщений, используйте сервис `simple_offboard/release`:
```python
release = rospy.ServiceProxy('simple_offboard/release', Trigger)
release()
```
## Дополнительные материалы
* [Полеты в поле ArUco-маркеров](aruco.md).
* [Примеры программ и сниппеты](snippets.md).