Skip to main content

Async PX4 drone controller — sequential autonomous flight via MAVLink

Project description

mavpilot

🇬🇧 English version

Асинхронный контроллер PX4-дрона на Python — последовательное автономное управление через MAVLink, встроенная 3D-визуализация в браузере и режим без железа.

CI PyPI Python License: MIT


Возможности

Чистый asyncio API Пишите последовательную логику миссии через await — без колбэков и машин состояний
PX4 OFFBOARD режим Стримит SET_POSITION_TARGET_LOCAL_NED на частоте 50 Гц
Точная посадка Визуально-направляемый спуск через простой callback API
Движение в теле дрона goto_body_relative() без ручного пересчёта NED/курс
Ограничение скорости рыскания Плавные переходы курса (по умолчанию 15 °/с, настраивается)
Визуализация в браузере Живая 3D-траектория + телеметрия через HTTP+SSE — без npm, без CDN
Mock-режим Встроенный физический симулятор — тестируйте миссию без SITL и железа
Потокобезопасность Heartbeat, receiver и streamer крутятся в фоновых потоках

Установка

pip install mavpilot

Или из исходников:

git clone https://github.com/Onikore/mavpilot
cd mavpilot
pip install -e ".[dev]"

Зависимость времени выполнения: pymavlink (устанавливается автоматически).


Быстрый старт — mock-режим

Дрон и SITL не нужны:

# Квадратная траектория
python -m mavpilot --mock

# Траектория в виде звезды
python -m mavpilot --mock --pattern star

# Демо точной посадки
python -m mavpilot --mock --precision-land

Откройте http://localhost:8765 в браузере — увидите живую 3D-визуализацию.


Использование как библиотека

import asyncio
from mavpilot import DroneController

async def mission():
    drone = DroneController(
        connection_string="udp:127.0.0.1:14540",  # SITL по умолчанию
        enable_viz=True,   # визуализация в браузере на :8765
    )

    await drone.connect()
    await drone.apply_safe_params()  # рекомендуемые параметры безопасности PX4
    await drone.wait_until_ready()   # ждём EKF / LOCAL_POSITION_NED

    await drone.takeoff(altitude_m=5.0)

    # Координаты NED (x=Север, y=Восток, z=Вниз)
    await drone.goto(x=10, y=0, z=-5)
    await drone.goto(x=10, y=10, z=-5, yaw_deg=90)
    await drone.goto_body_relative(forward_m=5, right_m=0, down_m=0)
    await drone.hover(duration_s=3.0)

    await drone.land()
    drone.close()

asyncio.run(mission())

Точная посадка

Передайте callback, возвращающий смещение маркера в системе координат тела дрона (FRD):

from mavpilot import DroneController, MarkerObservation

def get_marker() -> MarkerObservation | None:
    # подключите свой визуальный пайплайн
    # dx = смещение вперёд (м), dy = смещение вправо (м)
    return MarkerObservation(dx=0.3, dy=-0.1)

async def mission():
    drone = DroneController(mock=True, enable_viz=False)
    await drone.connect()
    await drone.takeoff(altitude_m=10.0)
    result = await drone.precision_land(
        get_marker_offset=get_marker,
        descent_rate_mps=0.3,
        final_altitude_m=0.5,
        horizontal_tolerance_m=0.15,
        min_altitude_floor_m=0.3,   # новый параметр в v0.2.0
    )
    if not result:
        # status ∈ {ABORTED_AT_FLOOR, MARKER_LOST, TIMEOUT}
        print(f"precision_land не приземлился: {result.status.value}")
        print(f"финальная позиция: {result.final_position}")
    drone.close()

Перевод пикселей камеры в смещение в теле дрона

from mavpilot.utils import pixel_to_body_offset

dx, dy = pixel_to_body_offset(
    px_norm_x=0.1,            # нормализованные координаты [-1, 1]
    px_norm_y=-0.05,
    camera_hfov_deg=90.0,
    camera_vfov_deg=60.0,
    altitude_above_ground_m=drone.get_local_position().altitude,
    camera_mount_yaw_deg=0.0,
)

CLI

python -m mavpilot [ОПЦИИ]

Опции:
  --connection STR      MAVLink endpoint  [по умолчанию: udp:127.0.0.1:14540]
  --mock                Симуляторный режим без железа
  --viz-port INT        Порт браузерной визуализации  [по умолчанию: 8765]
  --viz-host STR        Интерфейс визуализатора [по умолчанию: 127.0.0.1]
                        Используйте 0.0.0.0 для доступа из локальной сети
  --no-viz              Отключить браузерную визуализацию
  --precision-land      Точная посадка с симулированным маркером
  --pattern {square,star}  Паттерн полёта в демо  [по умолчанию: square]

Поведение при ошибках и Ctrl-C

  • Ctrl-C в любой момент миссии вызывает emergency_land(). Это включает: смену режима на AUTO_LAND, ожидание касания земли (до 10 с), отправку команды MAV_CMD_NAV_LAND если режим завис, и в крайнем случае DO_FLIGHTTERMINATION (мгновенное обесточивание моторов — дрон падает).
  • RTL не входит в emergency_land(). Возврат на точку старта — это отдельная штатная операция (drone.return_to_launch()), не аварийная.
  • Любое необработанное исключение в миссии (включая KeyboardInterrupt) также вызывает emergency_land().

Справочник API

DroneController(…)

