Автономные миссии
Автономные миссии и MAVLink
Цель занятия: обучающиеся собирают автономную миссию с условиями прерывания и проверяют её в SITL, включая сценарии отказа.
Автономная миссия — это описанный заранее маршрут плюс условия, при которых он прерывается. Вторая часть важнее первой: маршрут без условий прерывания — это аппарат, который продолжит выполнять план, что бы ни случилось.
MAVLink: язык общения с аппаратом
MAVLink — протокол, на котором наземная станция, бортовой компьютер и автопилот разговаривают друг с другом. В отличие от CRSF, который передаёт только положения стиков, MAVLink передаёт сообщения со смыслом: «лети в точку», «сообщи заряд», «переключись в режим возврата».
| Свойство | CRSF | MAVLink |
|---|---|---|
| Что передаёт | 16 чисел — положения органов управления | Именованные сообщения с параметрами |
| Направление | В основном от пульта к аппарату | Двусторонний обмен |
| Кто отправляет | Пульт | Наземная станция, бортовой компьютер, скрипт |
| Уровень команд | «Стик на 60 %» | «Лети в точку 55.7558, 37.6173 на высоте 50 м» |
Типовые сообщения:
| Сообщение | Смысл |
|---|---|
HEARTBEAT | «Я жив», раз в секунду. Пропал — связь потеряна |
GLOBAL_POSITION_INT | Текущие координаты и высота |
SYS_STATUS | Заряд, напряжение, состояние систем |
MISSION_ITEM | Одна точка маршрута |
COMMAND_LONG | Команда: взлёт, посадка, смена режима |
Из чего состоит миссия
flowchart TD
T["🛫 Взлёт<br/>до заданной высоты"] --> W1["📍 Точка 1"]
W1 --> W2["📍 Точка 2"]
W2 --> W3["📍 Точка 3"]
W3 --> L["🛬 Посадка / возврат домой"]
W1 -.->|мало заряда| RTL["🏠 Возврат домой"]
W2 -.->|потеря связи| RTL
W3 -.->|выход за геозону| RTL
Сплошные стрелки — план. Пунктирные — условия прерывания, и именно они отличают учебную миссию от безопасной.
Обязательные условия прерывания
| Условие | Типичная реакция | Почему |
|---|---|---|
| Заряд ниже порога | Возврат домой | Аппарат должен долететь обратно, а не упасть по пути |
| Потеря связи дольше N секунд | Возврат домой | Оператор потерял контроль |
| Выход за геозону | Остановка и возврат | Защита людей и имущества за границей зоны |
| Потеря GPS | Зависание или снижение | Без координат маршрут не имеет смысла |
| Превышение высоты | Принудительное снижение | Нарушение правил использования воздушного пространства |
SITL: полёт без аппарата
SITL (Software In The Loop) — запуск настоящей прошивки автопилота на компьютере, с моделируемыми датчиками и физикой. Наземная станция подключается к ней так же, как к реальному аппарату, и не видит разницы.
Что это даёт:
- миссию можно прогнать целиком до того, как аппарат вообще собран;
- отказы проверяются безопасно: потерю GPS или разряд можно вызвать намеренно;
- ошибка в скрипте не стоит аппарата;
- каждый обучающийся работает со своим «аппаратом», даже если в кабинете их два.
Запустить SITL и подключить станцию
Поднимаем симулятор автопилота, подключаем к нему QGroundControl. Проверяем, что видны телеметрия и положение.
Составить миссию
Ставим точки маршрута, задаём высоты, добавляем геозону и условия возврата.
Прогнать штатный сценарий
Запускаем миссию и смотрим, что аппарат проходит маршрут как задумано.
Сломать намеренно
Вызываем отказ: обрываем связь, «разряжаем» батарею, выводим за геозону. Проверяем, что срабатывает именно то поведение, которое задумано.
Разобрать лог
Открываем запись и находим момент срабатывания защиты. Тот же навык, что в разборе логов.
Управление из Python
Миссии можно не только рисовать в станции, но и собирать программно — через
pymavlink. Здесь программирование смыкается с полётом.
from pymavlink import mavutil
# Подключение к SITL (или к реальному аппарату — меняется только строка)
master = mavutil.mavlink_connection('udp:127.0.0.1:14550')
master.wait_heartbeat()
print(f"Связь есть: система {master.target_system}")
# Читаем телеметрию
while True:
msg = master.recv_match(type='GLOBAL_POSITION_INT', blocking=True)
lat = msg.lat / 1e7 # координаты приходят в виде целых чисел
lon = msg.lon / 1e7 # градусы × 10^7 — так точнее и компактнее
alt = msg.relative_alt / 1000.0
print(f"Координаты: {lat:.6f}, {lon:.6f} высота {alt:.1f} м")lat = 557558000 вместо 55.7558.
Дробные числа в протоколах избегают: они занимают больше места и по-разному
округляются на разных платформах. Умножение на даёт точность около
сантиметра при целочисленной арифметике. Тот же приём, что при работе с
деньгами в копейках, — и хороший повод обсудить, почему float не всегда друг.Первый безопасный скрипт
Начинать всегда с чтения, а не с команд:
# Уровень 1: только слушаем — ничего не может сломаться
msg = master.recv_match(type='SYS_STATUS', blocking=True)
print(f"Напряжение: {msg.voltage_battery / 1000.0:.2f} В")
# Уровень 2: команды — только в SITL, и только после того,
# как чтение телеметрии уверенно работаетДиагностика
| Симптом | Причина | Проверка |
|---|---|---|
wait_heartbeat() висит вечно | Неверный адрес/порт, SITL не запущен | Проверить строку подключения |
| Миссия не загружается | Точка вне геозоны или недостижимая высота | Проверить границы |
| Аппарат сразу возвращается | Условие прерывания срабатывает на старте | Проверить пороги заряда и GPS |
| Летит не туда | Перепутаны широта и долгота | Проверить порядок и деление на |
| Команды игнорируются | Аппарат не в нужном режиме или не armed | Проверить режим и ARM |
Приёмка занятия
- Миссия собрана, прогнана в SITL, маршрут пройден.
- Заданы и проверены срабатыванием минимум три условия прерывания.
- Скрипт на Python читает телеметрию и печатает координаты и заряд.
- Объясняет, почему порог возврата по заряду считается от расстояния, а не берётся круглым числом.