Перейти к содержимому






Популярно
Фотография
* * * * * 9 голосов

Запускаем дронов!

Написано Totoro , 28 Декабрь 2014 · 13 182 просмотров

opencomputers дрон
Дроны - как керосин. Они есть везде.
Еще года два назад это было просто еще одно интересное видео на Ютубе. Год назад они вдруг оказались в интернет магазинах. Затем просочились в рекламу на ТВ, и вот теперь - они есть и в OpenComputers!
Пришла пора с ними разобраться.

1. Матчасть
Дрон, в данном случае - квадрокоптер, это беспилотный летающий аппарат, приводимый в движение двумя парами горизонтальных винтов. Приостановливая вращение винтов с одного боку, дрон двигается в сторону (стрейф).
Эти винты вращаются в разном направлении (два - по часовой срелке и два - против), за счет чего дрон не нуждается в стабилизирующем хвостовом пропеллере (как вертолет). За счет этого же он и разворачивается в воздухе, замедлив вращение однонаправленной пары винтов.
Дрон обладает небольшой массой, для экономии энергии, которой у него не много (на 10-30 минут полета в среднем).
(с) Википедия

2. Дроны и OpenComputers
Приблизительное изображение дрона в OpenComputers =):

Изображение

В мире Майнкрафта дрон представляет из себя "сущность" (Entity). Это значит, что он обладает возможностями мобов Майнкрафта. (В то время как робот - это блок.)
Его можно сдвинуть с места толкая. Он умеет пролетать сквозь двери и калитки (в отличии от робота). Он движется не последовательно, из блока в блок, а из точки в точку. Причем маршрут может лежать по диагонали.

Конечно, движется он по кратчайшей линии, и если на пути окажется стена - дрон столкнется с нею.

Программирование дрона как две капли воды похоже на программирование микроконтроллера. Вы точно так же записываете программу на EEPROM, и при необходимости меняете ее на верстаке.
Только в отличии от контроллера, вам становится доступен новый компонент: drone.

Подробнее об командах дрона можно узнать здесь: OpenComputers/Дрон. (Или здесь: ocdoc.wiki (англ.))

3. План
Нужна какая-нибудь несложная задача, для целей эксперимента. Используем программку send из предыдущего поста, для удаленного управления. Зальем ее на планшет.
А дрон пусть... носит свиней. Будем оригинальными и непоследовательными.


1. Команда 'add X Y Z Name From'. Добавляем точку Name к маршруту, цепляя ее к точке From.
Зададим дрону последовательность точек, которые образуют граф - безопасные маршруты.
2. Команда 'catch' - дрон ловит свинью.
3. Команда 'drop' - дрон выпускает свинью.
4. Команда 'to X' - дрон летит в точку Х.

Для начала не будем особо заморачиваться с графом маршрутов. Это будет простое неориентированное дерево.
Примерно такое:

Изображение

4. Строим полигон
Построим что-нибудь подходящее для тестов. Отметим ключевые точки будущего графа красными блоками.
А синий блок - будет стартовой площадкой дрона.





Изображение

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

Иначе, к схеме выше было бы необходимо добавить станцию, где дрон мог бы зарядить аккумулятор.


5. Пишем программу
Скрипт для удаленного управления скопипастим из прошлого поста, подправим, чтобы умела отправлять несколько переменных и зальем на планшетик, для удобства.
(Для этого, соберите планшет - не забудьте клавиатуру и видеокарту! - положите его в зарядник и запустите с подключенного компа команду install. Укажите адрес винчестера планшета - и все, что было у вас на компе автоматически загрузится в планшет, включая даже ваши собственные программы.)
local com = require('component')
local modem = com.modem
local args = {...}

modem.broadcast(27, table.unpack(args))
io.write("Message: ")
print(table.unpack(args))
Далее - более сложная часть. Программа дрона. Программа предназначена для EEPROM. Значит соблюдаем те же правила: используем computer, component и API имеющихся у дрона компонентов. Включая его родной компонент drone.
В нашем случае, дрон вооружен апргейдом-лассо (leash) и беспроводной сетевой картой (modem) для связи.

Стоит отметить, что процесс отладки программы (по крайней мере в текущем билде мода) достаточно неудобен. В случае ошибки дрон отказывается включиться, издав тонкий писк, и не выводя никакой информации. Получить отчет об ошибке при помощи анализатора не выйдет - ведь Shift+ПКМ просто снимает дрона. Автор обещал в скором времени это исправить. Ну а пока - помучаемся.

Отредактировать чип в стороннем редакторе, не вынимая его из дрона тоже не выйдет. В отличии от файловых систем, которые имеют удобную папку вида /saves/World/opencomputers/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/, чипы EEPROM хранят свой код в NBT тегах предмета. Этим же обусловлено и ограничение размера кода в 4 килобайта.