DroneController(
    connection_string = "udp:127.0.0.1:14540",
    source_system     = 255,
    source_component  = MAV_COMP_ID_MISSIONPLANNER,
    loop_hz           = 50.0,       # частота стриминга сетпоинтов
    enable_viz        = True,       # запустить браузерную визуализацию
    viz_port          = 8765,
    mock              = False,      # симулятор без железа
    yaw_slew_rate_deg = 15.0,       # макс. скорость рыскания (°/с)
)

Методы управления полётом

Метод Описание
await connect(timeout_s) Открыть MAVLink и запустить фоновые потоки
await apply_safe_params() Записать рекомендуемые параметры безопасности PX4
await wait_until_ready(timeout_s) Ждать пока EKF не выдаст LOCAL_POSITION_NED
await takeoff(altitude_m, timeout_s) Арм, OFFBOARD режим, набор высоты
await goto(x, y, z, yaw_deg, …) Лететь в точку NED
await goto_relative(dx, dy, dz, …) Смещение от текущей позиции NED
await goto_body_relative(fwd, right, down, …) Смещение в системе тела дрона
await set_yaw(yaw_deg, timeout_s) Разворот на месте
await hover(duration_s) Удерживать позицию
await land(timeout_s) AUTO_LAND, ждать приземления
await precision_land(callback, …) Визуально-направляемый спуск; возвращает PrecisionLandResult
await return_to_launch(timeout_s) AUTO_RTL, ждать приземления
await emergency_land() Цепочка: AUTO_LAND → NAV_LAND → DO_FLIGHTTERMINATION
close() Остановить все потоки, закрыть соединение

Телеметрия

Метод Возвращает
get_local_position() Position(x, y, z) в метрах NED
get_yaw_rad() / get_yaw_deg() Текущий курс
is_armed() bool
is_offboard() bool
landed_state() int (1 = на земле, 2 = в воздухе)

Датаклассы

from mavpilot import Position, MarkerObservation

# Позиция в NED (x=Север, y=Восток, z=Вниз)
pos: Position       # pos.altitude == -pos.z

# Смещение маркера в системе тела дрона FRD
obs: MarkerObservation  # dx=вперёд, dy=вправо, dz=вниз (опционально)

Система координат

mavpilot использует NED-конвенцию PX4 из LOCAL_POSITION_NED:

Ось Направление Примечание
x Север (+)
y Восток (+)
z Вниз (+) высота = -z

Утилиты для преобразования координат:

from mavpilot.utils import body_to_ned, ned_to_body, pixel_to_body_offset

Визуализация

Лёгкий встроенный HTTP+SSE сервер раздаёт 3D-вид на Three.js без сборки и пакетного менеджера. Откройте http://localhost:8765 пока дрон работает.

Правая панель отображает:

  • Статус арма и режим полёта
  • Позицию, скорость, курс, заряд батареи в реальном времени
  • Активный сетпоинт
  • Лог команд (взлёт, goto, посадка, …)
  • Сообщения PX4 STATUSTEXT

Архитектура

asyncio event loop  <-- ваш код миссии
        |
        v
 DroneController
        |
        +-- heartbeat_thread   (1 Гц MAVLink heartbeat)
        +-- receiver_thread    (разбор входящих MAVLink → self._tel)
        +-- streamer_thread    (публикация SET_POSITION_TARGET_LOCAL_NED @ 50 Гц)
        +-- viz_server         (опциональный HTTP+SSE → браузер)

Всё общее состояние защищено _tel_lock и _setpoint_lock. В коде миссии asyncio-примитивы не нужны.


Подключение к реальному железу

# UART (Raspberry Pi <-> Pixhawk)
drone = DroneController(connection_string="/dev/ttyAMA0")

# UDP (SITL или мост компаньон-компьютер → GCS)
drone = DroneController(connection_string="udp:192.168.1.10:14540")

# TCP
drone = DroneController(connection_string="tcp:127.0.0.1:5760")

Рекомендуемые параметры безопасности (устанавливаются через apply_safe_params()):

Параметр Значение Назначение
COM_RCL_EXCEPT 7 Нет failsafe в offboard / mission / hold
COM_OBL_RC_ACT 4 Потеря RC → hold, не RTL
COM_OF_LOSS_T 2.0 с Таймаут потери offboard
COM_RC_IN_MODE 1 RC не требуется

Разработка

# Установка в editable-режиме с dev-зависимостями
pip install -e ".[dev]"

# Тесты
pytest -q

# Линтер
ruff check mavpilot/

# Проверка типов
mypy mavpilot/

Лицензия

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mavpilot-0.1.0.tar.gz (38.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mavpilot-0.1.0-py3-none-any.whl (35.7 kB view details)

Uploaded Python 3

File details

Details for the file mavpilot-0.1.0.tar.gz.

File metadata

  • Download URL: mavpilot-0.1.0.tar.gz
  • Upload date:
  • Size: 38.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mavpilot-0.1.0.tar.gz
Algorithm Hash digest
SHA256 30cb7bfd243c352d8e90ede7f667bd90382a03dba49120ae06cbdc93ffd415b4
MD5 ce46c34721326c8dde05dfa17b8eb671
BLAKE2b-256 9b10a77b997b3a16adff7495ace00b1dbd19eba45b5bc2bf2eb33a84e7ea0544

See more details on using hashes here.

File details

Details for the file mavpilot-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: mavpilot-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 35.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mavpilot-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 41c399b396694c1d54a22521d5216ddfc2817d94595f6b7e48fe8c657ee00813
MD5 ac3333dd72d700a36154ec2cfcfb3989
BLAKE2b-256 be88e1de14fd50749925ffa506282d71b1946e0923d8a2665b382a20f7686947

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page