"""A wrapper for pybullet to manage different clients.""" from __future__ import absolute_import from __future__ import division import functools import inspect import pybullet class BulletClient(object): """A wrapper for pybullet to manage different clients.""" def __init__(self, connection_mode=None): """Creates a Bullet client and connects to a simulation. Args: connection_mode: `None` connects to an existing simulation or, if fails, creates a new headless simulation, `pybullet.GUI` creates a new simulation with a GUI, `pybullet.DIRECT` creates a headless simulation, `pybullet.SHARED_MEMORY` connects to an existing simulation. """ self._shapes = {} if connection_mode is None: self._client = pybullet.connect(pybullet.SHARED_MEMORY) if self._client >= 0: return else: connection_mode = pybullet.DIRECT self._client = pybullet.connect(connection_mode) def __del__(self): """Clean up connection if not already done.""" if self._client>=0: try: pybullet.disconnect(physicsClientId=self._client) self._client = -1 except pybullet.error: pass def __getattr__(self, name): """Inject the client id into Bullet functions.""" attribute = getattr(pybullet, name) if inspect.isbuiltin(attribute): if name not in [ "invertTransform", "multiplyTransforms", "getMatrixFromQuaternion", "getEulerFromQuaternion", "computeViewMatrixFromYawPitchRoll", "computeProjectionMatrixFOV", "getQuaternionFromEuler", ]: # A temporary hack for now. attribute = functools.partial(attribute, physicsClientId=self._client) if name=="disconnect": self._client = -1 return attribute