Модуль оптического позиционирования

https://storage.yandexcloud.net/pioneer-doc.geoscan.ru-static/images/modules/optical_nav.png

Модуль позволяет позиционировать квадрокоптер, используя оптический датчик, который отслеживает смещение объектов. Это дает возможность удерживать положение и летать в автоматическом режиме без системы навигации и GPS. Модуль монтируется на плате расширения снизу и требует подключения шлейфом с базовой платой.

Модуль оснащен оптическим дальномером. Он может определять высоту над полом или препятствием в пределах 0-1,5 м. Если коптер поднимается выше этой отметки, зеленый светодиод на модуле перестает мигать и горит постоянно. Это говорит о том, что теперь для определения высоты используется барометр.

Подключите Пионер к Pioneer Station и активируйте кнопку OPT в параметрах автопилота, чтобы использовать модуль при полёте.

При программируемом полете используется команда ap.goToLocalPoint(x, y, z). При запуске моторов квадрокоптер запоминает точку старта как (0, 0, 0). При этом ось y направлена вперед (по направлению квадрокоптера), ось x - вправо. Параметр z отвечает за высоту полёта. Значения (x, y, z) в метрах задают координаты точки, в которую полетит квадрокоптер, относительно точки старта.

Примечание

Чем больше суммарная протяженность полета, тем больше будет накопленная ошибка. При этом снижается точность позиционирования.

Модуль распознает поверхность, над которой летит квадрокоптер. Чем больше деталей (таких как орнамент или стыки между плитками) попадает в поле зрения, тем точнее будет полёт.

Управляя квадрокоптером с пульта, выберите режим работы с системой навигации (тумблер SwB в среднем положении), и «Пионер» будет использовать подключенный модуль оптического потока, что сделает полет более стабильным.

Обновление прошивки

Для обновления прошивки модуля на вашем компьютере должна быть установлена программа Pioneer Station. Нажмите и удерживайте кнопку «Старт» на базовой плате квадрокоптера, и подключите кабелем microUSB к компьютеру. Запустите Pioneer Station, выберите пункт меню «Обновление прошивки» и следуйте указаниям помощника. При переходе к пункту «Выбор устройства» в списке будет отображаться не только базовая плата квадрокоптера PioneerBase, но и модуль оптического потока ModuleOptFlow. Поставьте галочку напротив модуля и нажмите «Далее». При выборе источника прошивки рекомендуется «встроенный» - это последняя актуальная версия, входящая в сборку программы. Если версия модуля не определяется автоматически, прочтите маркировку на обратной стороне платы и выберите соответствующую прошивку из доступных в папке Pioneer Station. Дождитесь окончания прошивки. После этого квадрокоптер перезагрузится в обычный режим.

Пример

Ниже приведен пример программы, использующий модуль оптического потока. Чтобы загрузить программу на «Пионер», воспользуйтесь Pioneer Station. Включите Пионер, пульт, переведите переключатель SwB в нижнее положение и нажмите кнопку «Старт» на базовой плате квадрокоптера. Через 5 секунд квадрокоптер взлетит, пролетит на 1 метр вперед и вернется в исходную точку для посадки.

-- https://learnxinyminutes.com/docs/ru-ru/lua-ru/ ссылка для быстрого ознакомления с основами языка LUA
-- количество светодиодов на основной плате пионера
local ledNumber = 4
-- создание порта управления светодиодами
local leds = Ledbar.new(ledNumber)
-- ассоциируем функцию распаковки таблиц из модуля table для упрощения
local unpack = table.unpack

-- переменная текущего состояния
local curr_state = "PREPARE_FLIGHT"

-- функция, изменяющая цвет 4-х RGB светодиодов на основной плате пионера
local function changeColor(color)
    -- проходим в цикле по всем светодиодам с 0 по 3
    for i=0, ledNumber - 1, 1 do
        leds:set(i, unpack(color))
    end
end

-- таблица цветов в формате RGB для передачи в функцию changeColor
local colors = {
        {1, 0, 0}, -- красный
        {1, 1, 1}, -- белый
        {0, 1, 0}, -- зеленый
        {1, 1, 0}, -- желтый
        {1, 0, 1}, -- фиолетовый
        {0, 0, 1}, -- синий
        {0, 0, 0}  -- черный/отключение светодиодов
}

-- таблица функций, вызываемых в зависимости от состояния
action = {
    ["PREPARE_FLIGHT"] = function(x)
        changeColor(colors[2]) -- смена цвета светодиодов на белый
        Timer.callLater(2, function () ap.push(Ev.MCE_PREFLIGHT) end) -- через 2 секунды отправляем команду автопилоту на запуск моторов
        Timer.callLater(4, function () changeColor(colors[3]) end)-- еще через 2 секунды (суммарно 4 секунды, так как таймеры запускаются сразу же друг за другом) меняем цвета светодиодов на зеленый
        Timer.callLater(6, function ()
            ap.push(Ev.MCE_TAKEOFF) -- еще через 2 секунды (суммарно через 6 секунд) отправляем команду автопилоту на взлет
            curr_state = "FLIGHT_TO_FIRST_POINT" -- переход в следующее состояние
        end)
    end,
    ["FLIGHT_TO_FIRST_POINT"] = function (x)
        changeColor(colors[4]) -- смена цвета светодиодов на желтый
        Timer.callLater(2, function ()
            ap.goToLocalPoint(0, 1, 1) -- отправка команды автопилоту на полет к точке с координатами (0 м, 1 м, 1 м)
            curr_state = "FLIGHT_TO_SECOND_POINT" -- переход в следующее состояние
        end)
    end,
    ["FLIGHT_TO_SECOND_POINT"] = function (x)
        changeColor(colors[5]) -- смена цвета светодиодов на фиолетовый
        Timer.callLater(2, function ()
            ap.goToLocalPoint(0, 0, 0.8) -- отправка команды автопилоту на полет к точке взлета (0 м, 0 м, 0.8 м)
            curr_state = "PIONEER_LANDING" -- переход в следующее состояние
        end)
    end,
    ["PIONEER_LANDING"] = function (x)
        changeColor(colors[6]) -- смена цвета светодиодов на синий
        Timer.callLater(2, function ()
            ap.push(Ev.MCE_LANDING) -- отправка команды автопилоту на посадку
        end)
    end
}

-- функция обработки событий, автоматически вызывается автопилотом
function callback(event)
    -- если достигнута необходимая высота, то выполняем функцию из таблицы, соответствующую текущему состоянию
    if (event == Ev.TAKEOFF_COMPLETE) then
        action[curr_state]()
    end
    -- если пионер с чем-то столкнулся, то зажигаем светодиоды красным
    if (event == Ev.SHOCK) then
        changeColor(colors[1])

    end
    -- если пионер достигнул точки, то выполняем функцию из таблицы, соответствующую текущему состоянию
    if (event == Ev.POINT_REACHED) then
        action[curr_state]()
    end

    -- если пионер приземлился, то выключаем светодиоды
    if (event == Ev.COPTER_LANDED) then
        changeColor(colors[7])
    end

end

-- включаем светодиод (красный цвет)
changeColor(colors[1])
-- запускаем одноразовый таймер на 2 секунды, а когда он закончится, выполняем первую функцию из таблицы (подготовка к полету)
Timer.callLater(2, function () action[curr_state]() end)