• A
  • A
  • A
  • АБВ
  • АБВ
  • АБВ
  • А
  • А
  • А
  • А
  • А
Обычная версия сайта

Первый проект

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

Первый проект

Введение

Когда мы поняли, что группе роботехники быть, встал вопрос о первом проекте. В качестве старта необходимо было выбрать что-то выполнимое за пару месяцев, а еще у нас не было уверенности, что своими силами мы можем сделать сложную механику (у нас был один 3D-принтер и скромный бюджет на общедоступные компоненты). С другой стороны хотелось решить какую-то известную, но интересную задачу управления, параллельно научившись чему-то новому.

В то время нам в руки уже попались черновики курса Underactuated Robotics, где многие алгоритмы разбирались на примере задачи CartPole (альтернативное название “inverted pendulum”), поэтому наш выбор достаточно быстро пал именно на нее. А еще эта задача отлично подходит для тестирования алгоритмов обучения с подкреплением, так что мы брались за проект с мыслью превратить этого “робота” в тренажер для самых разных экспериментов и использовать его для домашек будущего факультатива.

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

Механика

К текущей схеме мы пришли не сразу. Вдохновением для проектирования механической части послужили 3D-принтеры, поэтому мы использовали множество стандартных комплектующих для них. Первая версия состояла из шагового двигателя, ременной передачи и направляющих с цилиндрическим сечением. Кинематическая схема оказалось достаточно удачной за исключением того, что направляющие немного прогибались под действием тангенциальных сил, и, как следствие, во второй версии мы просто перешли на более стабильную направляющую в виде рельсы.

Первая версия каретки

Выбор контроллера был по большей части случайным, у нас уже на руках было несколько плат с ESP32 и их мощности в целом нам хватало (к тому же, для них была отличная библиотека для управления двигателем — FastAccelStepper). Начинали мы с самой простой беспаечной макетной платы, а со временем, когда электрическая схема устоялась, мы просто распаяли небольшую плату вручную с возможностью замены сгоревшего контроллера и драйвера.

Макетная плата

Позиция маятника считывается магнитным энкодером AS5600, который установлен с задней стороны каретки. Каретка приводится в движение шаговым двигателем NEMA 23 + драйвером TMC2209. В отличие от DC двигателей, на которых выходное “усилие” и, соответственно, ускорение около-линейно зависят от силы тока, шаговый двигатель умеет только “делать шаг”, т.е. поворачиваться примерно на 1/200 оборота. На практике оказалось достаточно просто “симулировать” ускорение каретки через частоту смены шага двигателя. По поводу ремня были сомнения, что его эластичность будет мешать управлению, но на практике все оказалось не так критично. К слову, это распространенная проблема на 3D принтерах, называемая “ghosting” или “ringing”, с которой борются с помощью алгоритма Input Shaping.

Управление

Для отладки мы сразу решили научиться делать физическую симуляцию. Не сильно думая, выбрали библиотеку pybullet, которая позволяет описать робота в sdf формате, а потом делает симуляцию “за тебя“. Это было полезно с образовательной точки зрения, но в итоге оказалось излишним. Гораздо проще оказалось вспомнить физику, а потом в 100 строчек набросать симуляцию, где у тебя полный контроль происходящего, да еще и работает все быстрее. Странно, что нам это сразу не пришло в голову, потому что было очевидно, что выводить дифференциальное уравнение динамики все равно придется для реализации алгоритма управления. Мы достаточно быстро остановились на очень простой модели, которая не учитывает трения, но работает с маятниками произвольный формы (делаем допущение, что можем достаточно точно оценить массу и момент инерции).

Расписав уравнения динамики, мы поняли, что хотим управлять именно ускорением, а не силой, т.к. это значительно упрощало модель. Благо наш шаговый двигатель был достаточно моментный и позволял достигать достаточно широкого спектра ускорений, однако стоит признать, что мы серьезно ограничены в максимальной скорости.

Далее захотелось потестировать уже какие-то алгоритмы управления. Для простоты решили научить робота держать стержень в балансе. С этим отлично справляется простой LQR-регулятор. Сделав пару запусков в симуляторе, мы осознали, как важна частота работы регулятора. При 10 Hz даже такая простая задача, как удержание палочки, оказалась невыполнимой. Это сразу побудило нас проверить, с какой герцовкой мы способны управлять пайплайном, если на управляющем компьютере крутится код на python, а общение с контроллером идет через serial порт в виде бинарных сообщений. Немного поколдовав и переписав код, мы поняли, что легко можем достигать 100 Hz (а если нужно, то можно выжать и больше). Затем был этап мучительной настройки параметров регулятора, это грустный и плохо формализуемый процесс, но в результате мы справились.

 

Потеститровав железку с балансом, мы перешли к задаче планирования траектории. Для этого нам очень сильно пригодились заметки упомянутого курса Underactuated Robotics. Более того автор этих лекций еще и разрабатывает со студентами библиотеку drake, где из коробки реализовано множество алгоритмов optimal control. Немного поколдовав на питоне, мы быстро научились вычислять оптимальную траекторию движения каретки. Правда даже в симуляторе после нескольких секунд работы накапливалась значительная ошибка между запланированной и исполненной траекториями (это связано с частотой управляющего сигнала). Сразу стало очевидно, что в реальной жизни будет еще хуже, а перепланировать траекторию на лету нам не хватит производительности. Это погрузило нас в серьезные раздумья на пару недель, но решение было найдено в виде LQR trajectory tracker, который смотрит на запланированную траекторию, знает на сколько мы сильно отклонились и корректирует запланированное ускорение на новое, чтобы вернуть робота к изначальному плану. В симуляторе это заработало просто отлично, и мы перешли к тестам на реальной железке.

Конечно же, как это обычно бывает, с первого раза на реальном железе у нас не заработало абсолютно ничего. Тут тебе и закусывание подшипника, которое пришлось убирать, и качество исполнения команд, и неточность описания модели (мы не учитывали массу и инерцию крепления маятника). Но... спустя неделю мучений, дебаггинга до 3:00 ночи и литров выпитого кофе, наступил исторический момент! Первый удачный запуск!

Что дальше?

  1. Мы уже начали эксперименты с обучением RL-моделей в симуляторе. Это небольшие полносвязные сети, работающие в пространстве непрерывных состояний и команд управления, для обучения используем ddpg. Постараемся рассказать про это подробнее в ближайшее время.
  2. Мы поняли, что текущая версия достаточно “грязно” исполняет команды управления, поэтому хотим сделать 3-ю (надеемся, финальную) версию робота, где будут подчищены все ошибки и достигнута высокая точность исполнения команд. Эту версию выложим в нашем репозитории, с “образцовой” документацией по сборке, API и запуску.
  3. На практике оказалось, что линейный CartPole вышел громоздким, чтобы студентам было удобно с ним работать за столом. Поэтому мы решили сделать радиальную версию, подсмотрев идею на YouTube. Этого робота собирает наша студентка в рамках проекта!
  4. С классическими методами управления мы уперлись в производительность: у CartPole нелинейная динамическая модель и расчет оптимальной траектории это дорогая операция. Поэтому сейчас мы умеем стартовать только из точки покоя. Будем дальше читать книжки и учиться работать из произвольного положения маятника и каретки!