createCollisionShape sometimes fails
LucaBonfiglioli opened this issue · comments
Hello, I am currently writing a software that should physically simulate objects falling on various types of containers, and to achieve this we decided to use pybullet
binding for bullet3.
I am currently stuck on this situation: 99.99% of the time the code runs smoothly, the simulation result is reasonable and its actually pretty fast. The remaining 0.01% of the time, the program crashes with the following error:
pybullet.error: createCollisionShape failed.
No other information is provided, which makes this very hard for me to debug.
This occurs randomly, and I still haven't figured out a way to replicate this. This is especially annoying because our runs are usually tens of thousands of simulations and can take hours, and I have to manually implement a fallback mechanism in case pybullet decides to stop working.
I cannot provide you an exact copy of my source code, so I have this (non-working) snippet to show you what I am doing. Some parts are omitted, others are simplified and many parameters are simply hardcoded to keep things simple.
import pybullet as pb
class PyBulletPhysicsProcessor:
def __init__(self) -> None:
self._pb_client = None
def process(self):
if self._pb_client is None:
self._pb_client = pb.connect(pb.DIRECT)
my_list_of_objects = [...] # A list of objects to load into the simulation
gravity = 9.81
dt = 1 / 100
steps = 10000
# Set the simulation parameters
pb.setGravity(0, 0, gravity, physicsClientId=self._pb_client)
pb.setTimeStep(dt, physicsClientId=self._pb_client)
obj_ids = []
# Import the objects into the simulation
for obj in my_list_of_objects:
# [OMITTED] Retrieve information about the object to load
fileobj = ... # A string with an absolute path to a .obj file
translation = ... # A 3D XYZ vector
rotation = ... # A quaternion
mass = ... # A float
# Import the object into the simulation
pb_obj = pb.createCollisionShape(
shapeType=pb.GEOM_MESH,
fileName=fileobj,
physicsClientId=self._pb_client,
)
pb_obj_id = pb.createMultiBody(
baseMass=mass,
baseCollisionShapeIndex=pb_obj,
basePosition=translation,
baseOrientation=rotation,
physicsClientId=self._pb_client,
)
# Save the object ID
obj_ids.append(pb_obj_id)
# Run the simulation
for _ in range(steps):
pb.stepSimulation(physicsClientId=self._pb_client)
# Get the final object poses
for obj, obj_id in zip(my_list_of_objects, obj_ids):
# Get the object pose
translation, rotation = pb.getBasePositionAndOrientation(
obj_id, physicsClientId=self._pb_client
)
# [OMITTED] Do stuff with the object pose
...
# Clear the scene
pb.resetSimulation(physicsClientId=self._pb_client)
Some observations that may help:
- The first simulation seems to have a higher failure chance. I would say, 30% of the times it fails, it does so on the first call to
createCollisionShape
. - The issue also occurs with both single and multi-processing.
- When using a high number of concurrent workers (>=16) the problem is even more likely to occur.
- I tested this on four different machines with completely different hardware and software stacks, same exact behavior.
- After the first call fails:
- The client is still connected to the server.
- All subsequent calls to
createCollisionShape
fail too, but not other pybullet3 methods. - The other workers are competely fine.
- Workers fail randomly even though the method is called with the exact same input file.
Reproduced this bug on:
- Ubuntu 18.04 / 20.04 / 22.04
- Python 3.8 / 3.9 / 3.10