
Введение
Как и многие, кто работает в ИТ я обожаю «Технологические преколы». Когда я впервые увидел робота‑доставщика Яндекса, первая мысль была: «Мне срочно нужен этот прикол. Не знаю зачем, но надо».
Первая остановка — Авито. Казалось бы, этого добра там должно быть навалом: списанные, убитые, оставленные в неположенных местах. Может, их даже продают под видом детских игрушек... или игрушек для взрослых. Тут уже в меру вашей испорченности.
Спойлер: на Авито роботов не оказалось. Я немного расстроился, но быстро забыл. Ну и ладно, не очень-то и хотелось.
Проходит четыре года. Я листаю Яндекс.Маркет и натыкаюсь на вот это.

Я почти нажал кнопку "Купить", но в последний момент задумался: "А какой в этом инженерный вызов? Скорее всего, после покупки я покатаю этого бота по квартире минут двадцать, а потом он отправится пылиться на полку. Я даже не куплю Raspberry Pi, потому что это слишком быстро надоест". Я решил взять время на раздумья.
А на следующий день на авто-ру увидел это:

И тут понял: вот оно. Это идеальная форма для визуального коллаба с роботом-доставщиком.
Что-то типа оглавления
Раздел 1. Дизайн
На Ozon я нашёл вот такую модельку. Заказал её и начал адаптировать окраску под оригинального доставщика от Яндекса.
    Спойлер №2: третья версия робота-доставщика для этого плохо подходила.

В итоге, для адаптации я выбрал первую версию доставщика — с белым кузовом и чёрно-жёлтыми декалями. Так, в обычном грузовике, сохранись образы оригинального робота-доставщика.

Я не буду долго описывать процесс покраски, и просто скажу, что для этого потребовалось:
- 3 балончика краски. Белая, черная и красная. 
- Тюбик желтой и черной акриловой краски. 
- Коробка из под монитора, чтобы красить в подъезде, а не на улице в -30°. 
Получилось вот так:

В итоге, я постарался найти баланс между "В теории это мог бы быть реальный грузовик от Яндекса" и "Он должен напоминать робота-доставщика". Это все еще робот, который будет возить небольшие штуки по дому между разными точками, но он не увешан датчиками, со всех сторон, как оригинальный робот-доставщик. По крайней мере пока не увешан.
В собранном виде это выглядит вот так:

В конце решил добавить в грузовой кузов лого Яндекса. Поскольку, модель грузовика японская, то и лого Яндекса пришлось "японизировать"

На этом часть с дизайном закончена. Давайте опишем техническую часть.
Раздел 2. Hardware
Изначально я планировал использовать оригинальную плату грузовичка. Для этого нужно было пайнуться в 2-3 местах: на драйвер основного двигателя, и на управляющий контакт рулевого сервопривода. Оригинальная плата выглядела вот так.

Начнем решать вопрос по частям.
1. Двигатель
Первое, о чем хочу предупредить: не используйте LLM в качестве основного советника по схемотехнике. Чат-ГПТ выдал ответ примерно на 100% состоящий из галлюцинаций.
 Дурак ли я, что поверил ему?
     - Да.
 Спалил ли я оригинальную схему?
     - Нет. Но очень сильно перегрел драйвер двигателя, подавая напряжение не на те контакты.
Из этого всего можно сделать вывод: программисты, возрадуйтесь - сегодня нейросети вас не заменят. Схемотехники - возрадуйтесь вдвойне.
Вернемся к повествованию. Посмотрев на плату, я примерно определил, что есть что. Полез гуглить. По запросу "6586 2402JF" я нашел примерно ничего. Чат-ГПТ выдал галлюцинации (смотрите историю выше), и я пошел в группы для робототехников.
Спасибо чату IT Lobby Irkutsk, в нем нашлись пару человек, которые подсказали, что это типовой драйвер TA6586 и скинули даташит на него.

2. Сервопривод
С сервоприводом все оказалось попроще. Я купил SG90 в подвале на рынке для экспериментов. Почитал по нему документацию, и понял, что управляется он тем же ШИМом. У меня не было под рукой подходящего источника импульсов, но я понимал, что проблема решается буквально в пару строк кода на условной Arduino или RaspberyPi.
После неудачного эксперимента с драйвером на оригинальной плате, я решил спаять отдельную плату расширения для управления питанием двигателя и сервопривода.
3. Плата расширения
Небольшой дисклеймер: я не то что бы всю жизнь занимаюсь проектированием плат. Я понимаю принципиальные вещи и умею держать паяльник в руках. Это моя первая полноценно спроектированная и изготовленная плата, не судите строго. Ко многим выводам я пришел в процессе разработки.
Как я уже написал, в какой-то момент я понял, что не хочу рисковать оригинальной платой, и решил спаять условный "драйвер управления грузовиком".