5.1. Основная часть
Это цикл который ждет указаний, а затем запускает соответствующую функцию.
drone = component.proxy(component.list("drone")())
modem = component.proxy(component.list("modem")())
leash = component.proxy(component.list("leash")())

modem.open(27)

route = {}
path = {}
current = ""

while true do
  name, _, sender, _, _, message, x, y, z, point, from = computer.pullSignal(1)
  if name == "modem_message" then
    if message == 'add' then
      add(tonumber(x), tonumber(y), tonumber(z), point, from)
      if current == "" then current = point end
    elseif message == 'to' then
      to(x)
    elseif message == 'catch' then
      catch()
    elseif message == 'drop' then
      drop()
    end
  end
  if #path > 0 and drone.getOffset() < 1 then
    drone.move(route[path[#path]].x-route[current].x, 
               route[path[#path]].y-route[current].y, 
               route[path[#path]].z-route[current].z)
    current = path[#path]
    path[#path] = nil
  end
end

modem.close()
Чтобы облегчить себе жизнь (и тестирование bios), вы можете сделать так: напишите заглушку для компонента drone (и других, если надо), вроде этой: http://pastebin.com/EVYzN5Bj
Просто скопируйте в папку на компьютере, где вы пишете программу для дрона.
Затем измените первые строки программы следующим образом:
component = require('component')
computer = require('computer')
drone = require('drone')
modem = component.modem

-- leash = component.proxy(component.list("leash")())
Затем добавьте в цикл условие выхода по нажатию кнопки:
if name == 'key_down' then break end
И вы можете просто запустить вашу программу для дрона на компьютере.
Разумеется полноценной эмуляцией дрона тут и не пахнет, зато очень удобно отслеживать глупые синтаксические и логические ошибки.


Как устроен код основного цикла?
Переменная route - хранит таблицу "вейпоинтов" (waypoints). Это вершины графа и информация о связях между ними.
Переменная path - хранит путь от текущей вершины до цели.
Переменная current - отмечает текущее местоположение дрона в графе.

В цикле мы читаем получаемые сообщения и вызываем соответствующие функции. Первая переданная вершина считается дроном текущей.

Во второй части цикла происходит проверка. Если путь до цели - не пуст (это значит, что дрону надо куда-то лететь) и дрон уже долетел до текущей вершины (getOffset()), то программа берет следующую вершину из path, отправляет дрона к ней и объявляет ее текущей.

5.2. Функции-команды
Теперь последовательно добавим функции для каждой команды.
function add(x, y, z, name, from)
  route[name] = {x=x, y=y, z=z, link = {}}
  if from ~= nil then
    if route[name] == nil or route[from] == nil then
      drone.setStatusText("Error!")
    else
      table.insert(route[name].link, from)
      table.insert(route[from].link, name)
    end
  end
end
Тут все просто. Пишем вершину в список. Если он связана с другой вершиной (from ~= nil), то в специальную табличку link заносим две связи: из name в from, и из from в name.
function search(target, point, prev)
  for key, name in pairs(route[point].link) do
    if name == target then
      table.insert(path, point)
      return true
    end
  end
  for key, name in pairs(route[point].link) do
    if name ~= prev then
      if search(target, name, point) then
        table.insert(path, point)
        return true
      end
    end
  end
  return false
end

function to(name)
  path = {}
  table.insert(path, name)
  search(name, current)
end
Функция to обнуляет старый путь (на всякий случай), затем вставляет в него цель пути (name) и запускает функцию search, которая рекурсивно ищет и записывает остальные промежуточные вершины на маршруте от name до current (текущей локации).
Функция search сделана достаточно примитивно (возможно вы предложите более эффективный способ?). Поскольку мы договорились, в целях упрощения использовать граф-дерево (не содержаший петель), от любой точки к другой существует один и только один маршрут, который функция и находит перебором связанных вершин.
function catch()
  for c = 2, 5 do
    if leash.leash(c) then return true end
  end
  return false
end

function drop()
  leash.unleash()
end
Тут все элементарно.

6. Подготовка
Пишем программу на дрона, заряжаем планшет и выдвигаемся в зону действий. Дрона ставим на синий куб (стартовая площадка) и включаем.

Изображение

После уточнения на местности, составляем карту вейпоинтов и строим на бумажке будущий граф:

Изображение

Для каждого загона добавлены две точки - name и name_up. Основные "трассы" дрона лежат на высоте в 6 блоков. А в каждом загоне спускаются к земле. (Чтобы заарканить животное, выстреливая лассо вбок, дрону желательно находиться на одном уровне с жертвой).

С планшета вносим координаты в память дрона. Примерно так:

Изображение

Главное - не ошибиться. Т.к. в код не была добавлена защита "от дурака" =)
Алгоритм позволяет добавлять вершину "на лету". В любой момент вы можете добавить еще одну ветку к схеме.

Теперь все готово к тесту.

7. Запуск
Все готово.
Проверим, как он двигается.
Введем send to sheeps в консоль планшета. Дрон уверенно поднимается в воздух и опускается в загоне в овцами.

Теперь введем send to pigs. Функция search снова вычислит путь и робот переместится в указанную вершину:

Изображение

Функции catch и drop тоже работают штатно =)

Изображение

Хотя и не лишены некоторых глюков (ведь физика веревки не просчитывается):

Изображение

8. Итоги
а) Дрон - любопытная штуковина.
б) Полный код прошивки. использованный в этом посте - здесь: http://pastebin.com/Cy1UR6vy
в) Навигация по вейпоинтам - интересный и очень распространенный способ организации сложного движения. Схему можно усложнить - опционально добавлять только одну связь в таблицу link - тогда получатся ребра с односторонним движением. Добавить петли, оптимизировать поиск кратчайшего пути.
Еще можно облегчить правление дроном - хранить все команды для конкретной задачи в виде файла-скрипта, который запускать одной командой и т.д.

Enjoy!




Как и прошлый пост, написано интересно, есть скриншоты. Ставлю "лайк" и пятёрку)

    • Totoro это нравится

Как и прошлый пост, написано интересно, есть скриншоты. Ставлю "лайк" и пятёрку)

Спасибо =)

2/3

Работа проделана огромная! Оформлено замечательно! В стиле Тotoro :)

    • Totoro, Fingercomp и Asummonster это нравится
