Программирование на Python
Справочник по библиотекам pioneer_sdk2 0.15.1 и pioneer_rknn 1.6.3 для вычислительного модуля Пионер Мини 2. Описаны установленные компоненты, подключение и автомат состояний, управление полётом, телеметрия, события, камеры, сервопривод, RC-каналы, нейросети на NPU и готовые примеры.
1. Установленное ПО
| Компонент | Версия | Путь |
|---|---|---|
| Python | 3.12.3 | /usr/bin/python3 |
pioneer_sdk2 | 0.15.1 | /usr/local/lib/python3.12/dist-packages/pioneer_sdk2/ |
pioneer_rknn (ИИ) | 1.6.3 | /usr/local/lib/python3.12/dist-packages/pioneer_rknn/ |
rknn-toolkit-lite2 | 2.3.0 | /usr/local/lib/python3.12/dist-packages/rknnlite/ |
OpenCV (cv2) | 4.10.0 | /usr/lib/python3.12/dist-packages/cv2/ |
| numpy | 1.26.4 | — |
| pyserial / grpcio | 3.5 / 1.74.0 | — |
Встроенная справка SDK на русском находится в pioneer_sdk2-0.15.1.dist-info/METADATA (966 строк) — это фактически официальная документация.
Зависимости SDK: numpy==1.26.4, opencv-python==4.10.0.84, pyserial==3.5. Поддерживаются Windows 10/11, Linux, macOS (Apple Silicon).
2. Подключение и автомат состояний
from pioneer_sdk2 import Pioneer
drone = Pioneer() # TCP 127.0.0.1:20556 (PlazLink)
# Pioneer(serial="/dev/ttyS3", baudrate=57600) # прямое подключение по UART
# Pioneer(tcp="host:port", wait_callback=True, safety_command=True, logger=True)
drone.close_connection()| Параметр | Описание |
|---|---|
serial | Последовательный порт |
tcp | 127.0.0.1:20556 |
wait_callback | true — ждать события |
safety_command | true — проверять состояние |
При wait_callback=True и safety_command=True работает контроль последовательности ON_LAND → ARMED → IN_SKY → ON_LAND:
- команда не из текущего состояния — игнорируется (возвращает
False); - пропуск обязательного этапа — исключение
RuntimeError; - контроль действует только в рамках одной программы.
3. Управление полётом
Основные команды
| Метод | Назначение |
|---|---|
arm(timeout=5, retries=0) | Запуск моторов (ждёт ENGINES_STARTED) |
disarm() | Отключение моторов |
takeoff() | Взлёт (ждёт TAKEOFF_COMPLETE) |
land() | Посадка (ждёт COPTER_LANDED) |
rtl() | Возврат домой |
reboot_board() | Перезагрузка платы |
point_reached() / point_deceleration() | Достижение/торможение у точки |
Навигация
| Метод | Назначение |
|---|---|
go_to_local_point(x, y, z, yaw, time=0) | Локальная точка (м, °); time=0 — текущая скорость |
go_to_local_point_body_fixed(x, y, z, yaw, time=0) | Смещение относительно текущей позиции |
go_to_global_point(lat, lon, alt, yaw=0) | Глобальная точка по GPS |
go_to_global_point_relative(lat, lon, alt, yaw) | Смещение по GPS |
set_yaw(yaw) | Угол рыскания (°) |
set_manual_speed(vx, vy, vz, yaw_rate, interval=1.0) | Скорость (м/с, рад/с) в глоб. СК |
set_manual_speed_body_fixed(...) | Скорость относительно корпуса |
Состояние и параметры
from pioneer_sdk2 import Pioneer, FlyState, NavSystem
state = drone.get_fly_state() # ON_LAND / ARMED / IN_SKY
nav = drone.get_nav_system() # GPS / LPS / OPT
drone.set_param("Copter_flyWithoutRc", 1.0)
drone.led_control(255, 0, 1, 0) # все LED — зелёный
drone.grab_open(velocity=100)4. Телеметрия и датчики
| Метод | Результат |
|---|---|
get_battery_status() | tuple(напряжение, температура) | None |
get_orientation() | tuple(roll, pitch, yaw) |
get_accel() / get_gyro() / get_mag() | tuple(x, y, z) |
get_altitude() | высота, м |
get_dist_sensor_data() | дальность (ToF), м |
get_motors_rpm() | list[4] оборотов |
get_ranger_data() | (право, лево, вперёд, назад, верх/низ), м |
get_local_position_lps() / get_local_velocity_lps() | tuple(x, y, z) / tuple(vx, vy, vz) |
get_local_yaw_lps() | угол, −180…+180° |
get_nav_status_lps() / get_nav_status_gps() | NO_DATA / CANNOT / LOW / OK |
get_optical_data() | tuple[int, int, float] (оптический поток) |
get_global_position_gps() / get_global_velocity_gps() | координаты / скорости (GPS) |
get_satellites_count() | tuple(GPS, ГЛОНАСС) |
time() / uptime() / flight_time() | секунды |
Классы состояний
FlyState:ON_LAND,ARMED,IN_SKYNavSystem:GPS,LPS,OPTNavStatus:NO_DATA,CANNOT,LOW,OK
5. События и field_watcher
from pioneer_sdk2 import Pioneer, Event
def on_point(ev):
print("Точка достигнута")
drone.subscribe(on_point, Event.POINT_REACHED)
# подписка на изменение произвольного поля телеметрии
watcher = {"comp": "SmartBoard", "field": "rcServo",
"callback": lambda v: print("rcServo =", v),
"last_value": None}
drone.field_watcher.append(watcher)Список событий Event: ALL, COPTER_LANDED, LOW_VOLTAGE1, LOW_VOLTAGE2, LOW_CHARGE, POINT_REACHED, POINT_DECELERATION, TAKEOFF_COMPLETE, ENGINES_STARTED, SHOCK.
6. Камеры и запись
from pioneer_sdk2 import Camera, CameraType, ImageViewer, RecorderControl
cam = Camera(CameraType.MAIN) # MAIN / OPT (из board_config.json)
frame = cam.get_cv_frame(timeout=5.0) # numpy BGR
iv = ImageViewer() # публикация в RTSP mediamtx
iv.imshow("test", frame) # rtsp://localhost:8554/test
rec = RecorderControl()
rec.get_camera_recording_configs(CameraType.MAIN) # [RecordingConfig(w,h,fps)]
rec.start_recording(CameraType.MAIN, output_dir="/mnt/media/videos/")
rec.take_photo("shot.jpg", CameraType.MAIN, output_dir="/mnt/media/photos/")
rec.stop_recording(CameraType.MAIN)
cam.stop(); iv.close()| Драйвер | Особенность |
|---|---|
| gstreamer | захват из shared memory /tmp/{maincamera,optcamera}; поддерживает ImageViewer |
| rtsp | Camera(camera_type, camera_ip="10.42.0.1:8554") |
Режимы записи/фото берутся из board_config.json (поле recordable): MAIN — до 4K/2K/FullHD/720p, OPT — 1280×800. Запись идёт через pm2-jmp-camera-control.
7. Сервопривод камеры
from pioneer_sdk2 import ServoCamera, ServoPriority
servo = ServoCamera()
servo.set_angle(-45, ServoPriority.HIGH) # диапазон -80…+30°, HIGH/MEDIUM/LOWКоманда уходит в Unix-сокет /tmp/servo.sock и исполняется службой pwm-servo (PWM chip0).
8. RC-каналы
Перед использованием требуется выставить параметры автопилота:
Copter_man_rcMode0 = 6.0
Copter_man_rcMode1 = 3.0
Copter_man_rcMode2 = 3.0
Copter_flyWithoutRc = 1.0
SensorMux_rc = 2.0
# непрерывная отправка каналов для поддержания связи
drone.send_rc_channels(channel_1=0, channel_2=0, channel_3=0,
channel_4=0, channel_5=1)
ch5, ch7 = drone.rc_sdk1_to_sdk2(...) # конвертация из SDK1channel_1— правый джойстик: −1 влево, 0, +1 вправоchannel_2— правый джойстик: −1 вперёд, 0, +1 назадchannel_3— левый джойстик: −1 вниз, 0, +1 вверхchannel_4— левый джойстик: +1 влево, 0, −1 вправоchannel_5— режим управления; 6–8 — дополнительные
9. ИИ на NPU (pioneer_rknn)
Модели берутся из локального реестра http://127.0.0.1:7777/model (Flask) либо по пути к .rknn файлу.
from pioneer_rknn import Yolo, YoloPose, PaddleOCR, ModelRegistry
model = Yolo(model_name="yolov8n", object_thresh=0.5) # arch: yolov8, yolov11
boxes, classes, scores = model.run([img]) # img: (1,640,640,3) uint8 BGR
model.release()
pose = YoloPose(model_name="yolov8n-pose") # 17 кейпойнтов COCO
ocr = PaddleOCR(det_model_name="PP-OCRv5_mobile_det",
rec_model_name="eslav_PP-OCRv5_mobile_rec")
boxes, texts = ocr.run(img) # [(текст, уверенность), …]Доступные модели в реестре
| Имя | Архитектура | Версия |
|---|---|---|
yolov8n | yolov8 | 1.0.0 |
yolov8n-pose | yolov8-pose | 1.0.0 |
PP-OCRv5_mobile_det | PP-OCRv5_mobile_det | 0.0.0 |
eslav_PP-OCRv5_mobile_rec | PP-OCRv5_mobile_rec | 0.0.0 |
Управление реестром
reg = ModelRegistry()
reg.list_model()
reg.get_model_info("yolov8n")
reg.upload_model("my_model", "1.0.0", "model.rknn", "yolov8")
reg.delete_model("my_model")ModelContainer сам определяет чип по /proc/device-tree/compatible (RK3576) и запускает инференс на NPU-ядре.
Класс ключевых точек YoloPose: NOSE 0, LEFT/RIGHT_EYE 1/2, LEFT/RIGHT_EAR 3/4, LEFT/RIGHT_SHOULDER 5/6, LEFT/RIGHT_ELBOW 7/8, LEFT/RIGHT_WRIST 9/10, LEFT/RIGHT_HIP 11/12, LEFT/RIGHT_KNEE 13/14, LEFT/RIGHT_ANKLE 15/16.
10. Визуальное программирование (Blockly)
pioneer-bricks (порт 2020) хранит программы как Blockly-XML и генерирует Python. Пример flight_test использует блоки:
start_blockpreflighttake_offgo_local_pointcontrols_whileUntilnot_point_reachedcam_get_cv_frameimshowlanding
Эквивалент на Python:
pioneer.arm()
pioneer.takeoff()
pioneer.go_to_local_point(0, 1, 1, 0, 0)
while not pioneer.point_reached():
img = cam_main.get_cv_frame()
iv.imshow("test", img)
pioneer.land()11. Готовые примеры на борту
| Файл | Что показывает |
|---|---|
/home/pioneermini/workspace/py.py | Маршрут по точкам с подпиской на POINT_REACHED |
/opt/scripts/test_nn.py | YOLO + ArUco + OpenCV, LED-индикация (многопоточно) |
/opt/scripts/servo_rc_trigger.py | Серво по RC-триггеру через field_watcher |
/opt/scripts/servo_example.py | Ручное управление углом серво |
/opt/tests/cam/*.py | Тесты камер, ToF (lasercam.py), EEPROM, серво |
pioneer-bricks/static/save/flight_test/ | Пример блочной программы (XML + Python) |
Запуск: python3 файл.py по SSH либо через code-server на http://10.42.1.1:9999 (рабочая папка /home/pioneermini/workspace).
12. Полные примеры
Маршрут по точкам (py.py)
from pioneer_sdk2 import Pioneer
import pioneer_sdk2, threading, time
drone = Pioneer()
point_event = threading.Event()
def point_reached(event): point_event.set()
drone.subscribe(point_reached, pioneer_sdk2.Event.POINT_REACHED)
try:
drone.arm()
drone.takeoff()
time.sleep(3)
for (x, y) in [(0,0), (1,0), (1,2), (-1,2), (-1,0), (0,0)]:
drone.go_to_local_point(x=x, y=y, z=1, yaw=0, time=3)
point_event.wait(); point_event.clear()
drone.land()
except KeyboardInterrupt:
drone.land()
finally:
drone.close_connection()YOLO + ArUco (фрагмент test_nn.py)
from pioneer_sdk2 import Camera, ImageViewer, Pioneer
from pioneer_rknn import Yolo
import cv2, numpy as np
model = Yolo(model_name="yolov8n", object_thresh=0.5)
cam = Camera()
iv = ImageViewer()
aruco = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_ARUCO_ORIGINAL)
while True:
img = cam.get_cv_frame()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
boxes, classes, scores = model.run([np.expand_dims(cv2.resize(img, [640,640]), 0)])
corners, ids, _ = cv2.aruco.detectMarkers(gray, aruco)
iv.imshow("XYZ", img)13. Нюансы и требования
- SDK требует поднятого
plazlink-core(мост к полётному контроллеру поttyS3). - Камеры требуют
media-server(mediamtx) и shared memory/tmp/maincamera,/tmp/optcamera. - Запись/фото — только при установленном
pm2-jmp-camera-control. - GPS-методы — при наличии модуля GNSS;
ranger/grab— при установленной нагрузке (вboard_config.json:ranger=true, grab=true, cargo=false). CameraTypeгенерируется динамически из секцииcamerasфайлаboard_config.json.- Событийное управление позволяет реализовать неблокирующую логику.