Image

Руководство для начинающих по робототехнике на Python

Создавайте 3D-симуляции с помощью PyBullet

Делиться

aa04f3044c21c912d4db92b7082e0630

Вступление

Роботы — это машины, способные выполнять задачи и принимать решения, копируя или заменяя действия человека. Робототехника — это научная область, занимающаяся проектированием и созданием роботов. Она представляет собой междисциплинарное сочетание:

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

В настоящее время ROS (операционная система для роботов) — это основной фреймворк для робототехники, который управляет всеми различными компонентами робота (датчиками, двигателями, контроллерами, камерами и т. д.), где все компоненты обмениваются данными по модульному принципу. Фреймворк ROS предназначен для реальных прототипов роботов и может использоваться как с Python, так и с C++. Учитывая его популярность, существует множество библиотек, созданных на основе ROS, например, Gazebo — самый продвинутый 3D-симулятор.

beff7955f5f8606e89c1fceba22e4733

Несмотря на сложность Gazebo, основы робототехники и удобные симуляции можно изучить и вне экосистемы ROS . Основные библиотеки Python:

  • PyBullet (для начинающих) — отлично подходит для экспериментов с URDF (Unified Robot Description Format), представляющим собой XML-схему для описания корпусов, частей и геометрии робота.
  • Веботы (средний) — физика более точная, поэтому можно строить более сложные симуляции.
  • MuJoCo (продвинутый) — симулятор реального мира, используется для исследовательских экспериментов. Библиотека RoboGYM от OpenAI построена на основе MuJoCo.
ce2c711276d27de6b16b3994426ff59a

Поскольку это руководство для начинающих, я покажу, как создавать простые 3D-модели с помощью PyBullet . Я покажу несколько полезных фрагментов кода на Python, которые можно легко применить в других подобных случаях (просто скопируйте, вставьте и запустите), и прокомментирую каждую строку кода, чтобы вы могли повторить этот пример.

Настраивать

PyBullet — самый удобный физический симулятор для игр, визуальных эффектов, робототехники и обучения с подкреплением. Вы можете легко установить его одной из следующих команд (если pip не работает, conda точно должен подойти):

pip install pybullet conda install -c conda-forge pybullet

PyBullet можно запустить в двух основных режимах:

  • p.GUI → открывает окно и показывает симуляцию в реальном времени.
  • p.DIRECT → без графического режима, используется для скриптов.

импортировать pybullet как p p.connect(p.GUI) #или p.connect(p.DIRECT)

24bc948ec85349e5cf919a3041431cfa

Поскольку это физический симулятор, первое, что нужно сделать, это настроить гравитацию :

p.resetSimulation() p.setGravity(gravX=0, gravY=0, gravZ=-9.8)

Задаёт вектор глобальной гравитации для моделирования. «-9,8» по оси Z означает ускорение 9,8 м/с² вниз, как на Земле. Без этого ваш робот и самолёт парили бы в невесомости, как в космосе.

URDF-файл

Если бы робот был человеческим телом, файл URDF был бы скелетом, определяющим его физическую структуру. Он написан на XML и, по сути, представляет собой чертеж машины, определяющий, как будет выглядеть ваш робот и как он будет двигаться.

Я собираюсь показать, как создать простой куб , который является 3D-эквивалентом печати («hello world»).

urdf_string = «»»» «»»

Вы можете сохранить код XLM как файл URDF или использовать его как строку.

import pybullet as p import tempfile ## setup p.connect(p.GUI) p.resetSimulation() p.setGravity(gravX=0, gravY=0, gravZ=-9.8) ## создать временный файл URDF в памяти с помощью tempfile.NamedTemporaryFile(suffix=».urdf», mode=»w», delete=False) as f: f.write(urdf_string) urdf_file = f.name ## загрузить URDF p.loadURDF(fileName=urdf_file, basePosition=[0,0,1]) ## отрисовать симуляцию for _ in range(240): p.stepSimulation()

20676330868aed407de22f58ada81a56

Обратите внимание, что цикл выполнялся с 240 шагами. Почему 240? Это фиксированный временной шаг, обычно используемый в разработке видеоигр для обеспечения плавного и отзывчивого игрового процесса без перегрузки процессора. 60 кадров в секунду (FPS) с отображением одного кадра каждую 1/60 секунды, что означает, что шаг физики в 1/240 секунды обеспечивает 4 обновления физики для каждого отрисованного кадра.

