Проектирование и управление манипулятором робота с помощью языка программирования Python
PyBullet — это интерфейс прикладного программирования (API), который позволяет вам иметь быстрый доступ к моделированию роботов с помощью механизма моделирования Bullet Physics SDK. Имея модель робота, вы готовы сразу приступить к программированию своего робота без необходимости трудоемкой настройки моделирования, как в операционной системе роботов (ROS). Это быстрый инструмент для исследований и обучения.
В этой статье вы узнаете, как создать модель SCARA (шарнирно-сочлененная рука робота с селективным соответствием требованиям) и смоделировать ее с помощью PyBullet с использованием языка программирования Python.
Благодаря расположению шарнира SCARA с параллельными осями, рука слегка податлива в направлении X-Y, но жестка в направлении Z, отсюда и термин селективная податливость. Это выгодно для многих типов сборочных операций, например, для вставки круглого штифта в круглое отверстие без заедания. Википедия
Модели роботов могут быть разработаны с использованием программного обеспечения CAD (автоматизированного проектирования), такого как Fusion360, SolidWorks, Blender и FreeCAD, или запрограммированы с помощью таких инструментов, как OpenSCAD. Программное обеспечение для моделирования роботов, такое как ROS2 или PyBullet, должно считывать файлы роботов в определенных форматах файлов, и один из этих форматов называется URDF (унифицированный формат описания роботов), который определяет физические свойства робота. Программное обеспечение CAD может преобразовывать модели роботов в URDF, но поскольку наш робот SCARA представляет собой простую модель, мы сами напишем код URDF, чтобы лучше понять, как он работает.
Наш робот scara будет роботом 2R (2 вращающихся шарнира) с 2 степенями свободы (степень свободы) и без захвата (или рабочего органа).
Чтобы начать изучать операционную систему роботов (ROS2) для управления роботами, ознакомьтесь с нашим всеобъемлющим курсом для начинающих.
Создание нашего робота Scara
Мы создадим файл и назовем его scara_bot.urdf. Откройте этот файл в любом текстовом редакторе, чтобы начать писать код. URDF — это язык разметки, поэтому мы начнем файл с версии XML (расширяемый язык разметки) и тегом robot. Все, что касается нашего робота, должно быть внутри открывающего (‹robot›) и закрывающего (‹/robot›) тега robot.
<?xml version="1.0"?> <robot name="scara_robot"> </robot>
У роботов есть цвета, поэтому мы определим некоторые цветовые материалы, которые будут иметь звенья или тела нашего робота. Эти цвета будут использоваться позже в коде, вызывая имена, которые мы им даем.
<?xml version="1.0"?> <robot name="scara_robot"> <material name="blue"> <color rgba="0.0 0.0 1.0 1.0"/> </material> <material name="black"> <color rgba="0.0 0.0 0.0 1.0"/> </material> <material name="white"> <color rgba="1.0 1.0 1.0 1.0"/> </material> </robot>
База
Основание робота похоже на шасси автомобиля, любая другая часть или звено этого робота можно проследить до него. Для серийных роботов-манипуляторов, таких как робот-скара, основание обычно крепится к плоской поверхности, на которой стоит робот. Помните, что каждая часть робота-скары представляет собой звено, соединенное суставами так же, как человеческая рука соединена плечевым и локтевым суставами.
Давайте создадим черную цилиндрическую основу для нашего робота и укажем ее положение относительно начала координат:
<?xml version="1.0"?> <robot name="scara_robot"> <material name="blue"> <color rgba="0.0 0.0 1.0 1.0"/> </material> <material name="black"> <color rgba="0.0 0.0 0.0 1.0"/> </material> <material name="white"> <color rgba="1.0 1.0 1.0 1.0"/> </material> <link name="world"/> <link name="base_link"> <visual> <origin xyz="0.0 0.0 0.4" rpy="0.0 0.0 0.0"/> <geometry> <cylinder length="0.8" radius="0.1"/> </geometry> <material name="black"/> </visual> </link> </robot>
Теперь мы закрепим базу на мире, чтобы она не упала. Это достигается путем создания фиксированного соединения между base_link и ссылкой world:
<?xml version="1.0"?> <robot name="scara_robot"> <material name="blue"> <color rgba="0.0 0.0 1.0 1.0"/> </material> <material name="black"> <color rgba="0.0 0.0 0.0 1.0"/> </material> <material name="white"> <color rgba="1.0 1.0 1.0 1.0"/> </material> <link name="world"/> <link name="base_link"> <visual> <origin xyz="0.0 0.0 0.4" rpy="0.0 0.0 0.0"/> <geometry> <cylinder length="0.8" radius="0.1"/> </geometry> <material name="black"/> </visual> </link> <joint name="base_joint" type="fixed"> <parent link="world"/> <child link="base_link"/> </joint> </robot>
Чтобы увидеть, как выглядит ваша модель, перетащите файл URDF на этот сайт, он покажет вам 3D-модель робота.
Верхняя рука
Наш робот-скара будет иметь два подвижных звена, которые будут соединены между собой шарниром. Первое звено, называемое верхним плечом или плечом1, будет соединено с базовой_связью, но на этот раз соединение будет не фиксированным, а вращающимся. Звено Руко1, шарнир которого вращается вокруг оси Z, будет смоделировано в виде параллелепипеда или прямоугольного параллелепипеда и окрашено в белый цвет.
<?xml version="1.0"?> <robot name="scara_robot"> <material name="blue"> <color rgba="0.0 0.0 1.0 1.0"/> </material> <material name="black"> <color rgba="0.0 0.0 0.0 1.0"/> </material> <material name="white"> <color rgba="1.0 1.0 1.0 1.0"/> </material> <link name="world"/> <link name="base_link"> <visual> <origin xyz="0.0 0.0 0.4" rpy="0.0 0.0 0.0"/> <geometry> <cylinder length="0.8" radius="0.1"/> </geometry> <material name="black"/> </visual> </link> <joint name="base_joint" type="fixed"> <parent link="world"/> <child link="base_link"/> </joint> <link name="arm1"> <visual> <origin xyz="0.0 -0.5 0.0" rpy="0.0 0.0 0.0"/> <geometry> <box size="0.1 1.0 0.1"/> </geometry> <material name="white"/> </visual> </link> <joint name="arm1_joint" type="revolute"> <origin xyz="0.0 0.0 0.8" rpy="0.0 0.0 0.0"/> <parent link="base_link"/> <child link="arm1"/> <axis xyz="0.0 0.0 1.0"/> <limit lower="-1.0" upper="1.0" effort="1000.0" velocity="1000.0"/> </joint> </robot>
Давайте визуализируем подвижную руку, которую мы только что создали, используя веб-средство просмотра URDF:
Нижняя рука
Нижнее плечо, звено рука2, будет соединено со звеном рука1 через вращающееся соединение, как показано ниже.
<?xml version="1.0"?> <robot name="scara_robot"> <material name="blue"> <color rgba="0.0 0.0 1.0 1.0"/> </material> <material name="black"> <color rgba="0.0 0.0 0.0 1.0"/> </material> <material name="white"> <color rgba="1.0 1.0 1.0 1.0"/> </material> <link name="world"/> <link name="base_link"> <visual> <origin xyz="0.0 0.0 0.4" rpy="0.0 0.0 0.0"/> <geometry> <cylinder length="0.8" radius="0.1"/> </geometry> <material name="black"/> </visual> </link> <joint name="base_joint" type="fixed"> <parent link="world"/> <child link="base_link"/> </joint> <link name="arm1"> <visual> <origin xyz="0.0 -0.5 0.0" rpy="0.0 0.0 0.0"/> <geometry> <box size="0.1 1.0 0.1"/> </geometry> <material name="white"/> </visual> </link> <joint name="arm1_joint" type="revolute"> <origin xyz="0.0 0.0 0.8" rpy="0.0 0.0 0.0"/> <parent link="base_link"/> <child link="arm1"/> <axis xyz="0.0 0.0 1.0"/> <limit lower="-1.0" upper="1.0" effort="1000.0" velocity="1000.0"/> </joint> <link name="arm2"> <visual> <origin xyz="0.0 -0.25 0.0" rpy="0.0 0.0 0.0"/> <geometry> <box size="0.1 0.5 0.1"/> </geometry> <material name="blue"/> </visual> </link> <joint name="arm2_joint" type="revolute"> <origin xyz="0.0 -1.0 0.0" rpy="0.0 0.0 0.0"/> <parent link="arm1"/> <child link="arm2"/> <axis xyz="0.0 0.0 1.0"/> <limit lower="-1.0" upper="1.0" effort="1000.0" velocity="1000.0"/> </joint> </robot>
Попробуйте визуализировать полную настройку робота с помощью онлайн-просмотра URDF и взаимодействуйте с моделью, перемещая связи через суставы. Давайте перейдем к другой части этой статьи, где мы пишем программу на Python, используя API PyBullet для моделирования нашей модели робота.
PyBullet: моделирование роботов
Отправной точкой для моделирования робота является наличие модели робота в формате, понятном симулятору робота, который мы сделали выше. PyBullet — это API, который позволяет вам управлять моделями роботов с помощью модулей Python и языка программирования python. Мы будем управлять нашим роботом-скарой, используя интерфейсы, предоставляемые PyBullet.
Чтобы установить PyBullet на Linux (Ubuntu) или Mac, откройте терминал (Ctrl+Alt+T), скопируйте и вставьте строку ниже:
sudo pip3 install pybullet
Для Windows выполните шаги здесь.
Код
Создайте свой файл python в том же каталоге/папке, где находится URDF. Назовем его my_robot.py и откроем в любом текстовом редакторе, в нашем случае в VS Code.
Импортируйте модуль PyBullet, который предоставляет вам доступ к API. PyBullet_data позволяет вам использовать файлы данных, поставляемые с PyBullet, а time — это модуль, который помогает ввести задержку в нашу симуляцию.
import pybullet as p import pybullet_data import time
Первое, что нужно сделать после импорта модулей, — это подключиться к физическому моделированию с помощью встроенного физического сервера под названием GUI. Чтобы увидеть, как выглядит PyBullet, мы запустим симуляцию без нашей модели робота. Не так быстро! Нам нужен метод stepSimulation(), чтобы запустить симуляцию с временным шагом по умолчанию, равным 1/240 секунды. Теперь наш код должен выглядеть так:
import pybullet as p import pybullet_data import time p.connect(p.GUI) while True: p.stepSimulation() time.sleep(1./240)
Если вы используете VS Code, вы можете запустить код с помощью Ctrl + F5 или открыть терминал (Ctrl + Alt + T), перейти в каталог кода и запустить файл с помощью Python3:
$ cd scara_robot/ ~/scara_robot$ python3 my_robot.py
Представление PyBullet после запуска кода показано ниже:
Наша среда моделирования — это пустой мир или пространство, в котором нет земли, поэтому наш робот упадет, если мы поместим его в этот мир. Давайте дадим слово этой среде. Этот пол представляет собой сине-белую плитку под названием plane, расположенную внутри PyBullet, доступ к которой можно получить через pybullet_data, как показано ниже.
import pybullet as p import pybullet_data import time p.connect(p.GUI) p.setAdditionalSearchPath(pybullet_data.getDataPath()) plane = p.loadURDF("plane.urdf") while True: p.stepSimulation() time.sleep(1./240)
Закройте симуляцию и запустите ее снова, чтобы увидеть изменения
Теперь, когда у нас есть место для отдыха нашего робота, давайте перенесем его в мир моделирования. Используйте метод loadURDF(), чтобы загрузить робота scara и установить гравитацию. Объекты будут плавать или двигаться хаотично, если гравитация не установлена должным образом.
import pybullet as p import pybullet_data import time p.connect(p.GUI) p.setAdditionalSearchPath(pybullet_data.getDataPath()) plane = p.loadURDF("plane.urdf") robot = p.loadURDF("scara_bot.urdf") p.setGravity(0,0,-10) while True: p.stepSimulation() time.sleep(1./240)
Чтобы управлять роботом, мы должны быть уверены, что PyBullet понимает суставы, которые будут управлять ссылками. Методы getNumJoints() и getJointInfo() могут получить количество суставов в роботе и информацию о каждом суставе соответственно. Мы будем использовать этот метод, чтобы понять сустав, которым мы хотим управлять. getNumJoints() принимает обязательный параметр, который является идентификатором робота, который мы запрашиваем, чтобы получить его соединение, в то время как getJointInfo() принимает идентификатор робота и номер соединения, которое мы хотим запросить. информация. Мы будем использовать цикл for для запроса идентификатора нашего робота, который был назван robot при загрузке URDF.
import pybullet as p import pybullet_data import time p.connect(p.GUI) p.setAdditionalSearchPath(pybullet_data.getDataPath()) plane = p.loadURDF("plane.urdf") robot = p.loadURDF("scara_bot.urdf") p.setGravity(0,0,-10) for i in range(p.getNumJoints(robot)): print(p.getJointInfo(robot, i)) while True: p.stepSimulation() time.sleep(1./240)
Запустите симуляцию
В нижней части рисунка выше показаны base_joint, arm1_joint и arm2_joint в скобках. Первое число в скобках — это индекс каждого сустава, который можно использовать для связи с ними. Прочтите Руководство по PyBullet, чтобы узнать больше о других деталях, указанных в скобках.
Теперь, когда мы знаем суставы, которыми хотим управлять (1 и 2), давайте перейдем к методам управления суставами. setJointMotorControlArray() управляет соединением и принимает несколько параметров, из которых мы будем использовать только четыре. Параметры:
- уникальный идентификатор робота
- jointIndex: это может быть передано как массив.
- controlMode: в PyBullet есть разные режимы управления; POSITION_CONTROL, VELOCITY_CONTROL, TORQUE_CONTROL и PD_CONTROL. Нас интересует POSITION_CONTROL
- targetPosition: здесь мы хотим, чтобы каждый сустав нашего робота находился.
Мы переместим ссылку arm1 в позицию -0,456, а ссылку arm2 в позицию 0,24. Позиции указаны в радианах. Нижний и верхний пределы, определенные в нашем URDF, ограничивают наше роботизированное соединение минимумом -1 радиан и максимумом 1 радиан. Суставы не могут двигаться за пределами этого диапазона.
import pybullet as p import pybullet_data import time p.connect(p.GUI) p.setAdditionalSearchPath(pybullet_data.getDataPath()) plane = p.loadURDF("plane.urdf") robot = p.loadURDF("scara_bot.urdf") p.setGravity(0,0,-10) for i in range(p.getNumJoints(robot)): print(p.getJointInfo(robot, i)) while True: target_arm_1 = -0.456 target_arm_2 = 0.24 p.setJointMotorControlArray(robot, [1,2], p.POSITION_CONTROL, targetPositions=[target_arm_1, target_arm_2]) p.stepSimulation() time.sleep(1./240)
Робот переместился из прямолинейного положения по умолчанию в наше целевое положение. Вы можете изменить целевое положение, чтобы увидеть, как ведет себя ваш манипулятор. Поздравляем, вы научились использовать PyBullet для моделирования роботов! 👏
Заключение
Вы видели, как создать простую модель робота-скары с двумя степенями свободы (2-DOF) в формате URDF с подробной информацией о суставах и оси вращения. Вы также увидите, как использовать API PyBullet для загрузки робота, запроса и получения информации о нем, а также управления его соединениями.
Следующим шагом будет добавление к роботу еще одного звена, призматического шарнира, который заставит его двигаться в трехмерном пространстве, и рабочего органа, также называемого захватом, для захвата объектов. Если вы хотите научиться моделировать робота с помощью операционной системы для роботов (ROS2), отметьте Reflect Robotics, чтобы изучить управление роботом с помощью Python и C++.
Если вам понравилась эта статья, пожалуйста, нажмите кнопку «Мне нравится» и не забудьте оставить комментарий, если у вас есть вопросы, замечания, исправления или вы просто хотите оценить работу.