Мы создали симуляцию 3D‑города с машинами, пешеходами и светофорами, по которому ездит шестиколёсный робот под управлением настоящего скетча Arduino. Все это для обучения детей и взрослых в кружках робототехники.

У нас есть онлайн‑лаборатория PinPort: в браузере собираешь схему, пишешь скетч для Arduino, и он исполняется на эмуляторе микроконтроллера. Светодиоды и датчики там давно, потом появились роботы. В этот раз задача была такая: сделать виртуальный город с улицами, машинами, пешеходами и светофорами. По нему ездит робот‑доставщик, и его задача — довезти заказ из пункта A в пункт Б.

Робота назвали R‑D6: шесть колёс, разворот на месте. Управляет им не скрипт на JavaScript, а обычный скетч для Arduino Uno. Скетч собирается на сервере через arduino‑cli, а полученная прошивка исполняется покомандно в эмуляторе ATmega328P. Ниже расскажу, из чего всё это состоит.

Три части успеха

У системы три части, и они движутся строго вместе:

  1. Плата. Эмулятор AVR исполняет прошивку с частотой 16 МГц: таймеры, ШИМ, I2C, UART.

  2. Физика. Робот — твёрдые тела в Rapier: корпус, шесть колёс, моторы. Шаг мира — 2 мс.

  3. Город. Светофоры, машины и пешеходы — своя логика, которая задаёт положение кинематических тел в том же мире Rapier.

Плата и физика идут поочередно: две миллисекунды процессора, затем один шаг мира. За эти две миллисекунды придуманный нами класс собирает с выводов платы скважность ШИМ на ENA/ENB и уровни IN1–IN4 драйвера L298N и превращает их в напряжение на моторах. В обратную сторону идут показания датчиков: цифровые пины попадают на выводы D2/D3, лидар и навигатор — в регистры устройств на шине I2C.

Почему именно так? Из‑за повторяемости. Если связать слои через реальное время, тот же скетч на слабом ноутбуке и на сильном десктопе поедет по‑разному. У нас есть уроки с автопроверкой и арена, где заезды считает сервер, так что результат обязан быть одинаковым везде.

Датчики как файлы регистров

В жизни лидар и навигатор общались бы с контроллером по UART со своим протоколом. Мы взяли самую простую для школьника схему — файл регистров на I2C. Первый байт записи задаёт номер регистра, дальше чтение идёт подряд, как у MPU6050 или DS3231.

Устройство

Адрес

Что отдаёт

Как часто обновляется

Лидар

0×52

36 секторов по 10°, расстояние в см (uint16), номер оборота

10 раз в секунду

Навигатор с камерой светофоров

0×53

флаги, сигнал перехода, номер точки, курс, угол на цель, расстояния, скорость, координаты

50 раз в секунду

Скан лидара — 72 байта, а буфер библиотеки Wire на Uno — 32. Поэтому встроенная библиотека RD6.h читает его тремя кусками по 24 байта, и только когда счётчик оборотов изменился. Мелочь, но она честная: с таким же ограничением сталкивается любой, кто пишет драйвер датчика на настоящей плате.

Сам лидар — это лучи в мире движка Rapier. В каждом секторе их три (−3°, 0°, +3°), и берётся ближайшее попадание. С одним лучом на сектор столб светофора толщиной 14 см с пяти метров проскакивал между лучами, и робот в него врезался. Дальность 20 м, дальше лидар отдаёт 2000 см — «ничего нет».

Город

План — сетка улиц 3 × 3 с шагом 32 м. Проезжая часть 8 м, по полосе в каждую сторону, тротуары по 3 м. На пяти перекрёстках стоят светофоры, у них 16 зебр. Цикл светофора — 50 с: 20 с зелёный одному направлению, 3 с жёлтый, 2 с все красные. У пешеходов зелёный горит вместе с попутным потоком машин, последние 4 с мигает.

