System of automatic unloading and loading of the drone (Part 2 – autopilot) / Habr

System of automatic unloading and loading of the drone (Part 2 – autopilot) / Habr

This article includes:

  1. Video demonstration

  2. The algorithm we used

  3. Geoscan Pioneer max programming (a short tutorial will not be interesting to everyone)

Video demonstration

Design from Automatic drone unloading and loading system (Part 1 — design) / Habr (

To test the performance in near-real conditions, we attached our seats to a simulated window to determine the necessary distance from the surface to which the seat is attached, when using the autopilot (the wind was not canceled by anyone, the drone should be able to make an emergency maneuver). Below is a video after multiple test flights that helped us fine-tune the system and finalize the landing design (16 second delays before each command (to control the entire flight, so we sped up the video):

The result of test flights:

  1. It is difficult to control the autopilot when landing on a horizontal platform (the solution is to reduce the surface area)

  2. Move the platform another 15 centimeters from the wall (when leveling, it flies very close to a vertical surface, and the slightest breeze will press it against the wall/window)

The algorithm we used

Since we need to finalize the design in the conditions of the future, we decided to develop an algorithm for automatic flight and conduct testing of our design for a “dumb machine”. Fortunately, we did not need to write an autopilot from scratch, since our Geoscan Pioneer max drone has it built-in, but despite this, we still needed to develop an algorithm for building a trajectory of movement, based on two input landing points (the third is the starting point ).

Algorithm (simplified):

Geoscan Pioneer max programming, servo connection

To begin with, we connected the servo drive, for this we need a Raspberry (since the built-in system does not know how to communicate with the servo drive), we connect the Raspberry according to the instructions on the Internet and now the question arises where to connect the servo and what to do. Some pins are used by default (but you can’t find information about this on the geoscan website) using such pins can damage the servo, so we recommend using GPIO25 for example. And of course Ground and Power.

Below are the programs for the operation of the servo drive, since it is unlikely that you will use only the servo drive in one-way order, the proposed programs already implement two-way communication, but the transfer limit is 31 characters, everything was based on the documentation (Programming in Lua – Pioneer Documentation December update 2022 (, BUT the information has application features.

-----------------Lua код, загружается на дрон через Pioneer station-----------
local uart =, 57600) -- объявляем uart для общения с pyhon кодом
local servo_stat="o"    -- статус сервопривода(например 'o'(открыто),'c'(закрыто))
local rc = Sensors.rc     -- подключаем пульт
local inp = ''            -- переменная для хранения информации для отправки на Python
local rec=""            -- переменная для хранения ответа(для будущего применения)

local function rotate_servo_open() -- функция открытия сервопривода

local function rotate_servo_close() -- функция закрытия сервопривода

local function main()               -- цикл
  rc_chans = table.pack(rc())     -- получаем иинформацию с пульта
  if rc_chans[8] < -0.8 then      --открытие (канал посмотри на пульте)
  elseif rc_chans[8] > 0.8 then   --закрытие (канал посмотри на пульте)
  inp = servo_stat..'\n' -- пусть разделитель '\n'
  uart:write(inp, #inp)  -- отправляем на Python
  rec = uart:read(uart:bytesToRead())    -- принимаем данные с Python

t =, main) --устанавливаем частоту цикла
t:start() -- начинаем цикл
##########################Python код, загружается на Raspberry########################
import serial             # библиотека для общения
from time import sleep    # библиотека для синхронизации
import RPi.GPIO as GPIO   # библиотека для общения
ser = serial.Serial("/dev/ttyS0", 57600, timeout=5) # открываем порт, бездумно не меняй
GPIO.setmode(GPIO.BCM)    # объявляем для общения с сервоприводом
GPIO.setup(25, GPIO.OUT)  # объявляем для общения с сервоприводом
sg = GPIO.PWM(25, 50)     # объявляем сервопривод
sg.start(8.06)            # объявляем задаём начальный угол
servo_opened = True       # по умолчанию замок открыт

def uart_read():          # функция чтения с Lua
  data = ser.readline().decode().replace('\n', "") # читаем, разделяем, убираем мусор
  if ser.in_waiting &gt; 20:      # чтобы не зависало, бездумно не меняй
      ser.reset_input_buffer() # чтобы не зависало, бездумно не меняй

  print('Read data: ')

  return data

def uart_write(answer): # функция ответа для Lua
  ser.write(answer.encode()) # кодируем, пишем
  print('UART writed')

def servo_control(event): # функция управления сервоприводом
  global servo_opened   # подключаем глобальные переменные
  global sg             # подключаем глобальные переменные
  if event == "c" and servo_opened: # закрываем серво если получили 'c'
      servo_opened = False
  elif event == "o" and not (servo_opened): # открываем серво если получили 'o'
      servo_opened = True

def auto_p_control(data):
  servo_event = data[0]
  servo_control(servo_event) # вызов функции для поворота сервопривода

  print("ANS : " + str(ans))
  uart_write(ans)  # отправка данных на Lua
  sleep(0.08)  # синхронизация

while True: # бесконечный цикл
  uart_data = uart_read() # вызываем функцию чтения
  if uart_data != ['']:  #если прочитанные данные не пустые
      auto_p_control(uart_data) # вызываем функцию ответа

Previous publications:

Scheduled for publication:

Related posts