Подключение скрипта Python к симулятору CoppeliaSim
Методист по олимпиадной робототехнике Университета Иннополис Алексей Овсянников рассказывает, как управлять роботом и сценой из программы, написанной на Python.
Продолжаем разбираться с симулятором CoppeliaSim. Сегодня будет внеочередная статья, так как начинаются курсы повышения квалификации по подготовке к номинации «Манипуляционные ИРС» олимпиады Innopolis Open in Robotics, а далеко не все слушатели умеют и хотят писать скрипты на Lua. Крайне популярным языком программирования (в образовательной среде в частности) является Python, поэтому рассмотрим, как можно написать на нем программу для управления роботом или сценой в симуляторе.
Сегодняшняя статья в полной мере соответствует древнему лозунгу программистов:
Никогда не стоит унывать и решение рано или поздно придет. Ну и про google не стоит забывать!
Начнем с того, что программировать на Python ранее мне не доводилось. Копирование готовых скриптов из умных статей не считается. Так что каждая возникающая ошибка была новой, неизведанной задачей, препятствием, которое приходилось преодолевать. Может это и к лучшему — я прошел эти грабли в роли такого же новичка, для которых и пишу.
Думаю, достаточно строить из себя мученика, пора переходить к делу! Внешние языки программирования могут использовать два набора API: legacy remote API и B0-based API. Ссылки на страницы справок не даю, так как официальный сайт лежит. Но справку можно найти в самом симуляторе:
Находим соответствующие статьи, изучаем их:
Понимаем, что legacy уже устарели и поддерживаются по инерции, так что имеет смысл сразу учиться использовать B0-based API. Дальнейшая работа будет разделена на четыре этапа:
- Настройка инструментария разработки — я рассмотрю как использование стандартного IDLE Python, так и работу через Visual Studio Code.
- Запуск и тестирование сцен и скриптов из библиотеки примеров — нужно для настройки и проверки всех инструментов, чтобы исключить ошибки наших собственных программ.
- Доработка сцены для подключения внешней управляющей программы — очевидно, что на этом этапе нужно включить сервер и ждать подключение программ-клиентов.
- Написание и запуск программы на Python — попробуем что-нибудь простенькое, например, плавное перемещение звеньев из точки в точку как в прошлой статье.
Подготовка инструментария
Идем на официальный сайт python.org и находим раздел Downloads. В нем переходим на All releases:
На открывшейся странице переходим в раздел для Windows (или другой актуальной для вас операционной среды):
И уже на этой странице видим пакеты установки для 64-битных систем:
Скорее всего вы установили симулятор CoppeliaSim тоже 64-битной версии. Если симулятор 32-битный, то и Python нужен 32-битный. Во время установки ставим галочку «Add …. To PATH», это избавит от ошибок и лишних движений в будущем. В результате на рабочем столе или в меню появится пункт IDLE (Python 3.8 64-bit):
Это и есть инструментарий, консоль, «среда разработки» Python. Тут мы можем писать команды «поштучно» или создать файл-скрипт из меню, в котором опишем алгоритм:
Внимательно изучив страницу «Enabling the B0-based remote API — client side» справки CoppeliaSim можно заметить, что для работы c B0-remote API в Python необходимо установить MessagePack:
Команду нам подсказывают, вводить ее надо в командную строку (или терминал) операционной системы:
Появился желтый warning, версия самого pip старая, есть новее и можем обновиться командой:
python -m pip install —upgrade pip
Хорошо, обновляемся и повторяем установку MessagePack’а:
Вот теперь все нормально, скрипты Python смогут общаться с симулятором через B0-based API.
В последнее время большую популярность приобрел редактор кода Visual Studio Code. В нем есть поддержка разработки на Python. Для использования этого варианта идем на официальный сайт, качаем и устанавливаем Visual Studio Code для своей операционной системы. Далее двигаемся согласно этому руководству: устанавливаем расширение, проверяем установку и выбираем интерпретатор Python. Тут стоит указать интерпретатор той же разрядности (32 или 64 бита), что и симулятор. У меня установлены обе версии, так что пришлось указывать явно.
На этом этапе стоит создать какой-нибудь простой скрипт и протестировать его запуск через VS Code. Можно даже использовать «HelloWorld» из руководства. Таким образом мы проверим, все ли в порядке с самой VS Code. Если ранее не был установлен MessagePack, то сейчас самое время это сделать. Открываем через меню «Terminal — New terminal» и в появившейся панели внизу пишем команду «pip install msgpack»:
Запуск тестовых сцен и скриптов
В настоящий момент разработчики симулятора активно изменяют тестовые сцены и программы, так что назначение и сочетание некоторых из них я не смог определить (сцена уже поменялась, а скрипт и описание к нему остались от предыдущей версии). Рассматривать я буду примеры из актуальной сборки CoppeliaSim 4.0.0. rev.4.
Открываем симулятор и сразу же запускаем b0-remote-API сервер:
Ждем несколько секунд, видим появившееся окно консоли и внизу сообщение, что все запущено:
Закрывать это окно ни в коем случае нельзя, это и есть API-сервер. При подключении программ-клиентов в этой консоли будут появляться соответствующие сообщения.
Теперь находим какую-нибудь сцену, к которой можно подключиться программой извне. Симулятор уже содержит демо-сцены в каталоге C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\scenes. Открываем, например, pControllerViaRemoteApi. Читаем сообщение, выскочившее при открытии:
Как нас и просят, не запускаем симуляцию (ее стартует программа-клиент), идем в указанный каталог C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\programming\b0RemoteApiBindings\python. Далее имеет смысл скопировать все файлы из этого каталога в какую-нибудь папку проекта, чтобы не бояться их испортить. Я не стал этого делать, а просто открыл этот каталог в VS Code:
Выбираем файл pController.py:
Если вы не используете VS Code, то этот файл можно открыть через контекстное меню в IDLE (важно — в IDLE нужной разрядности!):
Запускаем скрипт с помощью зеленого треугольничка в правом верхнем углу в VS Code или клавишей F5 в IDLE Python. Скорее всего, выскочит ошибка, что не найдена b0.dll:
Находим эту dll в корневом каталоге симулятора C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu и копируем к себе в папку со скриптами. Ранее я приводил отрывок из справки, в котором сказано, что эта библиотека явно зависит от других. Их мне копировать не хотелось, поэтому я нагуглил и добавил в программу команды, позволяющие искать недостающие dll в корневом каталоге:
import os
os.add_dll_directory(‘путь_к_файлам_dll’)
Так как в исходном скрипте ошибка возникает уже на строке 13 (import b0RemoteApi), то эти команды надо вставить еще выше:
Запускаем и, скорее всего, видим следующее:
Синие строки нам говорят, что программа подключилась к сцене, а потом пошли красные строки — ошибки. Ну что ж, продолжаем превозмогать трудности и расчехляем большие пушки! Ошибки вызваны тем, что недавно вышла новая версия MessagePack’а, а сцены и скрипты симулятора приспособлены к старой. Найти исправленный код скриптов, уже адаптированный к обновлению, можно на GiHub’е разработчиков. Лично я скачал исходники архивом и выдернул все содержимое папки Pytrhon. Еще раз исправляем файл pController.py, добавив две строки для поиска dll.
Возвращаемся к симулятору — из-за ошибок он не смог остановиться штатным образом, помогаем ему:
Запускаем программу еще раз и видим, что теперь ошибок нет (я специально привожу скрины из IDLE и VS Code, чтобы было понятно, где и как что выглядит):
Можете еще несколько раз позапускать скрипт и понаблюдать, как двигаются объекты сцены.
В итоге делаем вывод, что все работает. Можете сами изучить скрипт и попытаться понять, что там происходит. Я же буду двигаться дальше, к Манипуляционным ИРС.
Доработка собственной сцены
Давайте рассмотрим подготовку сцены на примере старшей возрастной группы. Скачиваем со страницы ресурсов олимпиады сцену, открываем ее в симуляторе:
Находим в готовых моделях B0 remote API server и добавляем его на сцену:
Настраиваем имя ноды и канала, я сделал себе так. Для сохранения имени жмем Restart node with above names:
Теперь осталось только отключить управление роботов из внутреннего скрипта на Lua. Я для этого просто закомментировал все содержимое функции sysCall_threadmain:
Этого достаточно, чтобы сцена заработала под управлением внешней программы.
Написание собственной программы на Python
В каталоге, где лежат файлы b0.dll, b0.py и b0RemoteApi.py (можно в том же каталоге, где был скрипт pController.py) создаем новый файл с программой на Python’е, например, SeniorManIRS.py. Этот набор файлов в каталоге можно считать необходимым минимумом:
- Файл .py с управляющей программой
- py
- py
- dll
Разумнее будет синхронизировать программу и сцену в симуляторе (как я уже говорил в прошлой статье в этом случае симулятор отрабатывает полученную команду на долю секунды, потом останавливается, отправляет состояние сцены в программу и ждет дальнейших команд). О том, как это сделать, написано в справке, в разделе «B0-based remote API modus operandi». Копируем оттуда код в нашу программу:
Естественно, надо в самом начале добавить знакомые нам две строки для поиска dll-лек в корневом каталоге симулятора. Находим в конце программы цикл, в нем как раз и будут выполняться синхронизированные с симулятором шаги. Перед циклом надо получить ссылки на связи (joint’ы, приводы, обобщенные координаты), а потом уже в цикле их перемещать. На языке Lua в прошлой статье мы использовали команду sim.GetObjectHandle(), скорее всего для Python’а есть подобная команда. Поиск по списку API-команд дал вот такую:
simxGetObjectHandle(string objectName, string topic)
А для считывания и установки позиций нашлись вот такие команды:
simxGetJointPosition(number jointHandle, string topic)
simxSetJointPosition(number jointHandle, number position, string topic)
Примеры использования этих или похожих команд можно найти в изученном ранее файле pController.py. Особое внимание стоит обратить на то, что команды возвращают массивы из двух значений — выполнилась ли команда (true-false) и нужное нам значение. Так что, запрашивая текущую позицию, мы получаем массив, а нужное значение хранится во второй его ячейке.
Добавим эти команды в программу, настроив простой цикл перемещения двух звеньев от текущего положения до угла 150:
Пробежимся по некоторым моментам:
- В строке 2 перед указанием пути к каталогу с dll я поставил символ r, чтобы обратные слеши корректно обрабатывались;
- В строке 5 я подключил библиотеку математических операций, чтобы использовать число Пи и переводить радианы в градусы и обратно;
- В строке 8 я исправил имя канала на выбранный в сцене симулятора (настраивали на предыдущем шаге);
- В строках 26-27 происходит запрос ссылок на приводы по их именам в сцене симулятора, они попадают в массивы link1 и link2; конкретно ссылки будут во вторых ячейках массивов;
- В строках 29-30 запрашиваются текущие координаты приводов; в качестве ссылок я использую вторые ячейки соответствующих массивов;
- В строках 32-33 полученные в радианах обобщенные координаты переводятся в градусы;
- В строках 39-40 идет накопление координат (в цикле), в следующих двух строках приводы будут устанавливаться в эти положения;
- В строке 43 я добавил небольшую паузу, чтобы манипулятор не улетал мгновенно в крайние положения
Вот, пожалуй, и все. Основная сложность с первичной настройкой инструментов — установкой всех необходимых библиотек, правильным выбором разрядности и т.д. После этого работа со сценой и собственными скриптами достаточно проста.
Подключение к внешним API из других языков и сред программирования происходит аналогично, надо только внимательно читать справку.
На сегодня буду заканчивать, и так статья вышла очень большой. Надеюсь, она будет полезна нашим слушателям на курсах повышения квалификации и школе олимпиадной подготовки, да и всем остальным, желающим познакомиться поближе с симулятором CoppeliaSim. Напишите в комментариях, какую область работы с симулятором раскрыть в следующих статьях, что было бы интересно изучить еще?