Машины (12 штук) ездят по полосам, стоят на красный, держат дистанцию и на перекрёстке выбирают поворот случайно. Повороты идут по дугам: направо — вокруг угла бордюра радиусом 2 м, налево — радиусом 6 м. На перекрёсток машина не въезжает, пока там едет кто‑то, чей путь пересекается с её путём. Если подъехали одновременно, первой едет та, у кого номер меньше. Столь тупое правило надёжно исключает взаимную блокировку.

Пешеходы (20 человек) ходят по петлям тротуаров вокруг кварталов, каждый на своём расстоянии от бордюра. У зебры человек с вероятностью 0,4 решает перейти улицу. Он ждёт у бордюра и начинает переход только на зелёный, а на мигающий уже не начинает. Роботу пешеходы уступают. Если робот стоит впереди ближе 1,7 м, человек останавливается, а через 0,6 с отступает в свою сторону, не перебегая перед роботом.

Машины и пешеходы — кинематические тела того же мира. Нас интересуют два последствия. Лидар видит их теми же лучами, что дома и деревья. А удар робота о пешехода — настоящий контакт в физике.

Навигатор и «морковка»

Маршрут строится алгоритмом Дейкстры по графу. Узлы графа — углы петель тротуаров, концы зебр, пункты A и Б.

Угол на цель навигатор отдаёт не на следующую точку, а на «морковку» — точку на линии маршрута в 2,5 м впереди робота. Это классический pure pursuit ( геометрический алгоритм управления движением мобильных роботов и автономных автомобилей, который заставляет транспортное средство следовать по заданной траектории, «преследуя» целевую точку на некотором расстоянии впереди ). Без него робот срезал к точке, до которой ещё 20 метров, уходил к бордюру и вставал перед деревьями, которые растут вдоль бордюра через каждые 8 м. С морковкой он держится середины тротуара и оси зебры.

Рядом работает судья. Он записывает финиш (центр робота ближе 1,5 м к Б), переход на красный (робот ступил на зебру, когда пешеходам горит красный), выезд на проезжую часть не по переходу и столкновения — раз в 20 мс по контактам физики.

Детерминизм: один скетч, один хеш

Ради этого всё и делалось так аккуратно. Три правила:

  • Случайность — только из генератора с зерном (mulberry32). Зерно задаётся свойством детали «Случай»: кто где появился, как сдвинуты фазы светофоров, кто решит перейти улицу.

  • Время — только шаги физики. Никаких Date.now() и performance.now() в модели.

  • Решения — на фиксированной сетке. Машины и пешеходы решают, что делать, раз в 20 мс, а двигаются на каждом шаге.

Проверяется это тестом. Одну и ту же прошивку гоняем дважды с разной нарезкой времени: по 2 мс и по 7,3 мс за вызов. Сравниваем хеш состояния мира — он должен совпасть. В бою проверка такая: на арене есть лига «Доставка», и там сервер гоняет прошивку участника в Node.js на тех же модулях, что и браузер. Хеши заездов на сервере совпали с теми, что мы получили локально, до последнего знака. А время доставки в браузере совпадает с тестом до десятой секунды.

Рисование

Отрисовка сделана на своём маленьком WebGL‑рендере без движков. Дома — коробки, окна рисует фрагментный шейдер по координатам: окно через 2,6 м вдоль стены и через 3 м по высоте, на первом этаже витрины. Ночью тот же шейдер зажигает около 45% окон по хешу этажа и пролёта — без единой текстуры. Камера едет за роботом и сама заходит ему за спину. Если робота закрывает дом, она поднимается; кроны деревьев на линии взгляда просто не рисуются.

Есть и вид сверху на Canvas 2D. Ему не нужен WebGL, и для отладки он полезнее объёмного: видно маршрут, сигналы всех светофоров и куда бьют лучи лидара.

Что получилось

Автопилот из пяти правил, который лежит в галерее примеров, прошёл все 12 комбинаций «маршрут × случай» без нарушений. Доставка занимает от 65 до 135 секунд модельного времени. Если вырезать из скетча правило светофора, судья записывает переход на красный. Потом появились уроки с автопроверкой и лига на арене. Добавились и условия: ночь, час пик с 40 пешеходами и ремонт тротуара, который приходится объезжать.