В предыдущем коде я визуализировал куб с помощью p.stepSimulation(). Это означает, что симуляция происходит не в реальном времени, и вы сами управляете моментом выполнения следующего шага физики. В качестве альтернативы можно использовать time sleep для привязки к часам реального мира.

import time ## рендер симуляции для _ в диапазоне (240): p.stepSimulation() #добавление шага физики (скорость ЦП = 0,1 секунды) time.sleep(1/240) #замедление до реального времени (240 шагов × 1/240 секунды, сон = 1 секунда)

756caa92ade8c7ba3f538a2f416317e0

В дальнейшем XML-код для роботов станет значительно сложнее. К счастью, PyBullet поставляется с набором готовых URDF-файлов. Вы можете легко загрузить куб по умолчанию, не создавая для него XML.

импорт pybullet_data p.setAdditionalSearchPath(path=pybullet_data.getDataPath()) p.loadURDF(fileName=»cube.urdf», basePosition=[0,0,1])

По сути, файл URDF определяет два основных элемента: звенья и сочленения . Звенья — это жёсткие части робота (например, наши кости), а сочленение — это соединение двух жёстких звеньев (например, наши мышцы). Без сочленений ваш робот был бы просто статуей, но с сочленениями он становится машиной, обладающей движением и функцией.

Вкратце, каждый робот представляет собой дерево звеньев, соединённых шарнирами. Каждый шарнир может быть неподвижным (неподвижным), вращаться («вращательный шарнир») и скользить («призматический шарнир»). Поэтому вам необходимо знать, какого робота вы используете.

Давайте рассмотрим пример знаменитого робота R2D2 из «Звездных войн».

61713f2f3962bed0f7fa61a8e73c9d45

Суставы

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

## настройка p.connect(p.GUI) p.resetSimulation() p.setGravity(gravX=0, gravY=0, gravZ=-9.8) p.setAdditionalSearchPath(path=pybullet_data.getDataPath()) ## загрузка URDF plane = p.loadURDF(«plane.urdf») robo = p.loadURDF(fileName=»r2d2.urdf», basePosition=[0,0,0.1]) ## рендеринг симуляции для _ в диапазоне (240): p.stepSimulation() time.sleep(1/240) p.disconnect()

e1502b68949d3f7f0ac3dd97c6ae2599

Прежде чем использовать робота, необходимо разобраться в его компонентах. PyBullet стандартизировал структуру данных, чтобы каждый импортируемый робот всегда определялся одними и теми же 17 универсальными атрибутами . Поскольку я хочу просто запустить скрипт, я подключусь к физическому серверу без графического интерфейса (p.DIRECT). Основная функция для анализа сочленения — p.getJointInfo().

