
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 года. Задача соревнований максимально приближена к той которую решает мобильная манипуляция в сервисной и промышленной робототехнике. Победители соревнования могут претендовать на вавакансии в ведущих робототехнических компаниях. О этих соревнованиях вы можете прочитать подробную статью на Хабре.
