
Mirte — это недорогая полностью open-source платформа учебного мобильного робота, где ученик проходит путь «от телеуправления и Blockly до Python, SSH и полноценного ROS», задуманная как единый «трек» обучения от начальной школы до университета, оставаясь на одном и том же роботе и в одной и той же среде. Идея Mirte в образовании — не прятать “настоящую” робототехнику за игрушечными абстракциями, а сделать к ней удобный, поэтапный вход.
Представьте урок, на котором школьник за 5 минут впервые в жизни запускает робота с ноутбука: сначала — обычным телеуправлением в браузере, затем — собирает программу из блоков, заглядывает «под капот» в сгенерированный Python, а через пару недель уже заходит по SSH, открывает VS Code на самом роботе, запускает Jupyter Notebook и пишет собственную ROS‑ноду.
И всё это — с одним и тем же роботом, на одной и той же платформе. Это и есть Mirte.
Зачем Mirte вообще появился
Создатели Mirte сформулировали задачу очень жёстко: образовательный робот должен быть одновременно дешёвым, полностью open‑source, без массы кастомных деталей и пригодным от начальной школы до университета.

Большинство наборов решают только один фрагмент картины:
либо это игрушка для начальной школы с закрытой прошивкой,
либо серьёзный набор для вуза, куда школьника просто не пустишь,
либо «конструктор по программированию», где нет реальной механики и электроники.