p.connect(p.DIRECT) dic_info = { 0:»Индекс сочленения», #начинается с 0 1:»Имя сочленения», 2:»Тип сочленения», #0 = вращательное, 1 = призматическое, 4 = фиксированное 3:»Индекс вектора состояния», 4:»Индекс вектора скорости», 5:»Флаги», #nvm всегда 0 6:»Демпфирование сочленения», 7:»Трение сочленения», #коэффициент 8:»Нижний предел сочленения», #минимальный угол 9:»Верхний предел сочленения», #максимальный угол 10:»Сила сочленения», #максимально допустимая сила 11:»Скорость сочленения», #максимальная скорость 12:»Имя ссылки», #дочерняя ссылка, подключенная к этому сочленению 13:»Ось сочленения», 14:»Положение родительского кадра», #позиция 15:»Возврат родительского кадра», #ориентация 16:»Индекс родительского кадра» #−1 = основание } for i in range(p.getNumJoints(bodyUniqueId=robo)): print(f»— JOINT {i} —«) joint_info = p.getJointInfo(bodyUniqueId=robo, jointIndex=i) print({dic_info[k]:joint_info[k] for k in dic_info.keys()})

f4c8e9e56f32191ab0e7947f941c12e3

Каждый сустав, будь то колесо, локоть или захват, должен обладать теми же свойствами. Код выше показывает, что у R2D2 15 суставов. Давайте проанализируем первый, называемый «от основания к правой ноге»:

  • Тип сочленения — 4, что означает, что оно неподвижно. Родительское звено — -1, что означает, что оно соединено с основанием , корневой частью робота (например, позвоночником нашего скелета). Для R2D2 основание — это основной цилиндрический корпус, большой сине-белый ствол.
  • Название соединения — «правая нога», поэтому мы понимаем, что это сочленение соединяет основание робота с правой ногой, но оно не моторизовано. Это подтверждается нулем в параметрах оси сочленения , амортизации сочленения и трения сочленения .
  • Положение и ориентация родительской рамы определяют, где правая ножка крепится к основанию.

Ссылки

С другой стороны, для анализа связей (сегментов физического тела) необходимо выполнить цикл по сочленениям, чтобы извлечь имя связи. Затем можно использовать две основные функции: p.getDynamicsInfo() для определения физических свойств связи и p.getLinkState() для определения её пространственного состояния.

p.connect(p.DIRECT) for i in range(p.getNumJoints(robo)): link_name = p.getJointInfo(robo, i)[12].decode('utf-8') #field 12=»Имя ссылки» dyn = p.getDynamicsInfo(robo, i) pos, orn, *_ = p.getLinkState(robo, i) dic_info = {«Масса»:dyn[0], «Трение»:dyn[1], «Положение»:pos, «Ориентация»:orn} print(f»— LINK {i}: {link_name} —«) print(dic_info)

134ef26e2d94e9d5a46e2a65992e12f7

Рассмотрим первый элемент, «правую ногу». Масса 10 кг влияет на силу тяжести и инерцию, а трение влияет на степень скольжения при соприкосновении с землёй. Ориентация (0,707 = sin(45°)/cos(45°)) и положение указывают на то, что звено правой ноги представляет собой цельную деталь, слегка выдвинутую вперёд (5 см) и наклонённую на 90° относительно основания.

Движения

Давайте посмотрим на сустав, который действительно может двигаться.

Например, сочленение 2 — это правое переднее колесо. Это сочленение типа 0, поэтому оно вращается. Оно соединяет правую ногу (индекс связи 1) с правым передним колесом: base_link → right_leg → right_front_wheel. Ось сочленения — (0,0,1), поэтому мы знаем, что колесо вращается вокруг оси Z. Пределы (нижний = 0, верхний = -1) указывают на то, что колесо может вращаться бесконечно, что нормально для роторов.

Мы можем легко перемещать это сочленение . Основная команда для управления приводами вашего робота — p.setJointMotorControl2(). Она позволяет контролировать силу, скорость и положение сочленения. В данном случае я хочу, чтобы колесо вращалось, поэтому я буду прилагать силу, чтобы постепенно увеличить скорость от нуля до заданного значения, а затем поддерживать её, балансируя приложенную силу и силы сопротивления (например, трение, демпфирование, гравитацию).

p.setJointMotorControl2(bodyUniqueId=robo, jointIndex=2, controlMode=p.VELOCITY_CONTROL, targetVelocity=10, force=5)

Теперь, если мы приложим одинаковую силу ко всем четырём колёсам , наш маленький робот будет двигаться вперёд. Из проведённого ранее анализа мы знаем, что сочленения для колеса — это сочленения 2 и 3 (правая сторона), а также 6 и 7 (левая сторона).

8b3016d0ea2810a160714d23574328a7

Учитывая это, я сначала заставлю R2D2 развернуться, вращая только одну сторону, а затем приложу силу к каждому колесу одновременно, чтобы заставить его двигаться вперед.

import pybullet as p import pybullet_data import time ## настройка p.connect(p.GUI) p.resetSimulation() p.setGravity(gravX=0, gravY=0, gravZ=-9.8) p.setAdditionalSearchPath(path=pybullet_data.getDataPath()) ## загрузка URDF plane = p.loadURDF(«plane.urdf») robo = p.loadURDF(fileName=»r2d2.urdf», basePosition=[0,0,0.1]) ## стабилизация for _ in range(240): p.stepSimulation() right_wheels = [2,3] left_wheels = [6,7] ### первый поворот for _ in range(240): for j in right_wheels: p.setJointMotorControl2(bodyUniqueId=robo, jointIndex=j, controlMode=p.VELOCITY_CONTROL, targetVelocity=-100, force=50) for j in left_wheels: p.setJointMotorControl2(bodyUniqueId=robo, jointIndex=j, controlMode=p.VELOCITY_CONTROL, targetVelocity=100, force=50) p.stepSimulation() time.sleep(1/240) ### затем двигаться вперед for _ in range(500): for j in right_wheels + left_wheels: p.setJointMotorControl2(bodyUniqueId=robo, jointIndex=j, controlMode=p.VELOCITY_CONTROL, targetVelocity=-100, force=10) p.stepSimulation() time.sleep(1/240) p.disconnect()

885e9366e65de052cfbc7a23a248e85e

Обратите внимание, что каждый робот имеет разную массу (вес), поэтому движения могут отличаться в зависимости от физических условий моделирования (например, гравитации). Вы можете экспериментировать, пробуя разные значения силы и скорости, пока не найдёте желаемый результат.

0a92b3f648ecab3f845e1e79127848e2

Заключение

Эта статья представляет собой руководство по использованию PyBullet и созданию простейших 3D-моделей для робототехники . Мы научились импортировать объекты URDF и анализировать сочленения и звенья. Мы также поработали со знаменитым роботом R2D2. В будущем появятся новые руководства с более продвинутыми роботами.

Полный код для этой статьи: GitHub

Надеюсь, вам понравилось! Обращайтесь ко мне с вопросами и отзывами, а также просто делитесь своими интересными проектами.

👉 Давайте общаться 👈

ce8d744ae62c3400aeea2115a68376cf

(Все изображения принадлежат автору, если не указано иное)

Источник: towardsdatascience.com

✅ Найденные теги: новости, Руководство

ОСТАВЬТЕ СВОЙ КОММЕНТАРИЙ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Фото сгенерированных лиц: исследование показывает, что люди не могут отличить настоящие лица от сгенерированных
Нейросети построили капитализм за трое суток: 100 агентов Claude заперли…
Скетч: цифровой осьминог и виртуальный мир внутри компьютера с человечком.
Сцена с жестами пальцами, где один жест символизирует "VPN", а другой "KHP".
‼️Paramount купила Warner Bros. Discovery — сумма сделки составила безумные…
Скриншот репозитория GitHub "Claude Scientific Skills" AI для научных исследований.
Структура эффективного запроса Claude с элементами задачи, контекста и референса.
Эскиз и готовая веб-страница платформы для AI-дизайна в современном темном режиме.
ideipro logotyp
Image Not Found
Звёздное небо с галактиками и туманностями, космос, Вселенная, астрофотография.

Система оповещения обсерватории Рубина отправила 800 000 сигналов в первую ночь наблюдений.

Астрономы будут получать оповещения о небесных явлениях в течение нескольких минут после их обнаружения. Теренс О'Брайен, редактор раздела «Выходные». Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной…

Мар 2, 2026
Женщина с длинными тёмными волосами в синем свете, нейтральный фон.

Расследование в отношении 61-фунтовой машины, которая «пожирает» пластик и выплевывает кирпичи.

Обзор компактного пресса для мягкого пластика Clear Drop — и что будет дальше. Шон Холлистер, старший редактор Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего…

Мар 2, 2026
Черный углеродное волокно с текстурой плетения, отражающий свет.

Материал будущего: как работает «бессмертный» композит

Учёные из Университета штата Северная Каролина представили композит нового поколения, способный самостоятельно восстанавливаться после серьёзных повреждений.  Речь идёт о модифицированном армированном волокном полимере (FRP), который не просто сохраняет прочность при малом весе, но и способен «залечивать» внутренние…

Мар 2, 2026
Круглый экран с изображением замка и горы, рядом электронная плата.

Круглый дисплей Waveshare для креативных проектов

Круглый 7-дюймовый сенсорный дисплей от Waveshare создан для разработчиков и дизайнеров, которым нужен нестандартный экран.  Это IPS-панель с разрешением 1 080×1 080 пикселей, поддержкой 10-точечного ёмкостного сенсора, оптической склейкой и защитным закалённым стеклом, выполненная в круглом форм-факторе.…

Мар 2, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых