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

GPSv2

Рекомендуемые сообщения

Я уже закидывал сюда похожую прогу года три назад, но она кривая-косая, не очень надежная, ну и геморная в плане развертки.
Эта версия более компактная (и простая в постройке), использует упрощенные вычисления и более эффективный механизм передачи сообщения меж компонентами; помимо этого используются особенности микроконтроллеров для автоматической конфигурации системы.
Код в репозитории, для контроллера и периферии. Для постройки одного модуля нужно 3 микроконтроллера второго уровня и один компьютер второго уровня, начинка одинаковая, в каждом нужен процессор, плата оперативной памяти и беспроводная плата второго уровня. Операционная система на компьютер не нужна.

 

В данном контексте компьютер будет контроллером, микроконтроллеры - периферией. Код для них пишется на eeprom. Помимо кода на eeprom можно записать параметры работы (в сегмент данных), для периферии это просто одно число - порт, на котором ожидаются запросы, для контроллера эта строка вида "port: \d+, key: \w+, anchor: \{-?\d, -?\d, -?\d\}", в ней записаны порт, на котором ожидаются запросы и с которого отправляются ответы, ключ-пароль (для настройки координат через беспроводные сообщения, об этом потом), а также якорь - координаты компьютера. По умолчанию используется 312 порт, ключ-пароль admin, и координаты {0, 0, 0}.

 

Схема постройки простая, нужно установить где-либо компьютер-контроллер, а потом вплотную к трем его сторонам установить микроконтроллеры-периферию, при этом не должно быть такого, что контроллер расположен между двумя периферийными микроконтроллерами (если с одной стороны есть микроконтроллер, на противоположную ставить нельзя). Помимо этого лицевые стороны микроконтроллеров (одна из 6 сторон имеет иную картинку, и, что важно, к ней не присоединяются провода) не должны смотреть на контроллер.
После постройки нужно единожды включить каждый из 4 компонентов, они при этом сами быстро выключатся. Это нужно для настройки модема, для того, чтобы компонент просыпался при получении определенного сообщения.
После этого система уже готова к работе, но при этом не знает (если это не было заранее записано в сегмент данных eeprom контроллера) своих координат, и будет отвечать на все запросы относительными. Для включения системы достаточно отправить сообщение "gps_wake", при этом система запустится, сконфигурируется, и после этого отброадкастит сообщение "gps_ready". Такое же сообщение, но на адрес того, от кого пришло "gps_wake", отправится в случае, если система уже активна на момент получения запроса.
Для того, чтобы сообщить координаты контроллеру, нужно отправить сообщение "gps_anchor", после которого идет ключ-пароль (записан в сегменте данных eeprom контроллера), после которого идут координаты (3 числа) контроллера. Координаты при этом запишутся на eeprom, т.е. при выключении-включении они все так же будут известны контроллеру.

 

Для использования системы достаточно отброадкастить "gps_request", контроллер ответит (именно тому, от кого запрос) сообщением "gps_response", после которого идут 3 числа - координаты x, y, z. Таймаут обработки запроса - 1 секунда, если вдруг 1 секунда прошла, а ответа не пришло - что-то не так. При этом контроллер при таймауте запроса забывает все его данные, поэтому кривой запрос (например, отправленный сквозь толстую стену, которая снизила мощность сигнала настолько, что он дошел лишь до части системы) не будет "портить" последующие. Имеет смысл "включить" систему перед первым запросом (послать "gps_wake" и дождаться ответа "gps_ready"), на непосредственно включение уйдет до примерно 2 секунд (вообще с потолка взял, на деле должно шустрее, но внутри таймаут привязки стоит именно 2 секунды, после этого он отправляет 3 сообщения периферии и посылает сообщение о готовности), включенная же сразу ответит.

 

Картинка для референса:
sAk9NAg.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Суть упрощенных вычислений - в прошлой реализации я решал СЛУ методом крамера, а там много умножений. В этой реализации я пользуюсь геометрией системы:
Будем искать относительные координаты цели. Относительные координаты контроллера - (0, 0, 0), 3 микроконтроллеров - (+-1, 0, 0), ... ,(0, 0, +-1).
Вместо решения той системы (подробно об этом в прошлой теме) из 3 уравнений, будем решать систему из других трех уравнений, конкретно получаемых вычитанием из первого уравнения предшествующей системы второго, третьего и четвертого. Из-за особого вида координат контроллера и микроконтроллеров уравнения получаются вида x_i * (2x - x_i) = d_0^2 - d_i^2 (d_0 - расстояние до контроллера, d_i - расстояние до микроконтроллера, у которого i-я координата не ноль, x_i - ровно эта i-я координата) и из них весьма тривиально выражаются x, y и z.
Для получения относительных координат контроллеров пользуемся способностью микроконтроллеров "закрывать" стороны, чтобы через них не отправлялись проводные сообщений. Стороны у него не относительные (перед-зад), а абсолютные (юг-север). Собственно, на этапе конфигурации каждый микроконтроллер отправляет в каждую сторону (кроме лицевой, ибо на ней он крашится, но т.к. делает он это через pcall, все окей) сообщение, контроллер же ловит их и запоминает, с какой стороны пришло.

 

Ну и как обычно, важное уточнение, подобный жпс дает координаты с точностью до блока, ибо события модема дают расстояние именно до блока, а не до entity, от которой пришло сообщение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@jammer312 Отличная работа. Особенно мне понравилась идея автоматического конфигурирования ячейки GPS по сторонам света. Компактный алгоритм вычисления координат тоже хорош.

 

 

Я предлагаю ещё сильнее упросить конфигурирование. Сейчас есть такое требование:

19 часов назад, jammer312 сказал:

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

Микроконтроллеры можно включать, обращаясь к ним как к компонентам компьютера:

component.microcontroller.start()

Если новые члены GPS-ячейки не проснулись по сообщению пробуждения до истечения таймаута, их можно включить индивидуальной командой.

 

 

Код довольно чистый, но у меня есть несколько замечаний:

  • Под номер порта выделена переменная, но кое-где остался захардкоженный вариант:
port = tonumber(port) or 312

m.send(a, 312, "gps_periphery_bind", a, s)
  • В функции handle_request для поля timeout по смыслу больше подходит название deadline.
  • Также в коде зачем-то объявлены переменные, которые используются один раз. Примеры:

В дальнейшем используется лишь одна переменная port:

local e = prx"eeprom"
local edata = e.getData()
local port = tonumber(edata) or 312

 

Здесь не нужна переменная owm, т.к. setWakeMessage возвращает предыдущее значение:

local owm = m.getWakeMessage()
m.setWakeMessage(wm)
if owm ~= wm then

 

А здесь не нужна переменная ok:

ok = pcall(open, side)
if ok then

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Про включение микроконтроллеров компьютерами знаю, здесь оно не используется из-за того, что нет возможности определить, относится ли микроконтроллер к ячейке или нет. Использование прямого включения в качестве запасного варианта делает нежелательным установку gps ячейки (точнее, ее контроллера) вплотную в другим микроконтроллерам, ибо и при первоначальном включении, и в случае форсмажора, из-за которого один из микроконтроллеров ячейки не проснулся, может включиться лишний микроконтроллер (вред этого варьируется в зависимости от назначения этого микроконтроллера). Могу сделать дополнительную версию, включающую подобный функционал, но имхо овчинка выделки не стоит (3 лишних прожатия пкм при постройке погоды не сделают).

 

Захардкоженный порт поправил, поле переименовал, `ok` сделал локальной.
Про объявление локальных переменных, использующихся один раз - мне кажется, их использование положительно влияет на читаемость кода, при этом потери от их объявления минимальны (емнип, луа держит локальные переменные на стеке, а может даже (некоторые) на регистрах, ну и оптимизаций при компиляции никто не отменял; даже если ничего из этого не выполняется, все равно упомянутые потери несоизмеримо малы по сравнению с временем работы компонентов). В частности, то, что `setWakeMessage` возвращает старое значение, мне не кажется очевидным, к тому же вики умалчивает об этом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
18 часов назад, jammer312 сказал:

Про включение микроконтроллеров компьютерами знаю, здесь оно не используется из-за того, что нет возможности определить, относится ли микроконтроллер к ячейке или нет.

...

Могу сделать дополнительную версию, включающую подобный функционал...

Не надо дополнительную версию. Предлагая эту идею, я надеялся, что у нас схожее представление об удобстве. Мне нравятся простые в настройке изолированные системы с минимальным влиянием друг на друга. Для тебя же является нормой тесное соседство различных систем. Пусть так и остаётся.

 

18 часов назад, jammer312 сказал:

Про объявление локальных переменных, использующихся один раз - мне кажется, их использование положительно влияет на читаемость кода, при этом потери от их объявления минимальны

Согласен, чем-то приходится жертвовать. Код, написанный для EEPROM, пробуждает во мне оптимизатора. Но да, выигрыш там не существенен.

 

Кстати, стек стеком, но переменная в Lua не удаляется сразу после её использования. Она удалится по завершении контекста, в котором была создана. Про сборщик мусора пока не говорим, промежуточные значения в любом случае где-то хранятся и как-то со временем удаляются.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Как это вообще нафиг работает?

Типо ну да стоит 3 контроллера и 1 пк но как оно определяет почти точную позицию чела

Изменено пользователем ItsMakar
Вопросительный знак

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
6 часов назад, ItsMakar сказал:

Как это вообще нафиг работает?

Типо ну да стоит 3 контроллера и 1 пк но как оно определяет почти точную позицию чела

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
4 часа назад, Zer0Galaxy сказал:

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

ясно

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...