Mirte решает всё разом:
одно семейство роботов (Basic/Light/Pioneer/Master) — разный «уровень возможностей» под возраст и задачи;
одна линейка софта — от браузерного Blockly до ROS;
единая философия Open Education / Open Science: все механические файлы, схемы, код, учебные материалы открыты и развиваются сообществом.
Это не просто «ещё один робот», это тре́к обучения инженерии, который можно растянуть на годы.
Как устроена лестница Mirte: от teleop и Blockly до ROS
Основная педагогическая идея Mirte: несколько слоёв сложности в одной среде, чтобы каждый ученик входил туда, где ему комфортно, и мог шаг за шагом подниматься выше. В документации это сформулировано прямо: цель Mirte — «чтобы все могли учиться робототехнике», поэтому доступны несколько уровней сложности программирования.
1. Первый контакт: веб‑интерфейс и телеуправление
Учитель включает робота. Mirte поднимает Wi‑Fi и web‑интерфейс; ученику достаточно открыть браузер и перейти по адресу Mirte (обычно вида http://mirte.local).
Что видит ученик:
панель управления роботом,
блоки Blockly,
и (чуть ниже) генерируемый Python‑код.
Первый сценарий — телеуправление (teleop): робот ездит по командам с клавиатуры/кнопок в интерфейсе. Для ученика это просто «робот поехал». На самом деле под капотом уже работает ROS: есть нода, публикующая команды движения (Twist) в топик cmd_vel, а драйвер привода превращает это в скорости колёс.

2. Blockly: визуальное программирование как мост, а не тупик
Следующая ступень — Blockly. В документации прямо сказано: «Самый простой способ программировать Mirte — использовать Blockly».
Ученик перетаскивает блоки:
начать программу;
двигаться вперёд N секунд;
если сработал датчик — повернуть;
повторять в цикле и т.п.
Сверху — «контрольная панель»: запустить, поставить на паузу, выполнить пошагово, остановить.
Важно, что при остановке программы Mirte автоматически выключает моторы — встроенная педагогическая «страховка».
Главное — это не игрушечный блок‑редактор:
под полотном Blockly виден Python‑код, сгенерированный по этим блокам;
этот код можно отредактировать и запустить теми же кнопками, что и блоки.
То есть Blockly в Mirte — не отдельный мир, а зеркало текстового кода. В материалах по Mirte прямо описано: «Блоки можно открыть, чтобы увидеть Python‑код ниже, который построен поверх ROS».

3. Python в браузере: первый шаг в «настоящем» коде
Когда ученик «наигрался» с блоками, учитель показывает следующую магию:
«Видишь этот Python под блоками? Давай уберём блоки и будем писать прямо здесь».
Документация Mirte описывает два способа программировать на Python:
Из веб‑интерфейса — редактируя код, сгенерированный Blockly, и управляя его запуском той же панелью.
Через Python API + ROS — когда Mirte становится частью ROS‑сети, а код подписывается, например, на cmd_vel и управляет моторами через вызовы API.
Пример из документации: Python‑скрипт, который слушает сообщения Twist и по ним задаёт скорости моторам через mirte_robot API — без дополнительной ROS‑инициализации, встроенной в robot.createRobot().

4. SSH: вход во «взрослый» Linux мира робототехники
Дальше ученику (или одному‑двум мотивированным в группе) дают следующий инструмент — терминал.
Mirte официально поддерживает подключение по SSH, о чём прямо сказано в документации Accessing the interface:
два интерфейса: web и Linux‑терминал через SSH;
web даёт Blockly и Python, SSH — Python и ROS.
Команды становятся инженерными:
ssh mirte@mirte.local (первый логин с паролем по умолчанию);
просмотр каталогов, mirte_ws с ROS‑workspace;
управление сервисами:
sudo service mirte-ros stop/start — перезапуск bringup робота;
sudo service mirte-jupyter start — запуск Jupyter (по умолчанию он выключен, чтобы не съедать RAM).
чтение логов через journalctl -u mirte-ros -f, если что‑то пошло не так.
Это момент, когда ученик впервые чувствует: «я не просто клацаю кнопки, я администрирую настоящего робота».

5. VS Code и Jupyter на самом роботе
Для комфортной разработки Mirte предлагает «IDE на роботе»:
на роботе запускается VS Code / code-server, к которому заходят через браузер;
Jupyter Notebook работает как отдельный сервис, по адресу вроде http://mirte.local:8888, с примерами на базе Jupyter‑ROS.
Практически это выглядит так: ученик открывает в браузере VS Code, но весь workspace — на самом роботе. Не нужно настраивать Python, ROS, расширения на каждом ученическом ноутбуке — инфраструктура уже внутри робота Mirte.

6. ROS: Mirte как часть настоящей экосистемы
На верхнем уровне Mirte — полноценный участник ROS/ROS2‑мира. Документация описывает:
системные сервисы, поднимающие ROS ноды(программы) при старте;
ROS‑workspace ~/mirte_ws, где можно создавать свои пакеты и ноды;
Python API, который можно комбинировать с ROS‑сообщениями и сервисами;
В исследованиях TU Delft подчёркивается, что MIRTE Pioneer массово используется в бакалаврских курсах, где более 300 студентов в год строят и программируют этих роботов, а архитектура специально сделана модульной и открытой для расширения.

Mirte раскрывает ROS‑архитектуру: ученики могут увидеть, как их код взаимодействует с другими ROS нодами.
Как выглядит учебный процесс глазами ученика
Первый урок: «робот оживает»
Ученик достаёт Mirte, включается WIFI точку доступа / подключается к сети, открывает браузер. Робот появляется как web‑страница. Никаких установок SDK, драйверов, несовместимых версий.
Он нажимает на кнопки управления — робот ездит, поворачивает, реагирует на команды. Через пару минут преподаватель показывает вкладку Blockly:
«Смотри, давай теперь не вручную, а программой заставим его проехать квадратом».
Ученик собирает простую программу: вперёд — повернуть — вперёд — повернуть… Нажимает Run — робот крутит квадрат вокруг стола.
Вторая ступень: «из блоков — в код»
Учитель нажимает «показать код под блоками». На экране появляется Python.
— «Это то же самое, что ты сделал блоками. Попробуем заменить число 2 на 4, чтобы он дольше ехал».
Ученик меняет константу прямо в коде, снова запускает — видит результат.
Постепенно он начинает двигать логику из блоков в текст: сначала меняет параметры, потом добавляет новое условие, потом вообще убирает часть блоков и дописывает Python код руками.
Третья ступень: «я админ своего робота»
Через несколько занятий учитель показывает SSH:
как подключиться;
как зайти в папку с рабочим пространством;
как запустить/остановить сервисы;
как прочитать лог, если робот не реагирует.
Ученик, который ещё вчера перетаскивал блоки, сегодня пишет catkin_create_pkg, редактирует CMakeLists.txt и запускает rosrun.
Четвёртая ступень: проект
К концу модуля у него может быть вполне взрослый проект:
ROS нода, которая читает данные ЛИДАРа или ультразвуковых датчиков;
алгоритм, который решает — ехать вперёд или объехать препятствие;
программирование в Jupyter Notebook, графики в ноутбуке, настройка PID, анализ поведения.
И всё это — на том же Mirte, который он впервые включил через браузер.
Выгода для ученика
1. Понятная траектория роста
Mirte снял одно из главных противоречий школьной робототехники: либо слишком легко и скучно, либо слишком сложно и «для олимпиадников».
Здесь есть непрерывная лестница:
Teleop → Blockly быстрый успех, мгновенный «вау‑эффект»;
Blockly → Python в браузере: переход от визуального мышления к текстовому коду, но в знакомой среде;
Python → SSH/VS Code/Jupyter: освоение инструментов инженерной работы;
SSH/IDE → ROS‑архитектура: понимание профессиональной экосистемы, с которой работают реальные инженеры.
Ученик не «перескакивает» с платформы на платформу — он расширяет горизонт на одной и той же базе до профессионального востребованного робототехника.
2. Реальные, переносимые навыки
Mirte учит не только программированию. Он учит инженерному способу думать:
Linux, терминал, SSH, сервисы— базовые навыки DevOps/робототехники;
работа с ROS: топики, ноды, пакеты, конфигурация, отладка — фундамент ROS‑разработчика;
Исследования по Mirte в инженерном образовании подчёркивают именно это: робот задуман так, чтобы будущее инженерное обучение было непрерывным и практико‑ориентированным, а не набором разрозненных лабораторных работ.
3. Мотивация через прозрачность и «взрослость»
Поскольку Mirte полностью открыт, ученик всегда может пойти глубже:
открыть файлы робота и увидеть, что именно запускается при старте;
заглянуть в схему/PCB и понять, куда идут провода;
скачать исходники web‑интерфейса и модифицировать его под себя.
Это даёт очень сильное чувство «я вхожу в реальный мир технологий, а не играю в укороченную версию».
Выгода для учителя
1. Один робот — весь спектр образования
В университетских материалах TU Delft прямо говорится: MIRTE Pioneer используется в бакалавриате массово (более 300 роботов в год), а Light/Basic — в школе и колледже.
Практически это означает:
школе или вузу не нужно закупать разные наборы под каждый курс;
преподаватель может строить длинный сквозной курс (или несколько лестниц сложности) на одной платформе;
переход учащегося из школы в вуз не ломает всё: Mirte остаётся знакомой базой, меняется глубина задач.
2. Гибкость под разный уровень группы
В одном классе всегда есть «быстрые» и «медленные» ученики. Mirte позволяет работать с этим не через «занижение планки», а через разный уровень доступа:
новичкам достаточно браузера и Blockly — они спокойно осваивают базовые идеи алгоритмов;
уверенные быстро переходят в Python (но всё ещё в веб‑интерфейсе, без сложной установки IDE и ROS);
мотивированные получают SSH, VS Code, ROS — и превращают лабораторные работы в мини‑проекты.
Таким образом, учитель может дать общее задание («робот должен проехать маршрут с обходом препятствий»), а уровень реализации — адаптировать под ученика: от «если расстояние < X — поверни» на Blockly до собственной ROS‑ноды с логированием и настройкой параметров.
3. Снижение операционной боли
Типичные проблемы робототехники в образовании:
«у меня не ставится драйвер»,
«эта версия Python конфликтует с ROS»,
«на Windows всё иначе»,
«у нас 20 ноутбуков, и на каждом всё по‑разному»,
«не получается установить linux и ROS»,
Mirte снимает это за счёт того, что вся сложность живёт на роботе:
доступ через браузер, без установки софта на ученических ПК;
одна и та же среда для всех — учителю не нужно разруливать зоопарк конфигураций;
обновления можно проводить централизованно, а не по машинам.
4. Сообщество и открытые материалы
Mirte разворачивается как проект открытого образования и открытой науки:
партнёры (TU Delft, University of Groningen, прикладные вузы) используют Mirte в своих курсах и публикуют материалы открыто;
университеты в других странах берут дизайн и строят собственные роботы, адаптируя их под свои программы.
Полностью открытый исходный код, список компонентов для покупки, инструкции по сборке, документация.
Для учителя это означает: он не один. Можно брать готовые сценарии, уроки, лабораторные, адаптировать и возвращать в общее поле.
Почему это действительно инновация (и почему «всех нужно учить так»)
Mirte соединяет сразу несколько тенденций современного образования в инженерии:
Открытая наука и open‑source.
Mirte — полностью открытый: от железа до кода и учебных материалов. Это означает, что:
образовательные учреждения не зависят от жизненного цикла коммерческого набора («сняли с производства» — и всё пропало);
студенты и пр��подаватели становятся со‑разработчиками, а не просто потребителями.
2. Сквозная инженерная подготовка.
Мир робототехники в жизни — это не отдельная дисциплина, а узел механики, электроники, программирования, сетей, UX и исследования. Mirte целенаправленно сделан как платформа, где можно учить всё это по спирали: сначала очень просто, потом всё сложнее, но на тех же объектах.
3. Фокус на реальных компетенциях.
Исследования по инженерной педагогике подчёркивают: наиболее эффективны те методики, где студенты делают «настоящие вещи» с понятной им связью с реальным миром. Mirte как раз об этом — это не симуляция, а реальный робот, который ведёт себя как система.
4. Сопряжение с индустрией.
ROS/ROS2 — де‑факто стандарт в академии и индустрии робототехники. Mirte с самого начала встроен в эту экосистему, а не в закрытую “игровую” среду. Значит, студенту потом проще войти в любые реальные проекты — от мобильных роботов до манипуляторов.
5. Масштабируемость и устойчивость.
Благодаря открытому дизайну, Mirte можно:
производить локально;
удешевлять и адаптировать под местные учебные планы;
объединять усилия разных университетов, школ, кружков.
Именно поэтому, когда разработчики Mirte говорят о «семействе открытых образовательных роботов», это не маркетинг. Это попытка построить общий стандарт инженерного образования через роботов, в котором любой учитель и ученик могут стать участниками, а не клиентами.
Выводы
Так как все выложено в open-source то проект может служить отправной точкой для переиспользования различных технологий, наработок и идей. Чтобы погрузиться лучше начать с просмотра видео доклада рассказанного на образовательном блоке конференции ROSCON в Великобритании. Сайт проекта. Документация.
Обсудить статью можно в ROS чате.
Народный курс по ROS2 на степике.
Как понять, что образовательный подход и образовательный робот приносит пользу? Главный критерий готовит ли он кадры с необходимыми знаниями и опытом для бизнеса и государства, именно поэтому были разработаны ROS2 соревнования которые пройдут на ROS meetup 21-22 марта 2026 года. Задача соревнований максимально приближена к той которую решает мобильная манипуляция в сервисной и промышленной робототехнике. Победители соревнования могут претендовать на вавакансии в ведущих робототехнических компаниях. О этих соревнованиях вы можете прочитать подробную статью на Хабре.
Четыре уровня программирования Mirte: от PWM к архитектуре
Введение: одна задача, разные инструменты
Представьте простую задачу: робот должен проехать вперёд на 1 метр и остановиться.
На первый взгляд, это простое требование. Но на Mirte можно написать этот код четырьмя принципиально разными способами — от управления отдельными пинами микроконтроллера до полноценной ROS архитектуры. И каждый способ открывает новый уровень понимания того, как на самом деле работает робот.
Это не просто "разные способы написать то же самое". Это четыре разных парадигмы мышления инженера. И именно поэтому в образовательном процессе нужно учить все четыре подхода.
Уровень 1: управление пинами PWM (быстрый результат)
Код
import time from mirte_robot import robot def level_1_move_forward_pwm(): """ Уровень 1: управляем пинами микроконтроллера напрямую через PWM. PWM (Pulse Width Modulation) - быстрое переключение напряжения для управления мощностью мотора. """ mirte = robot.createRobot() print("=" * 70) print("УРОВЕНЬ 1: Управление пинами PWM (низкоуровневый подход)") print("=" * 70) # На Mirte моторы подключены к GPIO пинам left_motor_pin = 'GP19' right_motor_pin = 'GP18' # Задаём PWM значение (0-255, где 255 = 100% мощности) pwm_power = 150 # примерно 60% мощности print(f"\n1. Устанавливаем оба мотора на PWM = {pwm_power} (60% мощности)") mirte.setAnalogPinValue(left_motor_pin, pwm_power) mirte.setAnalogPinValue(right_motor_pin, pwm_power) print("2. Гадаем, сколько времени нужно для проезда 1 метра...") print(" (зависит от батареи, веса, состояния пола...)") time.sleep(5) # ждём 5 секунд print("3. Останавливаем моторы") mirte.setAnalogPinValue(left_motor_pin, 0) mirte.setAnalogPinValue(right_motor_pin, 0) print("\n" + "!" * 70) print("РЕЗУЛЬТАТ: Робот вероятно проехал примерно 1 метр, но мы НЕ ЗНАЕМ ТОЧНО!") print("!" * 70) print("\nПРОБЛЕМЫ этого подхода:") print(" ❌ Точность: ± 50 см (сильно зависит от условий)") print(" ❌ Нет обратной связи - не знаем, где робот на самом деле") print(" ❌ Если один мотор сильнее - робот едит КРИВО") print(" ❌ Если батарея разрядилась - робот едит медленнее") print(" ❌ Мы просто ГАДАЕМ на основе времени") if __name__ == '__main__': level_1_move_forward_pwm()
Что происходит под капотом
Python: mirte.setAnalogPinValue('GP19', 150) ↓ ROS API преобразует в сервис-вызов ↓ Telemetrix протокол отправляет по USB ↓ RP2040 микроконтроллер (Pico) получает команду ↓ Pico устанавливает GPIO19 в режим PWM ↓ PWM 150/255 ≈ 59% → мотор вращается на 59% мощности
Плюсы этого уровня
✅ Максимально быстрый результат — робот реагирует мгновенно
✅ Очень простой код — всего 3-4 строки для движения
✅ Видна прямая причинно-следственная связь — код → поведение робота
✅ Ученик видит физику — как работают электроника и моторы
Минусы этого уровня
❌ Нет обратной связи
❌ Неточно (гадание по времени)
❌ Не масштабируется (добавить датчик = переписать код)
❌ Работает только для Mirte
Когда его использовать
🎓 Возраст 8-10 лет — первые уроки программирования и робототехники
🎓 Когда нужен быстрый результат — ученик должен увидеть, что его код работает
🎓 Для понимания базовой физики — как работает электроника
Ключевой вопрос ученика на этом уровне:
"Почему робот не ездит прямо? Почему один раз проехал 1 метр, а другой раз 0.8 метра?"
Этот вопрос ведёт к следующему уровню.
Уровень 2: управление скоростью через PID (инженерный контроль)
Код
import time from mirte_robot import robot def level_2_move_forward_with_pid(): """ Уровень 2: управляем СКОРОСТЬЮ моторов, не PWM. За кулисами работает PID контроллер: 1. Читает энкодеры (датчики вращения колёс) 2. Вычисляет текущую скорость каждого мотора 3. Сравнивает с желаемой скоростью 4. Автоматически корректирует PWM для синхронизации Результат: оба мотора крутятся СИНХРОННО, робот ездит РОВНО. """ mirte = robot.createRobot() print("=" * 70) print("УРОВЕНЬ 2: Управление скоростью моторов (PID контроллер)") print("=" * 70) # Задаём одинаковую скорость обоим моторам speed_value = 100 # условные единицы (0-255) print(f"\n1. Устанавливаем скорость = {speed_value}") print(" Что происходит под капотом:") print(" → PID контроллер КАЖДЫЕ 100мс читает энкодеры") print(" → Сравнивает скорость левого и правого мотора") print(" → Если левый медленнее - увеличивает его PWM") print(" → Если правый медленнее - увеличивает его PWM") print(" → В результате оба мотора синхронизируются") mirte.setSpeed('left', speed_value) mirte.setSpeed('right', speed_value) print(f"\n2. Едим 5 секунд (с автоматической синхронизацией)...") time.sleep(5) print("3. Останавливаем") mirte.setSpeed('left', 0) mirte.setSpeed('right', 0) print("\n" + "+" * 70) print("РЕЗУЛЬТАТ: Робот ездит РОВНО (не криво)!") print("+" * 70) print("\nЧТО УЛУЧШИЛОСЬ по сравнению с уровнем 1:") print(" ✅ Робот ездит прямо (оба мотора синхронизированы)") print(" ✅ Предсказуемое поведение") print(" ✅ Даже если один мотор немного слабее - система скомпенсирует") print("\nЧТО ВСЕ ЕЩЁ НЕ РЕШЕНО:") print(" ❌ Точность всё ещё примерно ± 20 см") print(" ❌ Мы НЕ ЗНАЕМ, где робот на самом деле") print(" ❌ Если батарея разрядилась - робот будет медленнее, но скорость 100 останется 100") print(" ❌ Мы всё ещё гадаем по времени: 'ехать 5 секунд' - это как далеко?") def level_2_smooth_acceleration(): """ Дополнительный пример: плавный разгон через PID. PID контроллер делает разгон мягким и предсказуемым, а не рывком. """ mirte = robot.createRobot() print("\n" + "=" * 70) print("УРОВЕНЬ 2: Плавный разгон с PID") print("=" * 70) max_speed = 150 print("\nФаза 1: Разгон от 0% до 100% мощности") for speed in range(0, max_speed, 15): progress = (speed / max_speed) * 100 print(f" → Скорость {speed:3d} ({progress:5.1f}%)", end='\r') mirte.setSpeed('left', speed) mirte.setSpeed('right', speed) time.sleep(0.1) print(f"\nФаза 2: Едим с максимальной скоростью...") mirte.setSpeed('left', max_speed) mirte.setSpeed('right', max_speed) time.sleep(2) print("Фаза 3: Плавное торможение от 100% до 0%") for speed in range(max_speed, 0, -15): progress = (speed / max_speed) * 100 print(f" → Скорость {speed:3d} ({progress:5.1f}%)", end='\r') mirte.setSpeed('left', speed) mirte.setSpeed('right', speed) time.sleep(0.1) mirte.setSpeed('left', 0) mirte.setSpeed('right', 0) print("\n✓ Разгон/торможение завершены") if __name__ == '__main__': level_2_move_forward_with_pid() time.sleep(1) level_2_smooth_acceleration()
Архитектура: как PID контроллер работает
mirte.setSpeed('left', 100) ↓ Mirte OS: КАЖДЫЕ 100 мс ↓ ┌─────────────────────────────────┐ │ 1. Читаем энкодеры │ │ current_speed_left = 95 │ │ current_speed_right = 100 │ └─────────────────────────────────┘ ↓ ┌─────────────────────────────────┐ │ 2. Вычисляем ошибку │ │ error_left = 100 - 95 = 5 │ └─────────────────────────────────┘ ↓ ┌─────────────────────────────────┐ │ 3. PID алгоритм │ │ correction = P*5 + I*∫5 + D*5'│ └─────────────────────────────────┘ ↓ ┌─────────────────────────────────┐ │ 4. Корректируем PWM │ │ new_pwm_left = 150 + 1 = 151 │ │ new_pwm_right = 150 (как было) └─────────────────────────────────┘ ↓ Оба мотора крутятся синхронно ✓
Плюсы этого уровня
✅ Ученик видит PID контроллер — один из самых важных инструментов в инженерии
✅ Введение в концепцию обратной связи — система сама себя корректирует
✅ Робот ездит прямо — ровное, предсказуемое движение
✅ Всё ещё просто — 2 строки кода, но под ними скрывается серьёзная инженерия
Минусы этого уровня
❌ Точность всё ещё ± 20 см
❌ Не знаем точно, где робот находится
❌ Управление по времени, а не по расстоянию
Когда его использовать
🎓 Возраст 10-12 лет — когда ученик спрашивает "почему криво?"
🎓 Для первых проектов с движением — робот должен ездить прямо
🎓 Для понимания инженерных решений — как инженеры решают проблемы
Ключевой вопрос ученика на этом уровне:
"Отлично, робот ездит ровно. Но как я узнаю, что он проехал ровно 1 метр? Как мне рассчитать время? Что если батарея разрядилась?"
Этот вопрос ведёт к следующему уровню.
Уровень 3: высокоуровневые функции (простая ROS абстракция)
Код
from mirte_robot import robot import time def level_3_move_forward_high_level(): """ Уровень 3: используем высокоуровневые функции Mirte. Вместо управления пинами или даже скоростями, мы просто говорим: "проехать вперёд на 1 метр" - и система сама разбирается, как это сделать. За кулисами: 1. Функция публикует Twist сообщение (ROS интерфейс скорости) 2. Робот считает пройденное расстояние через одометрию 3. Робот автоматически останавливается, когда достиг цели Это ИНТЕЛЛЕКТУАЛЬНОЕ управление! """ mirte = robot.createRobot() print("=" * 70) print("УРОВЕНЬ 3: Высокоуровневые функции Mirte") print("=" * 70) # Самый простой способ: просто вызвать функцию! print("\n1. Вызываем: mirte.move_forward(duration=1.0, speed=50)") print(" (робот ездит 1 секунду со скоростью 50)") mirte.move_forward(duration=1.0, speed=50) print("\n2. Робот двигается с автоматическим контролем расстояния") print(" Под капотом происходит:") print(" → Публикуется Twist сообщение с нужной скоростью") print(" → PID контроллер синхронизирует моторы") print(" → Энкодеры считают расстояние") print(" → Одометрия обновляет позицию робота (X, Y, угол)") print(" → Функция move_forward() читает одометрию") print(" → Когда пройденное расстояние >= нужного - функция останавливает робота") print("\n" + "+" * 70) print("РЕЗУЛЬТАТ: Робот проехал примерно нужное расстояние!") print("+" * 70) print("\nЧТО УЛУЧШИЛОСЬ:") print(" ✅ Точность: ± 5 см (реальная обратная связь от одометрии!)") print(" ✅ Простой интерфейс - одна функция вместо 10 строк кода") print(" ✅ Робот сам знает, когда остановиться") print(" ✅ Введение в ROS парадигму (топики, одометрия)") print("\nЧТО СКРЫТО ПОД КАПОТОМ:") print(" → Стандартная ROS архитектура") print(" → Одометрия (позиция робота)") print(" → Управление через Twist топик") def level_3_turn_example(): """ Пример: повернуться на 90 градусов. """ mirte = robot.createRobot() print("\n" + "=" * 70) print("УРОВЕНЬ 3: Пример - повернуться на месте") print("=" * 70) print("\nВызываем: mirte.turn_right(angle=90)") mirte.turn_right(angle=90) print("✓ Робот повернулся на 90 градусов (с точностью ± 5 градусов)") def level_3_complex_example(): """ Пример посложнее: нарисовать квадрат через высокоуровневые функции. """ mirte = robot.createRobot() print("\n" + "=" * 70) print("УРОВЕНЬ 3: Проект - нарисовать квадрат") print("=" * 70) print("\nПроект: нарисовать квадрат 1x1 метр") print("\nКод:") print(" for i in range(4):") print(" mirte.move_forward(distance=1.0, speed=0.2)") print(" mirte.turn_right(angle=90)") for i in range(4): print(f"\nСторона {i+1}: едим 1 метр вперёд") mirte.move_forward(distance=1.0, speed=0.2) if i < 3: print(f"Поворот {i+1}: вращаемся на 90 градусов") mirte.turn_right(angle=90) print(f"\n✓ Квадрат готов!") if __name__ == '__main__': level_3_move_forward_high_level() time.sleep(0.5) level_3_turn_example() # level_3_complex_example() # раскомментируй, чтобы нарисовать квадрат
Интерфейс Mirte уровня 3
# Основные высокоуровневые функции: mirte.move_forward(distance=1.0, speed=0.2) # → Проехать 1 метр вперёд со скоростью 0.2 м/с mirte.move_backward(distance=1.0, speed=0.2) # → Проехать 1 метр назад mirte.turn_right(angle=90) # → Повернуться на 90 градусов вправо mirte.turn_left(angle=90) # → Повернуться на 90 градусов влево x, y, theta = mirte.get_odometry() # → Получить текущую позицию и ориентацию робота
Плюсы этого уровня
✅ Точность ± 5 см — реальная обратная связь от одометрии
✅ Простой API — одна функция вместо множества строк кода
✅ Введение в ROS архитектуру — под капотом работает стандартная ROS парадигма
✅ Переносимый код — похожие функции есть на других ROS роботах
✅ Видна интеграция системы — команды → датчики → решения
Минусы этого уровня
❌ Скрыта сложность — ученик не видит, что происходит под капотом
❌ Сложнее отлаживать — если что-то не работает, нужно лезть в ROS
❌ Нельзя реализовать сложную логику — функции ограничены
Когда его использовать
🎓 Возраст 12-14 лет — когда нужна точность и простота
🎓 Для проектов, требующих точности — навигация, рисование фигур
🎓 Для введения в ROS без "шока сложности" — ученик видит результат, а не архитектуру
🎓 Когда нужна масштабируемость — добавляем датчики, логика работает
Ключевой вопрос ученика на этом уровне:
"Эти функции хорошо работают, но что если мне нужна более сложная логика? Что если робот должен принимать решение на основе датчика расстояния? Как я это напишу?"
Этот вопрос ведёт к следующему, финальному уровню.
Уровень 4: полноценная ROS нода (профессиональная архитектура)
Код
#!/usr/bin/env python3 """ Уровень 4: Полноценная ROS нода. Это уже ПРОФЕССИОНАЛЬНЫЙ подход к разработке на робототехнике. Вместо использования готовых функций, мы: 1. Подписываемся на ROS топики (одометрия, датчики) 2. Публикуем команды (скорость) 3. Реализуем нашу собственную логику управления Это позволяет создавать произвольно сложные системы управления. """ import rospy from geometry_msgs.msg import Twist from nav_msgs.msg import Odometry from sensor_msgs.msg import Range from tf_transformations import euler_from_quaternion import math class MirteNavigationNode: """ ROS нода для управления Mirte. Подписывается на топики, публикует команды, реализует логику. """ def __init__(self): # Инициализируем ROS узел rospy.init_node('mirte_navigation_node', anonymous=False) # Издатель для команд скорости self.cmd_vel_pub = rospy.Publisher( '/cmd_vel', Twist, queue_size=10 ) # Подписчик на одометрию self.odom_sub = rospy.Subscriber( '/odom', Odometry, self.on_odometry_received ) # Подписчик на датчик расстояния (если есть) self.distance_sub = rospy.Subscriber( '/mirte/distance_sensor', Range, self.on_distance_received ) # Переменные состояния self.current_x = 0.0 self.current_y = 0.0 self.current_yaw = 0.0 self.distance_to_obstacle = float('inf') rospy.loginfo("MirteNavigationNode инициализирована") def on_odometry_received(self, msg): """ Callback: вызывается когда приходит новое сообщение одометрии. Одометрия - это информация о позиции робота: - X, Y: координаты в глобальной системе - Yaw: ориентация (угол) """ self.current_x = msg.pose.pose.position.x self.current_y = msg.pose.pose.position.y q = msg.pose.pose.orientation (_, _, self.current_yaw) = euler_from_quaternion( [q.x, q.y, q.z, q.w] ) def on_distance_received(self, msg): """ Callback: вызывается когда приходит данные с датчика расстояния. Это может быть ультразвуковой датчик, LIDAR и т.д. """ self.distance_to_obstacle = msg.range def publish_velocity(self, linear_x, angular_z): """ Публикует команду скорости в ROS. linear_x: скорость вперёд (м/с) angular_z: угловая скорость (рад/с) """ twist = Twist() twist.linear.x = linear_x twist.angular.z = angular_z self.cmd_vel_pub.publish(twist) def move_forward_with_obstacle_avoidance(self, target_distance): """ Проехать вперёд, но если впереди препятствие - остановиться. Это пример того, как на уровне ROS ноды можно реализовать сложную логику, объединяя информацию из нескольких датчиков. """ start_x = self.current_x start_y = self.current_y rospy.loginfo(f"Едим вперёд на {target_distance} м (с проверкой препятствий)") rate = rospy.Rate(10) # 10 Hz while not rospy.is_shutdown(): # Вычисляем пройденное расстояние distance_traveled = math.sqrt( (self.current_x - start_x)**2 + (self.current_y - start_y)**2 ) # Проверяем препятствия if self.distance_to_obstacle < 0.2: # менее 20 см впереди rospy.logwarn("⚠️ Препятствие впереди! Останавливаемся!") self.publish_velocity(0.0, 0.0) break # Проверяем, достигли ли цели if distance_traveled >= target_distance: rospy.loginfo(f"✓ Достигли цели ({distance_traveled:.2f} м)") self.publish_velocity(0.0, 0.0) break # Иначе продолжаем ехать progress = (distance_traveled / target_distance) * 100 rospy.loginfo(f"Прогресс: {progress:.1f}%") self.publish_velocity(0.2, 0.0) # 0.2 м/с вперёд rate.sleep() def move_in_square_with_sensing(self, side_length): """ Нарисовать квадрат, но если впереди препятствие - остановиться. Пример сложной логики с использованием датчиков. """ rospy.loginfo(f"Рисуем квадрат {side_length}x{side_length} м") for side in range(4): rospy.loginfo(f"Сторона {side + 1}/4") # Пытаемся проехать self.move_forward_with_obstacle_avoidance(side_length) # Если упёрлись в препятствие - выходим if self.distance_to_obstacle < 0.2: rospy.logwarn("Не смогли завершить маршрут - препятствие!") break # Если не последняя сторона - поворачиваемся if side < 3: rospy.loginfo("Поворот на 90 градусов...") self.turn_in_place(angle=math.radians(90)) rospy.loginfo("✓ Квадрат завершен (или прерван препятствием)") def turn_in_place(self, angle): """ Повернуться на месте на нужный угол. angle: в радианах """ start_yaw = self.current_yaw rate = rospy.Rate(10) while not rospy.is_shutdown(): angle_diff = self.current_yaw - start_yaw # Нормализуем угол while angle_diff > math.pi: angle_diff -= 2 * math.pi while angle_diff < -math.pi: angle_diff += 2 * math.pi # Если повернулись - выходим if abs(angle_diff) >= abs(angle): break # Иначе продолжаем вращаться self.publish_velocity(0.0, 0.3) # 0.3 рад/с rate.sleep() self.publish_velocity(0.0, 0.0) # стоп def main(): """Главная функция""" try: # Создаём ROS ноду navigator = MirteNavigationNode() # Даём время на инициализацию rospy.sleep(1) # Пример 1: просто ехать вперёд # navigator.move_forward_with_obstacle_avoidance(target_distance=1.0) # Пример 2: нарисовать квадрат с проверкой препятствий navigator.move_in_square_with_sensing(side_length=1.0) except rospy.ROSInterruptException: pass if __name__ == '__main__': main()
Архитектура ROS ноды
ROS нода запущена ↓ Подписывается на топики: ├── /odom (одометрия - позиция робота) └── /mirte/distance_sensor (датчик расстояния) ↓ Каждый раз когда приходит новое сообщение: ├── on_odometry_received() обновляет x, y, yaw └── on_distance_received() обновляет distance_to_obstacle ↓ Главная логика: move_in_square_with_sensing() ├── Проверяет: достигли ли цели? ├── Проверяет: препятствие впереди? ├── Принимает решение: ехать, остановиться или повернуться └── Публикует команду скорости в /cmd_vel ↓ PID контроллер + моторы + энкодеры ↓ Робот движется и отправляет новую одометрию ↓ Цикл повторяется 10 раз в секунду
Плюсы этого уровня
✅ Произвольная сложность — можем реализовать любую логику
✅ Многодатчиковая интеграция — объединяем данные из разных источников
✅ Модульность — каждый метод делает одно
✅ Переиспользуемость — эту ноду можно использовать в других проектах
✅ Стандарт индустрии — это архитектура реальных роботов
✅ Профессиональный код — готово к deployment в реальные системы
Минусы этого уровня
❌ Нужно понимать ROS архитектуру
❌ Нужно понимать callbacks и асинхронность
❌ Больше кода, сложнее отлаживать
Когда его использовать
🎓 На курсах вузов — робототехника, автономные системы
🎓 Для сложных проектов — уклонение препятствий, планирование пути
🎓 Когда нужна модульность — интегрируем несколько датчиков и поведений
🏭 Для подготовки к реальной индустрии — это реальный код робот-разработчиков
Сравнение: одна задача, четыре решения
Таблица
Параметр | Уровень 1 | Уровень 2 | Уровень 3 | Уровень 4 |
|---|---|---|---|---|
Что используем | PWM пины | setSpeed + PID | Функции Mirte | ROS нода |
Размер кода | 5 строк | 10 строк | 5 строк | 100+ строк |
Скорость разработки | ⚡⚡⚡ | ⚡⚡ | ⚡⚡ | ⏱️ медленнее |
Точность | ± 50 см | ± 20 см | ± 5 см | ± 5 см |
Обратная связь | ❌ нет | ✅ слабая | ✅ полная | ✅ полная |
Переносимость | ❌ Mirte only | ❌ Mirte only | ⚠️ похожие функции | ✅ ROS стандарт |
Сложность логики | простая | простая | средняя | произвольная |
Для кого | 8-10 лет | 10-12 лет | 12-14 лет | 14+ / профи |
Использование | обучение | обучение + проекты | проекты | реальные системы |
Образовательная ценность: почему все четыре уровня?
Для ученика: путь от новичка к инженеру
Уровень 1 (PWM) — понимание физики
Вопрос: "Почему робот перемещается?" Ответ: Потому что я установил напряжение на мотор через PWM
Уровень 2 (PID) — понимание инженерного контроля
Вопрос: "Почему робот не ездит криво?" Ответ: Потому что PID контроллер читает энкодеры и корректирует скорость
Уровень 3 (функции) — системное мышление
Вопрос: "Откуда робот знает, что проехал 1 метр?" Ответ: Из одометрии - система интегрирует данные энкодеров в позицию
Уровень 4 (ROS нода) — архитектурное мышление
Вопрос: "Как реализовать сложное поведение с несколькими датчиками?" Ответ: Разделить на методы, подписать на топики, объединить логику
Ключевое: знания НАКАПЛИВАЮТСЯ, не теряются
На уровне 3 ученик НЕ ЗАБЫВАЕТ про PWM и PID — он их видит под капотом.
На уровне 4 ученик НЕ ЗАБЫВАЕТ про Twist и одометрию — он их использует в своей ноде.
Для учителя: гибкость и долгосрочность
Разные ученики, разные уровни:
Ученик, который впервые кодирует → уровень 1-2
Ученик, который знает Python → уровень 2-3
Ученик, готовящийся к вузу → уровень 3-4
Ученик, готовящийся к работе → уровень 4 + реальные проекты
Один робот, одна платформа:
8 лет: Mirte уровень 1 (PWM, LED, простые движения)
10 лет: Mirte уровень 2 (ровное движение, PID)
12 лет: Mirte уровень 3 (точная навигация, одометрия)
14 лет: Mirte уровень 4 (ROS архитектура, сложные проекты)
Выпускник знает:
✅ Физику электроники (GPIO, PWM)
✅ Инженерные решения (PID контроллер)
✅ Системное архитектуру (ROS топики, одометрия)
✅ Профессиональное программирование (ROS ноды, callbacks, навигация, SLAM)
Почему это важно
Традиционный путь (неправильный):
8 класс: Lego WeDo (закрытый, визуальный) ↓ (забываем всё) 10 класс: Arduino + датчики (открытый, но не ROS) ↓ (забываем всё, переучиваемся) ВУЗ: ROS + C++ (шок сложности!)
Путь Mirte (правильный):
8 класс: Mirte уровень 1 (PWM) ↓ (знания остаются, добавляются) 10 класс: Mirte уровень 2 (PID) - видим PWM под капотом ↓ (знания остаются, расширяются) 12 класс: Mirte уровень 3 (ROS) - видим PID и PWM в системе ↓ (знания остаются, углубляются) 14 класс: Mirte уровень 4 (ROS нода) - проектируем архитектуру ↓ (готовы к ВУЗ и работе)
Практический вывод
На Mirte ученик видит весь путь — от одного провода к архитектуре системы.
Каждый уровень закрывает вопрос предыдущего:
"Почему криво?" → Уровень 2 (PID)
"Как узнать расстояние?" → Уровень 3 (одометрия)
"Как реализовать сложное поведение?" → Уровень 4 (ROS нода)
"Как работает реальная робототехника?" → Уровень 4 показывает это
Это не просто четыре способа написать код. Это четыре парадигмы инженерного мышления.
И именно поэтому Mirte работает как долгосрочная образовательная платформа — от ребёнка в 8 лет, управляющего LED через PWM, до старшеклассника, проектирующего ROS архитектуру.
Обсудить статью можно в ROS чате.
Народный курс по ROS2 на степике.
Как понять, что образовательный подход и образовательный робот приносит пользу? Главный критерий готовит ли он кадры с необходимыми знаниями и опытом для бизнеса и государства, именно поэтому были разработаны ROS2 соревнования которые пройдут на ROS meetup 21-22 марта 2026 года. Задача соревнований максимально приближена к той которую решает мобильная манипуляция в сервисной и промышленной робототехнике. Победители соревнования могут претендовать на вавакансии в ведущих робототехнических компаниях. О этих соревнованиях вы можете прочитать подробную статью на Хабре.
