import pybullet as p # 导入 PyBullet 模块
import time # 导入 time 模块,用于延时操作
import pybullet_data # 导入 PyBullet 数据目录模块,用于设置 PyBullet 数据路径
p.connect(p.GUI) # 连接 PyBullet GUI
p.setAdditionalSearchPath(pybullet_data.getDataPath()) # 设置 PyBullet 数据路径
planeId = p.loadURDF("plane.urdf", useMaximalCoordinates=False) # 加载地面 URDF 模型
cubeId = p.loadURDF("cube_collisionfilter.urdf", [0, 0, 3], useMaximalCoordinates=False) # 加载正方体 URDF 模型
collisionFilterGroup = 0 # 设置碰撞过滤器分组
collisionFilterMask = 0 # 设置碰撞过滤器掩码
p.setCollisionFilterGroupMask(cubeId, -1, collisionFilterGroup, collisionFilterMask) # 设置物体的碰撞过滤器分组和掩码
enableCollision = 1 # 启用碰撞检测
p.setCollisionFilterPair(planeId, cubeId, -1, -1, enableCollision) # 启用平面和物体之间的碰撞检测
p.setRealTimeSimulation(1) # 开启实时仿真
p.setGravity(0, 0, -10) # 设置重力方向和大小
while (p.isConnected()): # 进入 PyBullet 循环
time.sleep(1. / 240.) # 每次循环暂停 1/240 秒,避免过度渲染
p.setGravity(0, 0, -10) # 设置重力方向和大小
planeId = p.loadURDF("plane.urdf", useMaximalCoordinates=False)
useMaximalCoordinates
是 PyBullet 中 loadURDF()
方法的一个可选参数,它用于控制 URDF 模型文件中的坐标系转换方式。具体地说,如果把 useMaximalCoordinates
设置为 True
,则 PyBullet 会执行更多的坐标系转换和优化操作,以最大限度地减少运动学和动力学计算的误差,并提高仿真的准确性和稳定性。但是,这会增加计算负担和内存占用。
如果将 useMaximalCoordinates
设置为 False
,则 PyBullet 会执行更少的坐标系转换,以减少计算负担和内存占用。但是,这样可能会降低仿真的准确性和稳定性。
p.setCollisionFilterGroupMask()
该函数是 PyBullet 中用于设置物体碰撞过滤器的函数。它的完整语法为:
p.setCollisionFilterGroupMask(bodyUniqueId, linkIndex, collisionFilterGroup, collisionFilterMask, physicsClientId=0)
其中,`bodyUniqueId` 表示物体的唯一 ID,`linkIndex` 是需要设置的链接索引。如果物体只有一个链接,则 `linkIndex` 应该为 -1。`collisionFilterGroup` 和 `collisionFilterMask` 分别表示要执行碰撞检测的两个物体的碰撞过滤器组和掩码。`physicsClientId` 参数是可选的,用于在多个 PyBullet 实例之间指定客户端 ID。
这个函数用于设置物体的碰撞过滤器。在 PyBullet 中,我们可以通过设置碰撞过滤器控制物体与其他物体的碰撞,以实现仿真中的各种效果。
具体地说,当一个物体与另一个物体进行碰撞检测时,PyBullet 会比较这两个物体的碰撞过滤器组和掩码,如果它们匹配,则检测碰撞,否则忽略碰撞。因此,我们可以通过设置不同的碰撞过滤器组和掩码,来控制物体与其他物体之间的碰撞关系。
在使用 `p.setCollisionFilterGroupMask()` 函数时,我们可以根据具体的需求设置不同的碰撞过滤器组和掩码,从而实现不同的碰撞关系。例如,我们可以把一个物体的碰撞过滤器设置为与另一个物体的碰撞过滤器不匹配,这样可以防止它们之间的碰撞。
例如:
假设我们有两个立方体,一个红色立方体和一个蓝色立方体,它们的碰撞过滤器组和掩码分别为:
- 红色立方体:碰撞过滤器组为 1,碰撞掩码为 1。
- 蓝色立方体:碰撞过滤器组为 2,碰撞掩码为 2。
如果我们把红色立方体的碰撞过滤器组设置为 2,碰撞掩码设置为 2,这时红色立方体就不会与蓝色立方体进行碰撞了。因为它们的碰撞过滤器不匹配,PyBullet 会忽略它们之间的碰撞。代码如下:
# 创建红色立方体和蓝色立方体
cube1Id = p.createCollisionShape(p.GEOM_BOX, halfExtents=[0.5, 0.5, 0.5])
cube2Id = p.createCollisionShape(p.GEOM_BOX, halfExtents=[0.5, 0.5, 0.5])
red_color = [1, 0, 0, 1] # 红色
blue_color = [0, 0, 1, 1] # 蓝色
cube1 = p.createMultiBody(baseCollisionShapeIndex=cube1Id, basePosition=[0, 0, 0.5], baseColor=red_color)
cube2 = p.createMultiBody(baseCollisionShapeIndex=cube2Id, basePosition=[1, 0, 0.5], baseColor=blue_color)
# 设置碰撞过滤器,使红色立方体不会和蓝色立方体碰撞
p.setCollisionFilterGroupMask(cube1, -1, 2, 2)
运行代码后,我们可以看到红色立方体和蓝色立方体都出现在了仿真环境中,但它们不会发生碰撞,因为红色立方体与蓝色立方体的碰撞过滤器不匹配。
p.setCollisionFilterPair(planeId, cubeId, -1, -1, enableCollision)
这是一个设置碰撞过滤器的函数。它的作用是让两个物体之间产生或不产生碰撞。具体来说,它的参数含义如下:
planeId
:表示一个物体的 ID,它将参与碰撞过滤器设置;cubeId
:表示另一个物体的 ID,同样将参与碰撞过滤器设置;-1
:表示默认的碰撞过滤器组和掩码,如果使用了其他值,则会定义自定义的碰撞过滤器组和掩码;enableCollision
:一个布尔值,表示是否启用碰撞。如果为True
,则两个物体之间将产生碰撞,如果为False
,则两个物体之间将不会产生碰撞。