pip install pybullet★Ships the Bullet engine. On Apple Silicon, if the build fails, use thepybullet-arm64drop-in fork.import pybullet as p cid = p.connect(p.GUI) # windowed viewer★p.GUIopens a 3D window;p.DIRECTruns headless (no rendering — use for training/servers). Returns a physics-client id.p.disconnect()Tear down the server. AlsoSHARED_MEMORY,TCP,UDPconnect modes for external servers.# headless training? use p.DIRECT — GUI is slow and needs a displaytipFor RL rollouts runDIRECT; render only when you need to watch. Multiple sims = multipleconnect()ids passed viaphysicsClientId=.
import pybullet_data p.setAdditionalSearchPath(pybullet_data.getDataPath())★Add the bundled asset path so you can load stock URDFs (plane.urdf,r2d2.urdf, KUKA, etc.) by name.p.setGravity(0, 0, -9.81) plane = p.loadURDF("plane.urdf")★Gravity is in m/s² along Z. A ground plane is the usual first body.p.setTimeStep(1/240) # default is 1/240 s★The physics timestep. ⚠️ 1/240 is the tuned default — changing it affects stability; prefer more substeps over a big timestep.p.resetSimulation() · p.setPhysicsEngineParameter(numSolverIterations=50)Wipe the world; tune the solver (iterations, ERP, contact params) for accuracy vs speed.
robot = p.loadURDF("r2d2.urdf", basePosition=[0,0,1], baseOrientation=p.getQuaternionFromEuler([0,0,0]))★Load an articulated body from URDF. Returns a body id you pass to every later call. Orientations are quaternions (x,y,z,w).p.loadURDF("model.urdf", useFixedBase=True, flags=p.URDF_USE_SELF_COLLISION)useFixedBasepins the base (e.g. a table-mounted arm). Flags toggle self-collision, inertia-from-file, etc.p.loadSDF("world.sdf") · p.loadMJCF("model.xml")Also loads SDF worlds and MuJoCo MJCF models (each returns a list of body ids).p.getQuaternionFromEuler([r,p_,y]) · p.getEulerFromQuaternion(q)Convert between Euler angles and quaternions — you'll do this constantly.
col = p.createCollisionShape(p.GEOM_BOX, halfExtents=[.5,.5,.5]) vis = p.createVisualShape(p.GEOM_BOX, halfExtents=[.5,.5,.5], rgbaColor=[1,0,0,1])★Build primitives in code:GEOM_BOX,GEOM_SPHERE,GEOM_CYLINDER,GEOM_CAPSULE,GEOM_MESH.body = p.createMultiBody(baseMass=1, baseCollisionShapeIndex=col, baseVisualShapeIndex=vis, basePosition=[0,0,2])★createMultiBodyassembles shapes into a dynamic body — the way to spawn objects without a URDF file.p.changeDynamics(body, -1, lateralFriction=0.8, restitution=0.2)Tune per-link physics: mass, friction, bounciness, damping. Link index-1= the base.