В следующей статье разберём сам автопилот: пять правил, коридор по лидару и светофор — с кодом.

Детали робота R‑D6

Посмотреть код и попробовать: «робот R‑D6 везёт заказ из A в Б по городу», кнопка «Запустить», регистрация не нужна. https://pinport.ru/p/ex‑robot‑rd6-delivery

Комментарии (16)


  1. reddice
    12.10.2026 20:15

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


    1. b_vova Автор
      12.10.2026 20:15

      Спасибо, я сам залипаю над тем, что получилось ))))


    1. 00Kirill00
      12.10.2026 20:15

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


  1. jorge-list
    12.10.2026 20:15

    О, как замечательно!
    А мы в Ассоциации Пошли-Поехали как раз обсуждаем в том числе интеграцию роботов-доставщиков в транспортную инфраструктуру городов.
    Кроме того, решение перекликается с идеей создать САПР велопешеходной транспортной инфраструктуры, одноимённый проект зарегистрирован на платформе "Университет 2035".


    1. b_vova Автор
      12.10.2026 20:15

      Интересно, я открыт к любым идеям и предложениям.


  1. otchgol
    12.10.2026 20:15

    Забавный симулятор. Выбор atmega и симуляция arduino кажется мне сомнительным. Целевая аудитория симулятора и цели не очень ясны. Я вижу питор в качестве движка и полную абстракцию от железа. Отдельной частью высокооуровневый командный протокол железа на исполнительные. Питон для 12-16 проще и железо с большим количеством ног можно получить. Но это мое видение. Тут нет аттачей хотел показать картинкой, но не так важно.


    1. b_vova Автор
      12.10.2026 20:15

      Спасибо, Arduino и ESP32 сильно развязывает руки по железу. Стоит копейки, создавай любые проекты в симуляторе и переноси код на реальные прототипы. Про Питон подумаю, но это отдельная разработка симулятора под Raspberry Pi Pico (или Pico W с Wi-Fi).

      UPD. Питон для образовательных целей нужен как воздух, проект в доработке.


      1. otchgol
        12.10.2026 20:15

        Да я пико и имел в виду. Больше выходов гораздо проще esp и среда разработки комфортнее. Сколько у вас ребятам лет, что они c++ могут понять для симулятора и мк? Я не могу в 12 получить устойчивое понимание питона как шаг с лего. Я так вижу https://habr.com/ru/articles/1093622/


        1. b_vova Автор
          12.10.2026 20:15

          Спасибо за ссылку, интересно, почитаю.


    1. 00Kirill00
      12.10.2026 20:15

      Если убрать эмуляцию микроконтроллера, получится обычная аркадная игра на JavaScript, коих в сети миллионы


      1. b_vova Автор
        12.10.2026 20:15

        Это не просто JavaScript, тут используется физический движок Rapier 3D.

        Полноценная 3D-физика: Вместо простых алгоритмов проверки пересечения прямоугольников (AABB) или окружностей, здесь задействованы сложные математические расчеты: симуляция гравитации, трения, упругости, массы, импульсов и честных столкновений трехмерных объектов произвольной формы.


  1. ShIV03
    12.10.2026 20:15

    1. Действительно, Круто! (особенно, когда заработает регистрация - можно будет форкать и редактировать). Спасибо! (однозначно "прирос" - похожу по плиткам в разделах)

    Автор "упустил" отметить в статье: Имеется поддержка (и примеры) Умного дома (по MQTT - на платном тарифе) и Wi-Fi (но, если не путаю, только "внутри" эмулируемого микроконтроллера)

    2. Мысли:
    - (базовая) Предусмотрели ли "прикручивать" (расширять);
    - (мрачно) "Где AI?";
    - (в удивлении, приподняты брови) Где "Создать"? (пожалуйста, добавьте такой пунктик, чтобы даже не входя, могли попробовать."порисовать". Пусть и без "Сохранения". Вы и так - позволяете "(собирать и) Запускать схему" - что грузит только браузер пользователя, так дайте и "рисовать свое");
    - (хочу) и эмуляцию самих (Home Assistant, Zigbee-сети), Ethernet и IP. Упс, и "заодно потянуло" BT, Wi-Fi;. Внешние эмуляторы. Намек: MCP
    - (мечтаю) соединить с реальным миром (с Ethernet, ...). Для того же MCP.

    PS: не нашел раздела "Документация".


    1. b_vova Автор
      12.10.2026 20:15

      Спасибо за обратную связь! Это ценно для развития проекта.

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

      2) По второму пункту

      • "прикручивать" (расширять): я об этом думаю, но направлений слишком много, боюсь все не сделать. Развивать проект будем этапами. В какую сторону нужно расширение?

      • AI в проекте нет, в смысле скетч не написать через AI, а надо? В каком виде?

      • С открытой регистрацией будет "Создать", чуть подождать надо.

      • Wifi эмулируется, смотрите проекты с бибиотекой Settings от Гайвера. Есть немного проектов и с MQTT

      • Связь с внешним миром может быть очень опасна в текущих реалиях.


      1. ShIV03
        12.10.2026 20:15

        1. Если правильно понял (архитектуру: на сервере - скетч собирается, а работа) "Всё (эмулируется) в веб-браузере".

        К тому, что вам - "не жалко" (серверных ресурсов), а только понимаете "опасно" - чем резко позиционируете "Для школ".

        Но судя по тарифам - и для разработчиов и enterprise.
        Позвольте им самим решать - предоставьте "расширение".

        Понимаю, что из ванильной эмуляции "вывести" что-то тяжело.
        Потому и спросил "Предусмотрели ли?" ("уже есть", или "будет").

        2. Про "Где AI?" -
        1) я показывал свою утомленность от статей по AI (и AI-ассистенты).
        Но не сказать ни слова - это, или у Автора "бронебойный лоб", или "вышел из длительного запоя" (отстал);
        2) если реализовать подключение по реальному IP, можно будет резко поднять интерес со стороны публики (надеюсь, что на сборке - серверы не просядут):
        - вам - "Воронка продаж";
        - нам - (при чтении статьи посетила идея) "Микроконтроллеры и AI" ("Галантерейщик!, и кардинал"). Т.е. PinPort - "мостик" ("за 200р/мес" - легко).
        3) Вот и предложил "Выход через TCP/IP на внешние устройства" (реальные и эмуляторы). Сразу же просится и "Вход".

        Понимаю, что симулятор "ворочается" медленно - не везде (не во всех применениях) будет работать.
        - поэтому первой мыслью было только - Гибкое расширение (внешними, самодельными симуляторами. Например, на MCP-протоколе);
        - но следом поразила Возможность "подцепиться" к реальной сети -- Открытый мир!

        Идея (существенного) Упрощения (разработки и) отладки МК-устройств с IP-связью с AI (как "AI->МК", так и "МК->AI") - Очень богатая!

        PS: >С открытой регистрацией будет "Создать", чуть подождать надо.

        Сам нашел возможность "редактирования" (без входа):
        (раздел)Уроки\(справа)Начать: первое мигание -->
        https://pinport.ru/learn/blink
        - а значит и типа "Создать" (поудалив "лишние" детали).

        Т.е. Уроки позволяют редактировать - "ясень пень!" (как только сразу не сообразил)


        1. b_vova Автор
          12.10.2026 20:15

          Спасибо за подробный разбор!

          Да, всё так: на сервере только сборка, эмуляция в вашем браузере. Расширение отчасти есть уже сейчас: прогон прошивки можно запросить по HTTP и получить отчёт о выводах и порте, так что MCP-сервер или AI-агент может гонять проекты сам. Если честно, для этого уже есть свой API.

          Свои модели устройств подключать пока нельзя, это в планах.

          Про выход в реальную сеть: опасно, если прокси - наш сервер. Идею записал.

          Про AI иронию оценил :) Без AI не существовало бы вашего коммента т.к. не существовало бы этого проекта.

          PS. Редактор в уроках без входа, спасибо, верно подмечено.


  1. 00Kirill00
    12.10.2026 20:15

    Пешеходы, которые вежливо уступают дорогу через 0,6 секунды, явно живут в утопическом городе мечты..