PyBullet 是基于 Bullet Physics SDK 开发的 Python 物理仿真库。具有安装简单、运行高效、功能全面等特点,是机器人仿真和强化学习的首选工具。
核心特点
- 🚀 易于安装:
pip install pybullet一键安装 - ⚡ 高性能:支持实时仿真,可进行 1000+ Hz 的控制循环
- 🌐 跨平台:支持 Windows、Linux、macOS
- 🎯 功能全面:刚体/多体动力学、碰撞检测、约束求解、软体物理
- 👁️ 内置可视化:支持 OpenGL 渲染和合成摄像头
- 🎮 VR 支持:支持 VR 设备与传感器仿真
主要应用
机器人仿真与控制
- 支持导入 URDF/SDF 格式的机器人模型
- 机械臂、足式机器人、无人机仿真
- 逆运动学求解、力矩控制
强化学习环境
- 提供 OpenAI Gym 标准接口
- 预构建环境(AntBulletEnv、HalfCheetahBulletEnv 等)
- 机器人行走、物体操纵等任务学习
其他应用
- 碰撞检测与路径规划
- 游戏物理引擎
- 计算机视觉数据合成
快速开始
1 | import pybullet as p |
与其他引擎对比
| 特性 | PyBullet | Gazebo | MuJoCo |
|---|---|---|---|
| 安装难度 | ⭐ 简单 | ⭐⭐⭐ 复杂 | ⭐⭐ 中等 |
| 运行速度 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Python 支持 | ✅ 优秀 | ✅ 好 | ✅ 好 |
| 开源 | ✅ | ✅ | ❌ |
适用场景
✅ 快速原型设计、强化学习研究、跨平台兼容需求
❌ 需要最高精度物理模拟、完整生态系统
资源
1、createCollisionShape
在 PyBullet 中,createCollisionShape 函数用于定义一个物体的物理边界(碰撞体)。它决定了物体在仿真世界中如何与其他物体发生碰撞、反弹或支撑,但不决定物体的外貌。
通常它需要与 createVisualShape(定义外观)配合使用,最后通过 createMultiBody 合成一个完整的物体。
1. 函数基本语法
p.createCollisionShape(shapeType, radius, halfExtents, height, meshScale, ...)
| 参数名 | 说明 | 示例 |
|---|---|---|
shapeType |
形状类型 | p.GEOM_BOX(方块)、p.GEOM_SPHERE(球体) |
radius |
半径 | 仅用于球体或胶囊体 |
halfExtents |
半长宽高 [x, y, z] |
用于方块。注意是中心到边的距离(即边长的一半) |
height |
高度 | 用于圆柱体或胶囊体 |
meshScale |
缩放比例 | 用于导入的 .obj 或 .stl 网格文件 |
2. shapeType 常用类型:
| 类型 | 说明 |
|---|---|
p.GEOM_BOX |
立方体或长方体 |
p.GEOM_SPHERE |
球体 |
p.GEOM_CYLINDER |
圆柱体 |
p.GEOM_CAPSULE |
胶囊体 |
p.GEOM_MESH |
网格模型 |
2、createVisualShape
在 PyBullet 中,createVisualShape 函数专门用于定义物体的 视觉外观。
简单来说,createCollisionShape 决定了物体“摸起来”是什么样的(物理碰撞),而 createVisualShape 决定了物体“看起来”是什么样的(颜色、纹理、形状)。
1. 函数基本语法
p.createVisualShape(shapeType, radius, halfExtents, length, rgbColor, specularColor, visualFramePosition)
| 参数名 | 说明 | 示例 |
|---|---|---|
shapeType |
形状类型 | p.GEOM_BOX, p.GEOM_SPHERE, p.GEOM_CYLINDER |
radius |
半径 | 用于球体或圆柱体 |
halfExtents |
半长宽高 | 用于方块 [x, y, z] |
length |
长度/高度 | 用于圆柱体或胶囊体 |
rgbColor |
颜色与透明度 | [R, G, B, A],范围 0 到 1。例如 [1, 0, 0, 1] 是纯红 |
specularColor |
高光颜色 | [R, G, B],决定物体表面反光颜色 |
visualFramePosition |
视觉偏移 | 视觉模型相对于质心的偏移位置 [x, y, z] |
3、loadURDF
1. 基本定义
loadURDF 是一个 API 接口,专门用于解析 URDF (Unified Robot Description Format, 统一机器人描述格式) 文件。URDF 是一种基于 XML 的文件格式,详尽地描述了机器人的:
- 外观 (Visual):模型长什么样。
- 物理碰撞形状 (Collision):物体占据的空间体积,用于碰撞检测。
- 关节 (Joints):机械臂或起重机的旋转轴、平移轨道。
- 质量属性 (Inertial):重量是多少,重心在哪里。
2. 函数语法与常用参数
p.loadURDF(fileName, basePosition, baseOrientation, useFixedBase, globalScaling)
| 参数名 | 类型 | 说明 |
|---|---|---|
| fileName | String | URDF 文件的路径(如 "r2d2.urdf")。 |
| basePosition | List | 初始坐标 |
| baseOrientation | List | 初始姿态(四元数)。可以用 p.getQuaternionFromEuler 转换得到。 |
| useFixedBase | Boolean | 关键参数! 设为 True(或 1)时,物体的基座会固定在空间中,不随重力掉落。 |
| globalScaling | Float | 缩放比例。例如 2.0 会让加载出来的模型变大一倍。 |
| flags | Integer | 额外加载选项,如 p.URDF_USE_INERTIA_FROM_FILE 使用 URDF 文件中的惯性数据。 |
3. pybullet中的坐标系
PyBullet 使用右手坐标系:红色表示 X 轴,绿色表示 Y 轴,蓝色表示 Z 轴。默认情况下,Z 轴指向上方,X-Y 平面为地面。
4、flags
flags 参数允许你在加载 URDF 时指定一些额外的选项,以控制加载行为。常用的 flag 包括:
1. 碰撞检测类
| 标志 | 作用描述 |
|---|---|
p.URDF_GEOM_FORCE_CONCAVE_TRIMESH |
强制将网格模型识别为 凹面(Concave)。如果不加,PyBullet 会把模型包裹成一个实心的“凸壳”。 |
p.URDF_USE_SELF_COLLISION |
开启模型内部 Link 之间的碰撞检测。 |
p.URDF_USE_SELF_COLLISION_EXCLUDE_PARENT |
开启自碰撞,但忽略父子连接件之间的碰撞。 |
p.URDF_USE_SELF_COLLISION_EXCLUDE_ALL_PARENTS |
忽略所有祖先节点的碰撞。 |
2. 惯性与动力学类
| 标志 | 作用描述 |
|---|---|
p.URDF_USE_INERTIA_FROM_FILE |
强制使用 URDF 文件中指定的 <inertia> 数据。 |
p.URDF_USE_IMPLICIT_CYLINDER |
将 URDF 中的圆柱体识别为原生圆柱碰撞体,而不是多面体拟合。 |
p.URDF_ENABLE_SLEEPING |
允许静止的物体进入“睡眠”状态,不消耗计算资源。 |
4、setJointMotorControl2
在 PyBullet 中,setJointMotorControl2 是控制机器人运动的核心函数。它允许你为特定的关节 (Joint) 设定控制模式,比如控制它的位置、速度或力矩。
对于你的桥式起重机,无论是控制大车滑行还是小车平移,都要靠这个函数来实现。
函数原型与核心参数
p.setJointMotorControl2(bodyUniqueId, jointIndex, controlMode, targetPosition, targetVelocity, force)
| 参数 | 说明 |
|---|---|
| bodyUniqueId | 模型的 ID(即 loadURDF 返回的 crane_id)。 |
| jointIndex | 关节的索引。大车、小车和吊钩在 URDF 中都有一个唯一的数字编号。 |
| controlMode | 控制模式。常用有 p.POSITION_CONTROL(位置)、p.VELOCITY_CONTROL(速度)。 |
| targetPosition | 目标位置。仅在位置控制模式下有效(例如让小车移动到 2.0 米处)。 |
| targetVelocity | 目标速度。在速度控制模式下,这是你期望达到的恒定速度。 |
| force | 最大驱动力(或力矩)。决定了电机的“力气”,如果力太小,可能拉不动沉重的起重机。 |
5、getNumJoints
1. 函数定义与返回值
getNumJoints(bodyUniqueId)只有一个参数,即你加载模型时获得的 ID(如 crane_id)。它返回一个整数,表示该模型包含的关节(Joint)总数。
1 | # 获取起重机有多少个关节 |
2. 为什么它对你很重要?
在 PyBullet 中,关节的索引(Index)是从 0 到 getNumJoints - 1 的连续整数。你之所以需要这个函数,主要有以下三个原因:
A. 遍历并识别关节
当你从 SolidWorks 导出 URDF 时,大车、小车、吊绳、吊钩各占一个关节。通过 getNumJoints 配合 getJointInfo ,你可以打印出所有关节的名字,从而确定你要控制的那个零件到底是几号。
1 | for i in range(p.getNumJoints(crane_id)): |
6、getJointInfo
1. 函数基本用法
getJointInfo 需要两个核心参数:
- bodyUniqueId:模型的 ID(如
crane_id)。 - jointIndex:关节的索引(从 0 到
getNumJoints-1)。
1 | info = p.getJointInfo(crane_id, 0) |
2. 返回值详解(重点)
该函数返回一个包含 17 个元素的元组。对于起重机仿真,最关键的参数如下:
| 索引 | 名称 | 说明 |
|---|---|---|
| 0 | jointIndex |
关节索引(与输入一致)。 |
| 1 | jointName |
关节名称(如 "trolley_joint"),用于识别大车还是小车。 |
| 2 | jointType |
关节类型(平移、旋转、固定等)。 |
| 8 | jointLowerLimit |
关节下限位(比如轨道的最左端)。 |
| 9 | jointUpperLimit |
关节上限位(比如轨道的最右端)。 |
| 12 | linkName |
该关节所连接的子连杆名称。 |
3. 识别关节类型(jointType)
通过 info[2],你可以判断起重机的各个部件是如何运动的:
- p.JOINT_PRISMATIC (1):平移关节。大车、小车的滑动通常属于这一类。
- p.JOINT_REVOLUTE (0):旋转关节。有角度限位,常用于模拟吊绳的摆动。
- p.JOINT_FIXED (4):固定关节。不可移动,通常用于连接装饰性零件。
- p.JOINT_SPHERICAL (3):球型关节。可以在三个方向旋转。
- 本文作者: Apezer
- 本文链接: http://example.com/2026/01/27/pybullet简介/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!