По итогу, я получил такого урода:

Результат меня мягко говоря не устроил. Недолго думая, спроектировал вторую версию платы. Главная фишка V2 - я развел плюсовую и минусовую шину по разные стороны платы. Получилось гораздо безопаснее.


4. Микрокомпьютер
У меня дома валяется Raspbery Pi Pico. Изначально я думал, что мне хватит его, потому что основную логику планировал крутить вне "грузовичка".
Ошибся я только в одном: у Raspbery Pi Pico отсутствует любая связь как таковая.
Варианта было два:
- Взять модуль Wi-Fi+BT под Raspbery Pi Pico. 
- Купить микрокомпьютер сразу с нужным модулем. 
Полистав форумы, пришел к выводу, что Orange Pi Zero 3 - лучшее, что можно найти под мой проект.
За 3 000 рублей вы получаете:
- Идеальный размер. Это 5*5 см. Влезает в любой DIY проект. 
- На борту Wi-Fi, Bluetooth, RJ-45 и бесполезный micro-HDMI. 
- 4 ядра и 2Gb RAM. Вообще я покупал версию на 1Gb, но опустим эту мелочь. 
- Ноги с ШИМом. И вообще, достаточно много ног. 
На этом в теории можно пускануть не требовательный проект, или собрать домашний NAS. Двигать модельку грузовика вперед-назад-влево-вправо она сможет. Обрабатывать видеопоток и сигналы от BT-маяков - пожалуйста.
ИМХО: Эта плата - самый сбалансированный микрокомпьютер по параметрам цена/размеры/производительность из всего, что я просмотрел.
5. Сборка
Сборка без кабины выглядит вот так. Я намеренно разделил контуры питания микрокомпьютера и "грузовичка", чтобы:
- Не париться с подключением "Оранжки" в общий контур питания. 
- Мозги должны работать даже тогда, когда батарея грузовика сядет. 
- Вытекает из второго: если масштабировать проект на грузовичок побольше - нужно быть независимым от контура питания автомобиля. С выключенным двигателем комп побольше не протянет долго. 
Глобальных изменений с точки зрения HW пока не планируется. Теперь мяч на стороне SW.

Раздел 3. Навигационная система.
На текущий момент реализовано около 10% задуманного функционала. В голове архитектура проекта выглядит следующим образом:

1. Определение позиции
Основной источник координат — Bluetooth-модуль. Он использует функцию position(), которая считывает силу сигнала от 4 Bluetooth-маяков, которые расположены в углах квартиры, и передает рассчитанную позицию в модуль формирования промпта.
2. Формирование промпта для LLM
Данные для формирования промпта поступают из нескольких источников:
- Телеграм-бот — для задания целевой точки движения. 
- Bluetooth-модуль — для определения текущего местоположения. 
- Энкодер поворота — для контроля угла колес. 
- Дополнительные датчики (опционально) — например, IMU или энкодеры на ведущих колесах, камера, лидар. Именно поэтому я решил использовать для управления LLM. Теоретически в любой момент можно попробовать добавить новые входящие сигналы, а языковая модель адаптируется к этим изменениям. 
Все эти данные скриптом собираются в промпт для LLM, которая выступает в роли "алгоритма навигации"
3. Обработка данных LLM и управление приводами
LLM анализирует входные данные и формирует JSON-ответ следующего формата:
`{   
"forward": speed,
"back": speed,
"left": angle,
"right": angle
}Серверная часть "драйвера" принимает этот JSON и выполняет соответствующие команды:
- Включает газ или реверс с заданной скоростью. 
- Поворачивает руль на указанный угол. 
- Двигается небольшими шагами (t мсек), после чего запрашивает новый ввод от LLM. 
Процесс повторяется до тех пор, пока текущая позиция (по данным от маяков) не совпадет с целевой точкой, заданной через Телеграм-бот.
Пока что мне лень реализовывать какой-то более быстрый способ связи между LLM и драйвером, поэтому для начала попробую REST.
4. Управление сервоприводом и двигателем
Сервопривод и двигатель работают по схожему принципу:
- Управляются через ШИМ (широтно-импульсную модуляцию). 
- Для сервопривода частота ШИМ определяет угол поворота. 
- Для двигателя — скорость вращения. 
Этими параметрами будет управлять библиотека, которую скорее всего придется написать ручками. Библиотека будет получать ввод от модуля, который взаимодействует с LLM, и преобразовывать его в нужную частоту на нужном пине.
Текущий статус разработки
Как я уже сказал, программная часть не еще завершена. Я разобрался с управлением двигателем и сервоприводом — могу задавать скорость вращения колес и угол поворота. Однако интеграция с LLM и Bluetooth-маяками еще в процессе. Надеюсь когда-нибудь меня отпустит работа и домашние дела, и я закончу этот проект.
Когда эта штука поедет - напишу вторую часть поста.
Комментарии (7)
 - iliasam10.02.2025 08:36- Идея использовать LLM (языковую модель) для управления движением по карте удивила. Думаю, какой-нибудь "A star" в данном случае будет куда меньше, проще, быстрее и надежнее. 
 Изобретение велосипедов - дело увлекательное, но с ROS можно получить результаты куда быстрей. - susuoltcev Автор10.02.2025 08:36- Здесь все правильно. Я хочу поизобретать велосипед. Это стрельба из пушки по воробьям, но это, что говорится, "хайп". 
 
 - engin10.02.2025 08:36- Идея с текстом не нова, не поленился нагуглил с десяток. 
 Google Indoor Maps от Google где они предоставляют решения для создания карт и навигации внутри зданий, используя бинарные карты, которые помогают пользователям находить свои пути в больших помещениях, таких как торговые центры, университеты и аэропорты. В некоторых случаях Google использует текстовые инструкции, чтобы направить пользователей к нужному месту, основываясь на их текущем положении.
 Есть и другие проекты IndoorAtlas, NavVis, Navigine, RoboSense, learPath Robotics и т.д., все они используют бинарные карты для решения задач навигации внутри зданий и других ограниченных пространств, при этом создавая текстовые указания для пользователей или автоматических систем.
 Подавляющая часть разрабов применяют iOS, Android с на базе NVIDIA Jetson, Intel NUC, Raspberry Pi и др. - iliasam10.02.2025 08:36- Подозреваю, что маршрут там строится классическими алгоритмами, и только потом превращается в текстовые подсказки. Традиционные приложения для навигации по GPS уже лет 20 так работают.  - engin10.02.2025 08:36- Бинарные карты изначально несут на себе регион в XY в пределах ограниченных периметров, их точность задается плотностью бинарных значений в пределах N пикселей . Генерирования таких карт происходит на базе растровых или векторных изображений. 
 И да в алгоритме перемещения присутствует обратная связь для позиционирования коррекции углов поворота и т.п. На каких принципах строить обратную связь, решать разработчику, к слову их не так и много, как хотелось бы, собственно как и в целом методов взаимодействия с картами. Их так же, увы мало - растровая карта без связи с логикой (навигация GPS или маячки), бинарная, оптическое распознавание статических маркеров, магнитуда иногда их смешивают между собой.
 
 
 
           
 
positroid
Эх, на самом интересном месте.
А что за конфигурация квартиры / bt-маяки / точность определения координат по ним? Уже делали какие-то вычисления и замеры или есть какая-то готовая система, доступная для DIY?
UPD: и по поводу корректности управления через промптинг для LLM (какой?) будет интересно почитать про результаты. LLM это все же не математический аппарат и точные расчеты проводить не умеет
susuoltcev Автор
Квартира самая тривиальная хрущевка. Прямоугольное пространство с препятствиями. LLM-ке я представлю его как массив нулей и единичек. 0 - ехать можно. 1 - нельзя.
Блютуз-маяки пока ХЗ какие. Но какие-то дома валяются. Еще не экспериментировал с этим. Хотелось бы верить, что работать это будет достаточно предсказуемо, по факту посмотрю.
LLM это все же не математический аппарат и точные расчеты проводить не умеет.
Эту гипотезу я тестировал. Суть была следующая: даю Чату-ГПТ массив нулей и единиц. Правила все те же: 0 - свободно, 1 - не проедешь.
Дал задачу достигнуть точки 5:3.
Просил у Чата-ГПТ ввод функции (вперед/назад/влево/вправо) + значение.
На вывод Чата-ГПТ двигал воображаемую "машину" по массиву.
Возвращал Чату-ГПТ его конечную точку в зависимости от предыдущего вывода.
Предварительно описал для себя правила, как будет меняться положение "машины" на плоскости в зависимости от "введенной функции"
И это таки заработало. Чат-ГПТ быстро понял как рулить, что просто повернуть колеса недостаточно, нужно еще нажать на газ.
Не с первого раза, но он научился добираться в указанную точку.