Эх, а игрока заарканить случпем нельзя?

Небольшая "очепятка":

yjFFCB6.png

    • Syabro и qwertyMAN это нравится

Эх, а игрока заарканить случпем нельзя?

Надо пробовать. Еще насчет приватов надо проверить. А то один дрон будет хозяина петлей держать, а второй - грабить. =)

 

Небольшая "очепятка":

yjFFCB6.png

Спасибо, исправил.

    • DUIIIES это нравится

если можно игроков арканить то это же какой транспорт получается 

Тоторе однозначно плюс. Отличный тутор!

    • Syabro, Totoro и Fingercomp это нравится
Фотография
Programist135
20 май 2015 20:14

Totoro, когда я запускаю дрона, то он пролетает 2 блока и останавливается с ошибкой computer halted. Что делать?

Кликнуть анализатором по нему. Должно написать в чат причину краша.

Или "computer halted" это и есть причина? =)

Фотография
Programist135
01 июн 2015 10:41

Или "computer halted" это и есть причина? =)

Да, так и есть.

Фотография
Programist135
01 июн 2015 10:47

если можно игроков арканить то это же какой транспорт получается 

Да, а то мне до друга за вещами далеко бежать =)

Ну, тогда причины могут быть самые разные. Надо дебажить дрона используя вывод в его экранчик, либо сетевые сообщения, или "эмулятор дрона" типа того, который я использовал в этом посте.

@Totoro, есть небольшой вопрос. Координаты при полете дрона относительно чего? Последнего места остановки? Места первичной установки?

Fingercomp подсказывает в чате, что дрон летает относительно текущей позиции.

Но если он уже куда-то летит, то "текущая позиция" смещена в точку назначения. И он полетит относительно неё.

Фотография
HeroBrine1st
22 фев 2017 16:29

Totoro, когда я запускаю дрона, то он пролетает 2 блока и останавливается с ошибкой computer halted. Что делать?

биос(программа) завершил(а) работу и компьютеру (дрону) просто нечего делать.

насчет того что у тебя дрон я уже знаю

биос(программа) завершил(а) работу и компьютеру (дрону) просто нечего делать.

насчет того что у тебя дрон я уже знаю

 

"Дата: 20 Май 2015".
Хорошо получить ответ на свой вопрос. Пусть и два года спустя XD

Игроки выросли, а дроны остались.

    • Totoro это нравится

Обратные ссылки на эту запись [ URL обратной ссылки ]

Обратных ссылок на эту запись нет

Август 2018

В П В С Ч П С
   1234
567891011
12131415161718
192021 22 232425
262728293031 

Новые комментарии

1 посетителей

0 пользователей, 0 гостей, 0 анонимных


Yandex (1)

Последние посетители

  • Фотография
    BrightYC
    20 авг 2018 - 22:17
  • Фотография
    Digitex
    20 авг 2018 - 01:15
  • Фотография
    doktorkrab
    17 авг 2018 - 22:52
  • Фотография
    fancube
    15 авг 2018 - 03:43
  • Фотография
    Fingercomp
    14 авг 2018 - 22:02