PyBullet Quickstart Guide
PyBullet Quickstart Guide
PyBullet Quickstart Guide
resetSimulation
33
34
startStateLogging/stopStateLogging 34
Quickstart Guide Synthetic Camera Rendering 37
Erwin Coumans, Yunfei Bai, 2016-2019 computeViewMatrix 37
Visit desktop doc, forums and star Bullet!
computeProjectionMatrix 38
Introduction 2 getCameraImage 38
Hello PyBullet World 3 getVisualShapeData 40
connect, disconnect 3 changeVisualShape, loadTexture 41
setGravity 6
Collision Detection Queries 42
loadURDF, loadSDF, loadMJCF 7
getOverlappingObjects, getAABB 42
saveWorld 9
getContactPoints, getClosestPoints 43
saveState, saveBullet, restoreState 10
rayTest, rayTestBatch 45
createCollisionShape/VisualShape 10
getCollisionShapeData 46
createMultiBody 13
Enable/Disable Collisions 47
stepSimulation 14
setRealTimeSimulation 15 Inverse Dynamics, Kinematics 48
getBasePositionAndOrientation 15 calculateInverseDynamics 48
resetBasePositionAndOrientation 16 calculateJacobian, MassMatrix 48
Transforms: Position and Orientation 16 calculateInverseKinematics(2) 50
getAPIVersion 18
Reinforcement Learning Gym Envs 53
Controlling a robot 18 Environments and Data 53
Base, Joints, Links 18 Train and Enjoy: DQN, PPO, ES 56
getNumJoints, getJointInfo 19
Virtual
setJointMotorControl2/Array 20 RealityresetBasePositionAndOrientation
getJointState(s), resetJointState 23 59
enableJointForceTorqueSensor 24 getVREvents,setVRCameraState 59
getLinkState 24
Debug GUI, Lines, Text, Parameters 61
getBaseVelocity, resetBaseVelocity 26
addUserDebugLine, Text 61
applyExternalForce/Torque 27
addUserDebugParameter 62
getNumBodies, getBodyInfo,
addUserData 64
getBodyUniqueId, removeBody 27
configureDebugVisualizer 64
createConstraint, removeConstraint,
changeConstraint 28 get/resetDebugVisualizerCamera 64
getNumConstraints, getKeyboardEvents, getMouseEvents 65
getConstraintUniqueId 29
Plugins 67
getConstraintInfo/State 30
loadPlugin,executePluginCommand 67
getDynamicsInfo/changeDynamics 30
setTimeStep 32 Build and install PyBullet 68
2
Introduction
PyBullet is an easy to use Python module for physics simulation for robotics, games, visual
effects and machine learning, with a focus on sim-to-real transfer. With PyBullet you can load
articulated bodies from URDF, SDF, MJCF and other file formats. PyBullet provides forward
dynamics simulation, inverse dynamics computation, forward and inverse kinematics, collision
detection and ray intersection queries. The Bullet Physics SDK includes PyBullet robotic
examples such as a simulated Minitaur quadruped, humanoids running using TensorFlow
inference and KUKA arms grasping objects.
Aside from physics simulation, there are bindings to rendering, with a CPU renderer
(TinyRenderer) and OpenGL visualization and support for Virtual Reality headsets such as HTC
Vive and Oculus Rift. PyBullet also has functionality to perform collision detection queries
(closest points, overlapping pairs, ray intersection test etc) and to add debug rendering (debug
lines and text). PyBullet has cross-platform built-in client-server support for shared memory,
UDP and TCP networking. So you can run PyBullet on Linux connecting to a Windows VR
server.
PyBullet wraps the new Bullet C-API, which is designed to be independent from the underlying
physics engine and render engine, so we can easily migrate to newer versions of Bullet, or use
a different physics engine or render engine. By default, PyBullet uses the Bullet 2.x API on the
CPU. We will expose Bullet 3.x running on GPU using OpenCL as well. There is also a C++ API
similar to PyBullet, see b3RobotSimulatorClientAPI.
PyBullet can be easily used with TensorFlow and frameworks such as OpenAI Gym.
Researchers from Google Brain [1,2,3,4], X, Stanford AI Lab [1,2,3], OpenAI,INRIA [1] and other
labs use PyBullet/Bullet C-API. If you use PyBullet in your research, please add a citation.
3
The installation of PyBullet is as simple as (sudo) pip install PyBullet (Python 2.x), pip3 install
PyBullet. This will expose the PyBullet module as well as PyBullet_envs Gym environments.
import pybullet as p
import time
import pybullet_data
physicsClient = p.connect(p.GUI)#or p.DIRECT for non-graphical version
p.setAdditionalSearchPath(pybullet_data.getDataPath()) #optionally
p.setGravity(0,0,-10)
planeId = p.loadURDF("plane.urdf")
cubeStartPos = [0,0,1]
cubeStartOrientation = p.getQuaternionFromEuler([0,0,0])
boxId = p.loadURDF("r2d2.urdf",cubeStartPos, cubeStartOrientation)
for i in range (10000):
p.stepSimulation()
time.sleep(1./240.)
cubePos, cubeOrn = p.getBasePositionAndOrientation(boxId)
print(cubePos,cubeOrn)
p.disconnect()
connect, disconnect
After importing the PyBullet module, the first thing to do is 'connecting' to the physics simulation.
PyBullet is designed around a client-server driven API, with a client sending commands and a
physics server returning the status. PyBullet has some built-in physics servers: DIRECT and
GUI. Both GUI and DIRECT connections will execute the physics simulation and rendering in
the same process as PyBullet.
Note that in DIRECT mode you cannot access the OpenGL and VR hardware features, as
described in the "Virtual Reality" and "Debug GUI, Lines, Text, Parameters" chapters. DIRECT
mode does allow rendering of images using the built-in software renderer through the
'getCameraImage' API. This can be useful for running simulations in the cloud on servers
without GPU.
You can provide your own data files, or you can use the PyBullet_data package that ships with
PyBullet. For this, import pybullet_data and register the directory using
pybullet.setAdditionalSearchPath(pybullet_data.getDataPath()).
4
getConnectionInfo
Given a physicsClientId will return the list [isConnected, connectionMethod]
Diagram with various physics client (blue) and physics server (green) options. Dark green
servers provide OpenGL debug visualization.
The GUI connection will create a new graphical user interface (GUI) with 3D OpenGL rendering,
within the same process space as PyBullet. On Linux and Windows this GUI runs in a separate
thread, while on OSX it runs in the same thread due to operating system limitations. On Mac
OSX you may see a spinning wheel in the OpenGL Window, until you run a 'stepSimulation' or
other PyBullet command.
The commands and status messages are sent between PyBullet client and the GUI physics
simulation server using an ordinary memory buffer.
It is also possible to connect to a physics server in a different process on the same machine or
on a remote machine using SHARED_MEMORY, UDP or TCP networking. See the section
about Shared Memory, UDP and TCP for details.
5
Unlike almost all other methods, this method doesn't parse keyword arguments, due to
backward compatibility.
required connection mode integer: DIRECT mode create a new physics engine and directly
DIRECT, communicates with it. GUI will create a physics engine with
GUI, graphical GUI frontend and communicates with it.
SHARED_ SHARED_MEMORY will connect to an existing physics engine
MEMORY, process on the same machine, and communicates with it over
UDP, TCP shared memory. TCP or UDP will connect to an existing
physics server over TCP or UDP networking.
optional UdpNetworkAddress string IP address or host name, for example "127.0.0.1" or "localhost"
(UDP and TCP) or "mymachine.domain.com"
optional UdpNetworkPort integer UDP port number. Default UDP port is 1234, default TCP port
(UDP and TCP) is 6667 (matching the defaults in the server)
optional options string command-line option passed into the GUI server. At the
moment, only the --opengl2 flag is enabled: by default, Bullet
uses OpenGL3, but some environments such as virtual
machines or remote desktop clients only support OpenGL2.
Only one command-line argument can be passed on at the
moment.
connect returns a physics client id or -1 if not connected. The physics client Id is an optional
argument to most of the other PyBullet commands. If you don't provide it, it will assume physics
client id = 0. You can connect to multiple different physics servers, except for GUI.
For example:
pybullet.connect(pybullet.DIRECT)
pybullet.connect(pybullet.GUI, options="--opengl2")
pybullet.connect(pybullet.SHARED_MEMORY,1234)
pybullet.connect(pybullet.UDP,"192.168.0.1")
pybullet.connect(pybullet.UDP,"localhost", 1234)
pybullet.connect(pybullet.TCP,"localhost", 6667)
Browser has one example under Experimental/Physics Server that allows shared memory
connection. This will let you execute the physics simulation and rendering in a separate
process.
You can also connect over shared memory to the App_SharedMemoryPhysics_VR, the Virtual
Reality application with support for head-mounted display and 6-dof tracked controllers such as
HTC Vive and Oculus Rift with Touch controllers. Since the Valve OpenVR SDK only works
properly under Windows, the App_SharedMemoryPhysics_VR can only be build under Windows
using premake (preferably) or cmake.
For UDP networking, there is a App_PhysicsServerUDP that listens to a certain UDP port. It
uses the open source enet library for reliable UDP networking. This allows you to execute the
physics simulation and rendering on a separate machine. For TCP PyBullet uses the clsocket
library. This can be useful when using SSH tunneling from a machine behind a firewall to a
robot simulation. For example you can run a control stack or machine learning using PyBullet on
Linux, while running the physics server on Windows in Virtual Reality using HTC Vive or Rift.
There is also a GRPC client and server support, which is not enabled by default. You can try it
out using the premake4 build system using the --enable_grpc option (see
Bullet/build3/premake4).
Note: at the moment, both client and server need to be either 32bit or 64bit builds!
disconnect
You can disconnect from a physics server, using the physics client Id returned by the connect
call (if non-negative). A 'DIRECT' or 'GUI' physics server will shutdown. A separate
(out-of-process) physics server will keep on running. See also 'resetSimulation' to remove all
items.
Parameters of disconnect:
optional physicsClientId int if you connect to multiple physics servers, you can pick which one.
7
setGravity
By default, there is no gravitational force enabled. setGravity lets you set the default gravity
force for all objects.
The setGravity input parameters are: (no return value)
optional physicsClientId int if you connect to multiple physics servers, you can pick which one.
Important note: most joints (slider, revolute, continuous) have motors enabled by default that
prevent free motion. This is similar to a robot joint with a very high-friction harmonic drive. You
should set the joint motor control mode and target settings using pybullet.setJointMotorControl2.
See the setJointMotorControl2 API for more information.
Warning: by default, PyBullet will cache some files to speed up loading. You can disable file
caching using setPhysicsEngineParameter(enableFileCaching=0).
required fileName string a relative or absolute path to the URDF file on the file
system of the physics server.
optional basePosition vec3 create the base of the object at the specified position in
world space coordinates [X,Y,Z]
optional baseOrientation vec4 create the base of the object at the specified orientation
as world space quaternion [X,Y,Z,W]
optional useMaximalCoordinates int Experimental. By default, the joints in the URDF file are
created using the reduced coordinate method: the joints
are simulated using the Featherstone Articulated Body
8
optional useFixedBase int force the base of the loaded object to be static
optional flags int The following flags can be combined using a logical
OR:
URDF_USE_INERTIA_FROM_FILE: by default, Bullet
recomputed the inertia tensor based on mass and
volume of the collision shape. If you can provide more
accurate inertia tensor, use this flag.
URDF_USE_SELF_COLLISION_INCLUDE_PARENT
will enable collision between child and parent, it is
disabled by default. Needs to be used together with
URDF_USE_SELF_COLLISION flag.
URDF_USE_SELF_COLLISION_EXCLUDE_ALL_PAR
ENTS will discard self-collisions between a child link
and any of its ancestors (parents, parents of parents,
up to the base). Needs to be used together with
URDF_USE_SELF_COLLISION.
URDF_USE_MATERIAL_COLORS_FROM_MTL, will
use the RGB color from the Wavefront OBJ file, instead
of from the URDF file.
URDF_ENABLE_CACHED_GRAPHICS_SHAPES, will
cache and re-use graphics shapes. It will improve
loading performance for files with similar graphics
assets.
optional globalScaling float globalScaling will apply a scale factor to the URDF
model.
optional physicsClientId int if you are connected to multiple servers, you can pick
one.
9
loadURDF returns a body unique id, a non-negative integer value. If the URDF file cannot be
loaded, this integer will be negative and not a valid body unique id.
By default, loadURDF will use a convex hull for mesh collision detection. For static (mass = 0,
not moving) meshes, you can make the mesh concave by adding a tag in the URDF:
<link concave="yes" name="baseLink"> see samurai.urdf for an example. There are some other
extensions to the URDF format, you can browser the examples to explore. PyBullet doesn't
process all information from a URDF file. See the examples and URDF files to get an idea what
features are supported. Usually there is a Python API to replace the compensate for lacking
URDF support. Each link can only have a single material, so if you have multiple visual shapes
with different materials, you need to split them into separate links, connected by fixed joints. You
can use the OBJ2SDF utility to do this, part of Bullet.
loadSDF, loadMJCF
You can also load objects from other file formats, such as .bullet, .sdf and .mjcf. Those file
formats support multiple objects, so the return value is a list of object unique ids. The SDF
format is explained in detail at http://sdformat.org. The loadSDF command only extracts some
essential parts of the SDF related to the robot models and geometry, and ignores many
elements related to cameras, lights and so on. The loadMJCF command performs basic import
of MuJoCo MJCF xml files, used in OpenAI Gym. See also the Important note under loadURDF
related to default joint motor settings, and make sure to use setJointMotorControl2.
required fileName string a relative or absolute path to the URDF file on the file
system of the physics server.
optional globalScaling float globalScaling is supported for SDF and URDF, not for
MJCF. Every object will be scaled using this scale factor
(including links, link frames, joint attachments and linear joint
limits)
optional physicsClientId int if you are connected to multiple servers, you can pick one.
loadBullet, loadSDF and loadMJCF will return an array of object unique ids:
objectUniqueIds list of int the list includes the object unique id for each object loaded.
10
saveWorld
You can create an approximate snapshot of the current world as a PyBullet Python file, stored
on the server. saveWorld can be useful as a basic editing feature, setting up the robot, joint
angles, object positions and environment for example in VR. Later you can just load the
PyBullet Python file to re-create the world. The python snapshot contains loadURDF commands
together with initialization of joint angles and object transforms. Note that not all settings are
stored in the world file.
optional clientServerId int if you are connected to multiple servers, you can pick one
The saveState command only takes an optional clientServerId as input and returns the state id.
The saveBullet command will save the state to a .bullet file on disk.
The restoreState command input arguments are:
optional fileName string filename of the .bullet file created using a saveBullet command.
optional clientServerId int if you are connected to multiple servers, you can pick one
Either the filename or state id needs to be valid. Note that restoreState will reset the positions
and joint angles of objects to the saved state, as well as restoring contact point information. You
need to make sure the objects and constraints are setup before calling restoreState. See the
saveRestoreState.py example.
11
createCollisionShape/VisualShape
Although the recommended and easiest way to create stuff in the world is using the loading
functions (loadURDF/SDF/MJCF/Bullet), you can also create collision and visual shapes
programmatically and use them to create a multi body using createMultiBody. See the
createMultiBodyLinks.py and createVisualShape.py example in the Bullet Physics SDK.
optional fileName string Filename for GEOM_MESH, currently only Wavefront .obj. Will create
convex hulls for each object (marked as 'o') in the .obj file.
optional collisionFrameP vec3 translational offset of the collision shape with respect to the link frame
osition
optional collisionFrameOr vec4 rotational offset (quaternion x,y,z,w) of the collision shape with respect
ientation to the link frame
optional physicsClientId int If you are connected to multiple servers, you can pick one.
The return value is a non-negative int unique id for the collision shape or -1 if the call failed.
createVisualShape
You can create a visual shape in a similar way to creating a collision shape, with some
additional arguments to control the visual appearance, such as diffuse and specular color.
When you use the G EOM_MESH type, you can point to a Wavefront OBJ file, and the visual
12
shape will parse some parameters from the material file (.mtl) and load a texture. Note that large
textures (above 1024x1024 pixels) can slow down the loading and run-time performance.
optional halfExtents vec3 list of 3 floats default [1,1,1]: only for GEOM_BOX
optional planeNormal vec3 list of 3 floats default: [0,0,1] only for GEOM_PLANE
optional rgbaColor vec4, list of 4 color components for red, green, blue and alpha, each in
floats range [0..1].
optional specularColor vec3, list of 3 specular reflection color, red, green, blue components in
floats range [0..1]
optional visualFramePosition vec3, list of 3 translational offset of the visual shape with respect to the
floats link frame
optional vertices list of vec3 Instead of creating a mesh from obj file, you can provide
13
optional normals list of vec3 vertex normals, number should be equal to number of
vertices.
optional visualFrameOrientati vec4, list of 4 rotational offset (quaternion x,y,z,w) of the visual shape
on floats with respect to the link frame
optional physicsClientId int If you are connected to multiple servers, you can pick
one.
The return value is a non-negative int unique id for the visual shape or -1 if the call failed.
See createVisualShape, createVisualShapeArray a nd createTexturedMeshVisualShape
examples.
createMultiBody
Although the easiest way to create stuff in the world is using the loading functions
(loadURDF/SDF/MJCF/Bullet), you can create a multi body using createMultiBody.
See the createMultiBodyLinks.py example in the Bullet Physics SDK. The parameters of
createMultiBody are very similar to URDF and SDF parameters.
You can create a multi body with only a single base without joints/child links or you can create a
multi body with joints/child links. If you provide links, make sure the size of every list is the same
(len(linkMasses) == len(linkCollisionShapeIndices) etc). The input parameters for createMultiBody are:
optional basePosition vec3, list of 3 floats Cartesian world position of the base
optional baseInertialFrameOrientation vec4, list of 4 floats Local orientation of inertial frame, [x,y,z,w]
optional linkMasses list of float List of the mass values, one for each link.
optional linkCollisionShapeIndices list of int List of the unique id, one for each link.
optional linkVisualShapeIndices list of int list of the visual shape unique id for each link
optional linkPositions list of vec3 list of local link positions, with respect to parent
optional linkOrientations list of vec4 list of local link orientations, w.r.t. parent
optional linkInertialFramePositions list of vec3 list of local inertial frame pos. in link frame
optional linkInertialFrameOrientations list of vec4 list of local inertial frame orn. in link frame
optional linkParentIndices list of int Link index of the parent link or 0 for the base.
optional linkJointTypes list of int list of joint types, one for each link. Only
JOINT_REVOLUTE, JOINT_PRISMATIC, and
JOINT_FIXED is supported at the moment.
optional batchPositions list of vec3 array of base positions, for fast batch creation of
many multibodies.See example.
optional physicsClientId int If you are connected to multiple servers, you can
pick one.
stepSimulation
stepSimulation will perform all the actions in a single forward dynamics simulation step such as
collision detection, constraint solving and integration. The default timestep is 1/240 second, it
can be changed using the setTimeStep or setPhysicsEngineParameter API.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
See also setRealTimeSimulation to automatically let the physics server run forward dynamics
simulation based on its real-time clock.
setRealTimeSimulation
By default, the physics server will not step the simulation, unless you explicitly send a
'stepSimulation' command. This way you can maintain control determinism of the simulation. It
is possible to run the simulation in real-time by letting the physics server automatically step the
simulation according to its real-time-clock (RTC) using the setRealTimeSimulation command. If
you enable the real-time simulation, you don't need to call 'stepSimulation'.
Note that setRealTimeSimulation has no effect in DIRECT mode: in DIRECT mode the physics
server and client happen in the same thread and you trigger every command. In GUI mode and
in Virtual Reality mode, and TCP/UDP mode, the physics server runs in a separate thread from
the client (PyBullet), and setRealTimeSimulation allows the physicsserver thread to add
additional calls to stepSimulation.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
getBasePositionAndOrientation
16
getBasePositionAndOrientation reports the current position and orientation of the base (or root
link) of the body in Cartesian world coordinates. The orientation is a quaternion in [x,y,z,w]
format.
optional physicsClientId int if you are connected to multiple servers, you can pick
one.
See also resetBasePositionAndOrientation to reset the position and orientation of the object.
This completes the first PyBullet script. Bullet ships with several URDF files in the Bullet/data
folder.
resetBasePositionAndOrientation
You can reset the position and orientation of the base (root) of each object. It is best only to do
this at the start, and not during a running simulation, since the command will override the effect
of all physics simulation. The linear and angular velocity is set to zero. You can use
resetBaseVelocity to reset to a non-zero linear and/or angular velocity.
required posObj vec3 reset the base of the object at the specified position in world
space coordinates [X,Y,Z]
required ornObj vec4 reset the base of the object at the specified orientation as world
space quaternion [X,Y,Z,W]
optional physicsClientId int if you are connected to multiple servers, you can pick one.
[yaw, pitch, roll] or 3x3 matrices. PyBullet provides a few helper functions to convert between
quaternions, euler angles and 3x3 matrices. In additions there are some functions to multiply
and invert transforms.
getQuaternionFromEuler and g
etEulerFromQuaternion
The PyBullet API uses quaternions to represent orientations. Since quaternions are not very
intuitive for people, there are two APIs to convert between quaternions and Euler angles.
The getQuaternionFromEuler input arguments are:
required eulerAngle vec3: list of 3 The X,Y,Z Euler angles are in radians, accumulating 3 rotations
floats expressing the roll around the X, pitch around Y and yaw around
the Z axis.
getEulerFromQuaternion
getMatrixFromQuaternion
getMatrixFromQuaternion is a utility API to create a 3x3 matrix from a quaternion. The input is a
quaternion and output a list of 9 floats, representing the matrix.
multiplyTransforms, invertTransform
PyBullet provides a few helper functions to multiply and inverse transforms. This can be helpful
to transform coordinates from one to the other coordinate system.
The output of invertTransform is a position (vec3) and orientation (vec4, quaternion x,y,x,w).
getAPIVersion
You can query for the API version in a year-month-0-day format. You can only connect between
physics client/server of the same API version, with the same number of bits (32-bit / 64bit).
There is a optional unused argument physicsClientId, added for API consistency.
Controlling a robot
In the Introduction we already showed how to initialize PyBullet and load some objects. If you
replace the file name in the loadURDF command with "r2d2.urdf" you can simulate a R2D2
robot from the ROS tutorial. Let's control this R2D2 robot to move, look around and control the
gripper. For this we need to know how to access its joint motors.
A simulated robot as described in a URDF file has a base, and optionally links connected by
joints. Each joint connects one parent link to a child link. At the root of the hierarchy there is a
single root parent that we call base. The base can be either fully fixed, 0 degrees of freedom, or
fully free, with 6 degrees of freedom. Since each link is connected to a parent with a single joint,
the number of joints is equal to the number of links. Regular links have link indices in the range
[0..getNumJoints()] Since the base is not a regular 'link', we use the convention of -1 as its link
index. We use the convention that joint frames are expressed relative to the parents center of
mass inertial frame, which is aligned with the principle axis of inertia.
getNumJoints, getJointInfo
After you load a robot you can query the number of joints using the getNumJoints API. For the
r2d2.urdf this should return 15.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
getNumJoints returns an integer value representing the number of joints.
getJointInfo
For each joint we can query some information, such as its name and type.
required bodyUniqueId int the body unique id, as returned by loadURDF etc.
20
optional physicsClientId int if you are connected to multiple servers, you can pick one.
jointName string the name of the joint, as specified in the URDF (or SDF etc) file
jointType int type of the joint, this also implies the number of position and velocity variables.
JOINT_REVOLUTE, JOINT_PRISMATIC, JOINT_SPHERICAL, JOINT_PLANAR,
JOINT_FIXED. See the section on Base, Joint and Links for more details.
qIndex int the first position index in the positional state variables for this body
uIndex int the first velocity index in the velocity state variables for this body
jointDamping float the joint damping value, as specified in the URDF file
jointFriction float the joint friction value, as specified in the URDF file
jointLowerLimit float Positional lower limit for slider and revolute (hinge) joints.
jointUpperLimit float Positional upper limit for slider and revolute joints. Values ignored in case upper
limit <lower limit.
jointMaxForce float Maximum force specified in URDF (possibly other file formats) Note that this value
is not automatically used. You can use maxForce in 'setJointMotorControl2'.
jointMaxVelocity float Maximum velocity specified in URDF. Note that the maximum velocity is not used
in actual motor control commands at the moment.
linkName string the name of the link, as specified in the URDF (or SDF etc.) file
setJointMotorControl2/Array
Note: setJointMotorControl is obsolete and replaced by setJointMotorControl2 API. (Or even
better use setJointMotorControlArray).
21
We can control a robot by setting a desired control mode for one or more joint motors. During
the stepSimulation the physics engine will simulate the motors to reach the given target value
that can be reached within the maximum motor forces and other constraints.
Important Note: by default, each revolute joint and prismatic joint is motorized using a velocity
motor. You can disable those default motor by using a maximum force of 0. This will let you
perform torque control.
For example:
maxForce = 0
mode = p.VELOCITY_CONTROL
p.setJointMotorControl2(objUid, jointIndex,
controlMode=mode, force=maxForce)
You can also use a small non-zero force to mimic joint friction.
If you want a wheel to maintain a constant velocity, with a max force you can use:
maxForce = 500
p.setJointMotorControl2(bodyUniqueId=objUid,
jointIndex=0,
controlMode=p.VELOCITY_CONTROL,
targetVelocity = targetVel,
force = maxForce)
optional physicsClientId int if you are connected to multiple servers, you can pick one.
Note: the actual implementation of the joint motor controller is as a constraint for
POSITION_CONTROL and VELOCITY_CONTROL, and as an external force for
TORQUE_CONTROL:
setJointMotorControlArray
Instead of making individual calls for each joint, you can pass arrays for all inputs to reduce
calling overhead dramatically.
required jointIndices list of int index in range [0..getNumJoints(bodyUniqueId) (note that link
index == joint index)
optional physicsClientId int if you are connected to multiple servers, you can pick one.
getJointState(s), resetJointState
We can query several state variables from the joint using getJointState, such as the joint
position, velocity, joint reaction forces and joint motor torque.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
getJointState output
jointReactionForces list of 6 floats These are the joint reaction forces, if a torque sensor is enabled for
this joint it is [Fx, Fy, Fz, Mx, My, Mz]. Without torque sensor, it is
[0,0,0,0,0,0].
appliedJointMotorTorque float This is the motor torque applied during the last stepSimulation.
Note that this only applies in VELOCITY_CONTROL and
POSITION_CONTROL. If you use TORQUE_CONTROL then the
applied joint motor torque is exactly what you provide, so there is
no need to report it separately.
24
getJointStates is the array version of getJointState. Instead of passing in a single jointIndex, you
pass in a list of jointIndices.
There is also getJointStateMultiDof for spherical joints.
resetJointState
You can reset the state of the joint. It is best only to do this at the start, while not running the
simulation: resetJointState overrides all physics simulation. Note that we only support 1-DOF
motorized joints at the moment, sliding joint or revolute joints.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
enableJointForceTorqueSensor
You can enable or disable a joint force/torque sensor in each joint. Once enabled, if you perform
a stepSimulation, the 'getJointState' will report the joint reaction forces in the fixed degrees of
freedom: a fixed joint will measure all 6DOF joint forces/torques. A revolute/hinge joint
force/torque sensor will measure 5DOF reaction forces along all axis except the hinge axis. The
applied force by a joint motor is available in the appliedJointMotorTorque of getJointState.
optional enableSensor int 1/True to enable, 0/False to disable the force/torque sensor
optional physicsClientId int if you are connected to multiple servers, you can pick one.
25
getLinkState
You can also query the Cartesian world position and orientation for the center of mass of each
link using getLinkState. It will also report the local inertial frame of the center of mass to the
URDF link frame, to make it easier to compute the graphics/visualization frame.
optional computeLinkVelocity int If set to 1, the Cartesian world velocity will be computed and
returned.
optional computeForwardKinematics int if set to 1 (or True), the Cartesian world position/orientation
will be recomputed using forward kinematics.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
localInertialFramePosition vec3, list of 3 floats local position offset of inertial frame (center of
mass) expressed in the URDF link frame
worldLinkFramePosition vec3, list of 3 floats world position of the URDF link frame
worldLinkFrameOrientation vec4, list of 4 floats world orientation of the URDF link frame
The relationship between URDF link frame and the center of mass frame (both in world space)
is: urdfLinkFrame = comLinkFrame * localInertialFrame.inverse(). For more information about
the link and inertial frame, see the ROS URDF tutorial.
26
examples/pybullet/tensorflow/humanoid_runnin load a humanoid and use a trained neural network to control the
g.py running using TensorFlow, trained by OpenAI
examples/pybullet/examples/quadruped.py load a quadruped from URDF file, step the simulation, control
the motors for a simple hopping gait based on sine waves.Will
also log the state to file using p.startStateLogging. See video.
examples/quadruped_playback.py Create a quadruped (Minitaur), read log file and set positions as
motor control targets.
examples/pybullet/examples/testrender.py load a URDF file and render an image, get the pixels (RGB,
depth, segmentation mask) and display the image using
MatPlotLib.
getBaseVelocity, resetBaseVelocity
You get access to the linear and angular velocity of the base of a body using getBaseVelocity.
The input parameters are:
required bodyUniqueId int body unique id, as returned from the load* methods.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
This returns a list of two vector3 values (3 floats in a list) representing the linear velocity [x,y,z]
and angular velocity [wx,wy,wz] in Cartesian worldspace coordinates.
You can reset the linear and/or angular velocity of the base of a body using resetBaseVelocity.
The input parameters are:
required objectUniqueId int body unique id, as returned from the load* methods.
optional linearVelocity vec3, list of 3 floats linear velocity [x,y,z] in Cartesian world coordinates.
optional angularVelocity vec3, list of 3 floats angular velocity [wx,wy,wz] in Cartesian world coordinates.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
applyExternalForce/Torque
You can apply a force or torque to a body using applyExternalForce and applyExternalTorque.
Note that this method will only work when explicitly stepping the simulation using
stepSimulation, in other words: setRealTimeSimulation(0). After each simulation step, the
external forces are cleared to zero. If you are using 'setRealTimeSimulation(1),
applyExternalForce/Torque will have undefined behavior (either 0, 1 or multiple force/torque
applications).
required forceObj vec3, list of 3 floats force/torque vector to be applied [x,y,z]. See flags for
coordinate system.
required posObj vec3, list of 3 floats position on the link where the force is applied. Only for
applyExternalForce. See flags for coordinate system.
28
getBodyInfo will return the base name, as extracted from the URDF, SDF, MJCF or other
file.
removeBody will remove a body by its body unique id (from loadURDF, loadSDF etc).
required parentLinkIndex int parent link index (or -1 for the base)
required childBodyUniqueId int child body unique id, or -1 for no body (specify a
non-dynamic child frame in world coordinates)
JOINT_POINT2POINT, JOINT_GEAR
required jointAxis vec3, list of 3 floats joint axis, in child link frame
required parentFramePosition vec3, list of 3 floats position of the joint frame relative to parent center
of mass frame.
required childFramePosition vec3, list of 3 floats position of the joint frame relative to a given child
center of mass frame (or world origin if no child
specified)
optional parentFrameOrientation vec4, list of 4 floats the orientation of the joint frame relative to parent
center of mass coordinate frame
optional childFrameOrientation vec4, list of 4 floats the orientation of the joint frame relative to the
child center of mass coordinate frame (or world
origin frame if no child specified)
optional physicsClientId int if you are connected to multiple servers, you can
pick one.
createConstraint will return an integer unique id, that can be used to change or remove the
constraint. See examples/pybullet/examples/mimicJointConstraint.py for an example of a
JOINT_GEAR and examples/pybullet/examples/minitaur.py for a JOINT_POINT2POINT and
examples/pybullet/examples/constraint.py for JOINT_FIXED.
changeConstraint
optional jointChildPivot vec3, list of 3 floats updated child pivot, see 'createConstraint'
optional gearRatio float the ratio between the rates at which the two
gears rotate
removeConstraint will remove a constraint, given by its unique id. Its input parameters are:
getNumConstraints, getConstraintUniqueId
You can query for the total number of constraints, created using 'createConstraint'. Optional
parameter is the int physicsClientId.
getConstraintUniqueId
getConstraintUniqueId will take a serial index in range 0..getNumConstraints, and reports the
constraint unique id. Note that the constraint unique ids may not be contiguous, since you may
remove constraints. The input is the integer serial index and optionally a physicsClientId.
getConstraintInfo/State
You can query the constraint info give a constraint unique id.
The input parameters are
getConstraintState
Give a constraint unique id, you can query for the applied constraint forces in the most recent
simulation step. The input is a constraint unique id and the output is a vector of constraint
forces, its dimension is the degrees of freedom that are affected by the constraint (a fixed
constraint affects 6 DoF for example).
getDynamicsInfo/changeDynamics
You can get information about the mass, center of mass, friction and other properties of the
base and links.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
The return information is limited, we will expose more information when we need it:
local inertia vec3, list of 3 floats local inertia diagonal. Note that links and base are centered
diagonal around the center of mass and aligned with the principal
axes of inertia.
local inertial pos vec3 position of inertial frame in local coordinates of the joint
frame
local inertial orn vec4 orientation of inertial frame in local coordinates of joint frame
changeDynamics
You can change the properties such as mass, friction and restitution coefficients using
changeDynamics.
optional mass double change the mass of the link (or base for linkIndex -1)
optional physicsClientId int if you are connected to multiple servers, you can pick
one.
optional contactStiffness double stiffness of the contact constraints, used together with
contactDamping.
optional contactDamping double damping of the contact constraints for this body/link.
Used together with contactStiffness. This overrides
the value if it was specified in the URDF file in the
contact section.
optional localInertiaDiagnoal vec3 diagonal elements of the inertia tensor. Note that the
base and links are centered around the center of
mass and aligned with the principal axes of inertia so
there are no off-diagonal elements in the inertia
33
tensor.
optional jointDamping double Joint damping coefficient applied at each joint. This
coefficient is read from URDF joint damping field.
Keep the value close to 0.
Joint damping force = -damping_coefficient *
joint_velocity.
setTimeStep
Warning: in many cases it is best to leave the timeStep to default, which is 240Hz. Several
parameters are tuned with this value in mind. For example the number of solver iterations and
the error reduction parameters (erp) for contact, friction and non-contact joints are related to the
time step. If you change the time step, you may need to re-tune those values accordingly,
especially the erp values.
You can set the physics engine timestep that is used when calling 'stepSimulation'. It is best to
only call this method at the start of a simulation. Don't change this time step regularly.
setTimeStep can also be achieved using the new setPhysicsEngineParameter API.
required timeStep float Each time you call 'stepSimulation' the timeStep will proceed with
'timeStep'.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
setPhysicsEngineParameter
You can set physics engine parameters using the setPhysicsEngineParameter API. The
following input parameters are exposed:
setDefaultContactERP is an API to set the default contact parameter setting. It will be rolled into
the setPhysicsEngineParameter API.
getPhysicsEngineParameters
You can query some current physics engine parameters using the getPhysicsEngineParameters
command, using the optional 'physicsClientId'. This will return named tuples of parameters.
resetSimulation
resetSimulation will remove all objects from the world and reset the world to initial conditions. It
takes one optional parameter: the physics client Id (in case you created multiple physics server
connections).
startStateLogging/stopStateLogging
State logging lets you log the state of the simulation, such as the state of one or more objects
after each simulation step (after each call to stepSimulation or automatically after each
simulation step when setRealTimeSimulation is enabled). This allows you to record trajectories
of objects. There is also the option to log the common state of bodies such as base position and
orientation, joint positions (angles) and joint motor forces.
All log files generated using startStateLogging can be read using C++ or Python scripts. See
quadruped_playback.py and kuka_with_cube_playback.py for Python scripts reading the log
files. You can use bullet3/examples/Utils/RobotLoggingUtil.cpp/h to read the log files in C++.
For MP4 video recording you can use the logging option STATE_LOGGING_VIDEO_MP4. We
plan to implement various other types of logging, including logging the state of VR controllers.
As a special case, we implemented the logging of the Minitaur robot. The log file from PyBullet
simulation is identical to the real Minitaur quadruped log file. See
Bullet/examples/pybullet/examples/logMinitaur.py for an example.
Important: various loggers include their own internal timestamp that starts at zero when created.
This means that you need to start all loggers at the same time, to be in sync. You need to make
sure to that the simulation is not running in real-time mode, while starting the loggers: use
pybullet.setRealTimeSimulation(0) before creating the loggers.
STATE_LOGGING_CONTACT_POINTS
STATE_LOGGING_VR_CONTROLLERS.
STATE_LOGGING_PROFILE_TIMINGS
This will dump a timings file in JSON format that can be opened
using Google Chrome about://tracing LOAD.
required fileName string file name (absolute or relative path) to store the log file data.
optional objectUniqueIds list of int If left empty, the logger may log every object, otherwise the logger
just logs the objects in the objectUniqueIds list.
optional maxLogDof int Maximum number of joint degrees of freedom to log (excluding the
base dofs). This applies to
STATE_LOGGING_GENERIC_ROBOT_DATA. Default value is
12. If a robot exceeds the number of dofs, it won't get logged at all.
optional deviceTypeFilter int deviceTypeFilter allows you to select what VR devices to log:
VR_DEVICE_CONTROLLER, VR_DEVICE_HMD
,VR_DEVICE_GENERIC_TRACKER or any combination of them.
Applies to STATE_LOGGING_VR_CONTROLLERS. Default
values is VR_DEVICE_CONTROLLER.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
37
The command will return a non-negative int loggingUniqueId, that can be used with
stopStateLogging.
Todo: document the data that is logged for each logging type. For now, use the log reading
utilities to find out, or check out the C++ source code of the logging or Python dumpLog.py
script.
stopStateLogging
You can stop a logger using its loggingUniqueId.
submitProfileTiming
PyBullet and Bullet have instrumented many functions so you can see where the time is spend.
You can dump those profile timings in a file, that can be viewed with Google Chrome in the
about://tracing window using the LOAD feature. In the GUI, you can press 'p' to start/stop the
profile dump. In some cases you may want to instrument the timings of your client code. You
can submit profile timings using PyBullet. Here is an example output:
The synthetic camera is specified by two 4 by 4 matrices: the view matrix and the projection
matrix. Since those are not very intuitive, there are some helper methods to compute the view
and projection matrix from understandable parameters.
Check out this article about intrinsic camera matrix with links to OpenGL camera information.
computeViewMatrix
The computeViewMatrix input parameters are
coordinates
required cameraTargetPosition vec3, list of 3 floats position of the target (focus) point, in
Cartesian world coordinates
required cameraTargetPosition list of 3 floats target focus point in Cartesian world coordinates
computeProjectionMatrix
The input parameters are
This command also will return a 4x4 projection matrix, using different parameters. You can
check out OpenGL documentation for the meaning of the parameters.
The input parameters are:
getCameraImage
The getCameraImage API will return a RGB image, a depth buffer and a segmentation mask
buffer with body unique ids of visible objects for each pixel. Note that PyBullet can be compiled
using the numpy option: using numpy will improve the performance of copying the camera
pixels from C to Python. Note: the old renderImage API is obsolete and replaced by
getCameraImage.
optional lightDirection vec3, list of 3 floats lightDirection specifies the world position of the
light source, the direction is from the light source
position to the origin of the world frame.
optional physicsClientId int if you are connected to multiple servers, you can
pick one.
rgbPixels list of [char RED,char GREEN,char BLUE, list of pixel colors in R,G,B,A format,
char ALPHA] [0..width*height] in range [0..255] for each color
far=1000.//depends on projection
matrix, this is default
near=0.01//depends on projection
matrix
depth = far * near / (far - (far - near) *
depthImg)//depthImg is the depth
from Bullet 'getCameraImage'
segmentationMaskBuffer list of int [0..width*height] For each pixels the visible object
unique id. If
ER_SEGMENTATION_MASK_OBJ
ECT_AND_LINKINDEX is used, the
segmentationMaskBuffer combines
the object unique id and link index as
follows:
value = objectUniqueId +
(linkIndex+1)<<24. See example.
Note that copying pixels from C/C++ to Python can be really slow for large images, unless you
compile PyBullet using NumPy. You can check if NumPy is enabled using
PyBullet.isNumpyEnabled(). pip install pybullet has NumPy enabled, if available on the system.
getVisualShapeData
You can access visual shape information using getVisualShapeData. You could use this to
bridge your own rendering method with PyBullet simulation, and synchronize the world
transforms manually after each simulation step.
The output is a list of visual shape data, each visual shape is in the following format:
dimensions vec3, list of 3 floats dimensions (size, local scale) of the geometry
meshAssetFileName string, list of chars path to the triangle mesh, if any. Typically relative to the
URDF, SDF or MJCF file location, but could be absolute.
localVisualFrame position vec3, list of 3 floats position of local visual frame, relative to link/joint frame
localVisualFrame orientation vec4, list of 4 floats orientation of local visual frame relative to link/joint frame
42
rgbaColor vec4, list of 4 floats URDF color (if any specified) in red/green/blue/alpha
The physics simulation uses center of mass as a reference for the Cartesian world transforms,
in getBasePositionAndOrientation and in getLinkState. If you implement your own rendering,
you need to transform the local visual transform to world space, making use of the center of
mass world transform and the (inverse) localInertialFrame. You can access the
localInertialFrame using the getLinkState API.
changeVisualShape, loadTexture
You can use changeVisualShape to change the texture of a shape, the RGBA color and other
properties.
optional rgbaColor vec4, list of 4 color components for RED, GREEN, BLUE and ALPHA,
floats each in range [0..1]. Alpha has to be 0 (invisible) or 1
(visible) at the moment. Note that TinyRenderer doesn't
support transparancy, but the GUI/EGL OpenGL3 renderer
does.
optional specularColor vec3 specular color components, RED, GREEN and BLUE, can
be from 0 to large number (>100).
loadTexture
Load a texture from file and return a non-negative texture unique id if the loading succeeds. This
unique id can be used with changeVisualShape.
43
getOverlappingObjects, getAABB
This query will return all the unique ids of objects that have axis aligned bounding box overlap
with a given axis aligned bounding box. Note that the query is conservative and may return
additional objects that don't have actual AABB overlap. This happens because the acceleration
structures have some heuristic that enlarges the AABBs a bit (extra margin and extruded along
the velocity vector).
getAABB
You can query the axis aligned bounding box (in world space) given an object unique id, and
optionally a link index. (when you don't pass the link index, or use -1, you get the AABB of the
base).
optional physicsClientId int if you are connected to multiple servers, you can pick one.
44
The return structure is a list of vec3, aabbMin (x,y,z) and aabbMax (x,y,z) in world space
coordinates.
getContactPoints, getClosestPoints
The getContactPoints API returns the contact points computed during the most recent call to
stepSimulation. Its input parameters are as follows:
optional bodyA int only report contact points that involve body A
optional bodyB int only report contact points that involve body B. Important: you
need to have a valid bodyA if you provide body B.
optional linkIndexA int Only report contact points that involve linkIndexA of bodyA
optional linkIndexB int Only report contact points that involve linkIndexB of bodyB
optional physicsClientId int if you are connected to multiple servers, you can pick one.
getContactPoints will return a list of contact points. Each contact point has the following fields:
contactDistance float contact distance, positive for separation, negative for penetration
getClosestPoints
It is also possible to compute the closest points, independent from stepSimulation. This also lets
you compute closest points of objects with an arbitrary separating distance. In this query there
will be no normal forces reported.
required distance float If the distance between objects exceeds this maximum distance,
no points may be returned.
optional linkIndexA int link index for object A (-1 for base)
optional linkIndexB int link index for object B (-1 for base)
optional physicsClientId int if you are connected to multiple servers, you can pick one.
getClosestPoints returns a list of closest points in the same format as getContactPoints (but
normalForce is always zero in this case)
rayTest, rayTestBatch
You can perform a single raycast to find the intersection information of the first object hit.
required rayToPosition vec3, list of 3 floats end of the ray in world coordinates
optional physicsClientId int if you are connected to multiple servers, you can
pick one.
The raytest query will return the following information in case of an intersection:
hit fraction float hit fraction along the ray in range [0,1] along the ray.
hit position vec3, list of 3 floats hit position in Cartesian world coordinates
hit normal vec3, list of 3 floats hit normal in Cartesian world coordinates
rayTestBatch
This is similar to the rayTest, but allows you to provide an array of rays, for faster execution. The
size of 'rayFromPositions' needs to be equal to the size of 'rayToPositions'. You can one ray
result per ray, even if there is no intersection: you need to use the objectUniqueId field to check
if the ray has hit anything: if the objectUniqueId is -1, there is no hit. In that case, the 'hit fraction'
is 1. The maximum number of rays per batch is
pybullet.MAX_RAY_INTERSECTION_BATCH_SIZE.
required rayToPositions list of vec3, list of list list of end points for each ray in world coordinates
of 3 floats
optional physicsClientId int if you are connected to multiple servers, you can
pick one.
Output is one ray intersection result per input ray, with the same information as in above rayTest
query. See batchRayTest.py example how to use it.
getCollisionShapeData
You can query the collision geometry type and other collision shape information of existing body
base and links using this query. It works very similar to getVisualShapeData.
required objectUniqueId int object unique id, received from loadURDF etc
47
optional physicsClientId int if you are connected to multiple servers, you can pick one.
dimensions vec3 depends on geometry type: for GEOM_BOX: extents, for GEOM_SPHERE
dimensions[0] = radius, for GEOM_CAPSULE and GEOM_CYLINDER,
dimensions[0] = height (length), dimensions[1] = radius. For GEOM_MESH,
dimensions is the scaling factor.
filename string Only for GEOM_MESH: file name (and path) of the collision mesh asset
local frame pos vec3 Local position of the collision frame with respect to the center of mass/inertial frame.
local frame orn vec4 Local orientation of the collision frame with respect to the inertial frame.
Enable/Disable Collisions
By default, collision detection is enabled between different dynamic moving bodies.
Self-collision between links of the same body can be enabled using flags such as
'URDF_USE_SELF_COLLISION' flag in loadURDF (see the loadURDF command for more
info).
You can enable and disable collision detection between groups of objects using the
setCollisionFilterGroupMask API.
setCollisionFilterGroupMask
Each body is part of a group. It collides with other bodies if their group matches the mask, and
vise versa. The following check is performed using the group and mask of the two bodies
involved. It depends on the collision filter mode.
required collisionFilterGroup int bitwise group of the filter, see below for explanation
required collisionFilterMask int bitwise mask of the filter, see below for explanation
optional physicsClientId int if you are connected to multiple servers, you can pick one.
You can have more fine-grain control over collision detection between specific pairs of
linksThere using the setCollisionFilterPair API: you can enable or disable collision detection.
setCollisionFilterPair will override the filter group/mask and other logic.
setCollisionFilterPair
optional physicsClientId int if you are connected to multiple servers, you can pick one.
There is a plugin API to write your own collision filtering implementation as well, see the
collisionFilterPlugin implementation.
calculateInverseDynamics
calculateInverseDynamics will compute the forces needed to reach the given joint accelerations,
starting from specified joint positions and velocities. The inverse dynamics is computed using
the recursive Newton Euler algorithm (RNEA).
required objPositions list of float joint positions (angles) for each degree of freedom (DoF).
Note that fixed joints have 0 degrees of freedom. The base
is skipped/ignored in all cases (floating base and fixed
base).
required objVelocities list of float joint velocities for each degree of freedom (DoF)
required objAccelerations list of float desired joint accelerations for each degree of freedom
(DoF)
optional physicsClientId int if you are connected to multiple servers, you can pick one.
calculateInverseDynamics returns a list of joint forces for each degree of freedom.
calculateJacobian, MassMatrix
calculateJacobian will compute the translational and rotational jacobians for a point on a link,
e.g. x_dot = J * q_dot. The returned jacobians are slightly different depending on whether the
root link is fixed or floating. If floating, the jacobians will include columns corresponding to the
root link degrees of freedom; if fixed, the jacobians will only have columns associated with the
joints. The function call takes the full description of the kinematic state, this is because
calculateInverseDynamics is actually called first and the desired jacobians are extracted from
this; therefore, it is reasonable to pass zero vectors for joint velocities and accelerations if
desired.
required localPosition list of float the point on the specified link to compute the jacobian for, in
link local coordinates around its center of mass.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
calculateJacobian returns:
calculateMassMatrix
calculateMassMatrix will compute the system inertia for an articulated body given its joint
positions. The composite rigid body algorithm (CBRA) is used to compute the mass matrix.
optional physicsClientId int if you are connected to multiple servers, you can pick one.
The result is the square mass matrix with dimensions dofCount * dofCount, stored as a list of
dofCount rows, each row is a list of dofCount mass matrix elements.
Inverse Kinematics
You can compute the joint angles that makes the end-effector reach a given target position in
Cartesian world space. Internally, Bullet uses an improved version of Samuel Buss Inverse
Kinematics library. At the moment only the Damped Least Squares method with or without Null
Space control is exposed, with a single end-effector target. Optionally you can also specify the
target orientation of the end effector. In addition, there is an option to use the null-space to
specify joint limits and rest poses. This optional null-space support requires all 4 lists
(lowerLimits, upperLimits, jointRanges, restPoses), otherwise regular IK will be used. See also
inverse_kinematics.py example in Bullet/examples/pybullet/examples folder for details.
calculateInverseKinematics(2)
calculateInverseKinematics input parameters are:
required targetPosition vec3, list of 3 floats target position of the end effector (its link
coordinate, not center of mass coordinate!).
By default this is in Cartesian world space,
unless you provide currentPosition joint
angles.
optional targetOrientation vec3, list of 4 floats target orientation in Cartesian world space,
quaternion [x,y,w,z]. If not specified, pure
position IK will be used.
optional lowerLimits list of floats [0..nDof] Optional null-space IK requires all 4 lists
(lowerLimits, upperLimits, jointRanges,
restPoses). Otherwise regular IK will be used.
Only provide limits for joints that have them
(skip fixed joints), so the length is the number
51
optional upperLimits list of floats [0..nDof] Optional null-space IK requires all 4 lists
(lowerLimits, upperLimits, jointRanges,
restPoses). Otherwise regular IK will be used..
lowerLimit and upperLimit specify joint limits
optional jointRanges list of floats [0..nDof] Optional null-space IK requires all 4 lists
(lowerLimits, upperLimits, jointRanges,
restPoses). Otherwise regular IK will be used.
optional restPoses list of floats [0..nDof] Optional null-space IK requires all 4 lists
(lowerLimits, upperLimits, jointRanges,
restPoses). Otherwise regular IK will be used..
Favor an IK solution closer to a given rest
pose
optional jointDamping list of floats [0..nDof] jointDamping allow to tune the IK solution
using joint damping factors
optional currentPosition list of floats [0..nDof] list of joint positions. By default PyBullet
uses the joint positions of the body. If
provided, the targetPosition and
targetOrientation is in local space!
By default, the IK will refine the solution until the distance between target end effector and
actual end effector is below a residual threshold (1e-4) or the maximum number of iterations is
reached.
calculateInverseKinematics2
Similar to calculateInverseKinematics, but it takes a list of end-effector indices and their target
positions (no orientations at the moment).
required targetPositions list of vec3 target position of the end effector (its link
coordinate, not center of mass coordinate!).
By default this is in Cartesian world space,
unless you provide currentPosition joint
angles.
The source code of pybullet, pybullet_envs, pybullet_data and the examples are here:
https://github.com/bulletphysics/bullet3/tree/master/examples/pybullet/gym.
You can train the environments with RL training algorithms such as DQN, PPO, TRPO and
DDPG. Several pre-trained examples are available, you can enjoy them like this:
After you "sudo pip install pybullet", the pybullet_envs and pybullet_data packages are
available. Importing the pybullet_envs package will register the environments automatically to
OpenAI Gym.
You can get a list of the Bullet environments in gym using the following Python line:
print(
env = gym.make('MinitaurBulletEnv-v0')
import pybullet_envs.bullet.minitaur_gym_env as e
env = e.MinitaurBulletEnv(render=True)
import pybullet_envs.bullet.racecarGymEnv as e
env = e.RacecarGymEnv(isDiscrete=False ,renders=True)
env.reset()
KukaBulletEnv-v0 Simulation of the KUKA Iiwa robotic arm, grasping an object in a tray.
The main reward happens a the end, when the gripped can grasp the
object above a certain height. Some very small reward/cost happens
each step: cost of action and distance between gripper and object.
Observation includes the x,y position of the object.
Note: this environment has issues training at the moment, we look into it.
We ported the Roboschool environments to pybullet. The Roboschool environments are harder
than the MuJoCo Gym environments.
HalfCheetahBulletEnv-v0
HopperBulletEnv-v0
Walker2DBulletEnv-v0
56
InvertedPendulumBulletEnv-v0
InvertedDoublePendulumBulletEnv-v0
InvertedPendulumSwingupBulletEnv-v0
It is also possible to access the data, such as URDF/SDF robot assets, Wavefront .OBJ files
from the pybullet_data package. Here is an example how to do this:
import pybullet
import pybullet_data
datapath = pybullet_data.getDataPath()
pybullet.connect(pybullet.GUI)
pybullet.setAdditionalSearchPath(datapath)
pybullet.loadURDF("r2d2.urdf",[0,0,1])
Alternatively, manually append the datapath to the filename in the loadURDF/SDF commands.
For discrete Gym environments such as the KukaBulletEnv-v0 and RacecarBulletEnv-v0 you
can use OpenAI Baselines DQN to train the model using a discrete action space. Some
examples are provided how to train and enjoy those discrete environments:
python -m pybullet_envs.baselines.train_pybullet_cartpole
python -m pybullet_envs.baselines.train_pybullet_racecar
OpenAI Baselines will save a .PKL file at specified intervals when the model improves. This
.PKL file is used in the enjoy scripts:
python -m pybullet_envs.baselines.enjoy_pybullet_cartpole
python -m pybullet_envs.baselines.enjoy_pybullet_racecar
There are also some pre-trained models that you can enjoy out-of-the-box. Here is a list of
pretrained environments to enjoy:
57
python -m pybullet_envs.examples.enjoy_TF_AntBulletEnv_v0_2017may
python -m pybullet_envs.examples.enjoy_TF_HalfCheetahBulletEnv_v0_2017may
python -m pybullet_envs.examples.enjoy_TF_AntBulletEnv_v0_2017may
python -m pybullet_envs.examples.enjoy_TF_HopperBulletEnv_v0_2017may
python -m pybullet_envs.examples.enjoy_TF_HumanoidBulletEnv_v0_2017may
python -m pybullet_envs.examples.enjoy_TF_InvertedDoublePendulumBulletEnv_v0_2017may
python -m pybullet_envs.examples.enjoy_TF_InvertedPendulumBulletEnv_v0_2017may
python -m pybullet_envs.examples.enjoy_TF_InvertedPendulumSwingupBulletEnv_v0_2017may
python -m pybullet_envs.examples.enjoy_TF_Walker2DBulletEnv_v0_2017may
After training, you can visualize the trained model, creating a video or visualizing it using a physics server
(python -m pybullet_envs.examples.runServer or ExampleBrowser in physics server mode or in Virtual
Reality). If you start a local GUI physics server, the visualizer (bullet_client.py) will automatically connect
58
to it, and use OpenGL hardware rendering to create the video. Otherwise it will use the CPU tinyrenderer
instead. To generate the video, use:
In a similar way you can train and visualize the Minitaur robot:
Virtual Reality
See also the vrBullet quickstart guide.
The VR physics server uses the OpenVR API for HTC Vive and
Oculus Rift Touch controller support. OpenVR is currently
working on Windows, Valve is also working on a Linux version.
getVREvents,setVRCameraState
getVREvents will return a list events for a selected VR devices that changed state since the last
call to getVREvents. When not providing any deviceTypeFilter, the default is to only report
VR_DEVICE_CONTROLLER state. You can choose any combination of devices including
VR_DEVICE_CONTROLLER, VR_DEVICE_HMD (Head Mounted Device) and VR_DEVICE_GENERIC_TRACKER
(such as the HTC Vive Tracker).
Note that VR_DEVICE_HMD and VR_DEVICE_GENERIC_TRACKER only report position and orientation events.
getVREvents has the following parameters:
optional allAnalogAxes int 1 for all analogue axes, 0 with just a single axis
optional physicsClientId int if you are connected to multiple servers, you can pick one.
controllerPosition vec3, list of 3 floats controller position, in world space Cartesian coordinates
controllerOrientation vec4, list of 4 floats controller orientation quaternion [x,y,z,w] in world space
buttons int[64], list of button flags for each button: VR_BUTTON_IS_DOWN (currently
states (OpenVR has a held down), VR_BUTTON_WAS_TRIGGERED (went down
maximum of 64 at least once since last cal to getVREvents,
buttons) VR_BUTTON_WAS_RELEASED (was released at least once
since last call to getVREvents). Note that only
VR_BUTTON_IS_DOWN reports actual current state. For
example if the button went down and up, you can tell from the
RELEASE/TRIGGERED flags, even though IS_DOWN is still
false. Note that in the log file, those buttons are packed with
10 buttons in 1 integer (3 bits per button).
setVRCameraState
setVRCameraState allows to set the camera root transform offset position and orientation. This
allows to control the position of the VR camera in the virtual world. It is also possible to let the
VR Camera track an object, such as a vehicle.
optional rootOrientation vec4, vector of 4 floats camera root orientation in quaternion [x,y,z,w] format.
optional physicsClientId int if you are connected to multiple servers, you can pick
61
one.
addUserDebugLine, Text
You can add a 3d line specified by a 3d starting point (from) and end point (to), a color
[red,green,blue], a line width and a duration in seconds. The arguments to addUserDebugline
are:
required lineFromXYZ vec3, list of 3 starting point of the line in Cartesian world coordinates
floats
required lineToXYZ vec3, list of 3 end point of the line in Cartesian world coordinates
floats
optional lineColorRGB vec3, list of 3 RGB color [Red, Green, Blue] each component in range
floats [0..1]
optional lifeTime float use 0 for permanent line, or positive time in seconds
(afterwards the line with be removed automatically)
optional parentObjectUniqueId int new in upcoming PyBullet 1.0.8: draw line in local
coordinates of a parent object/link.
optional parentLinkIndex int new in upcoming PyBullet 1.0.8: draw line in local
coordinates of a parent object/link.
optional physicsClientId int if you are connected to multiple servers, you can pick
one
addUserDebugLine will return a non-negative unique id, that lets you remove the line using
removeUserDebugItem.
addUserDebugText
62
You can add some 3d text at a specific location using a color and size. The input arguments
are:
required textPosition vec3, list of 3 3d position of the text in Cartesian world coordinates
floats [x,y,z]
optional textColorRGB vec3, list of 3 RGB color [Red, Green, Blue] each component in range
floats [0..1]
optional lifeTime float use 0 for permanent text, or positive time in seconds
(afterwards the text with be removed automatically)
optional textOrientation vec4, list of 4 By default, debug text will always face the camera,
floats automatically rotation. By specifying a text orientation
(quaternion), the orientation will be fixed in world space
or local space (when parent is specified). Note that a
different implementation/shader is used for camera
facing text, with different appearance: camera facing
text uses bitmap fonts, text with specified orientation
uses TrueType fonts..
optional parentObjectUniqueId int new in upcoming PyBullet 1.0.8: draw line in local
coordinates of a parent object/link.
optional parentLinkIndex int new in upcoming PyBullet 1.0.8: draw line in local
coordinates of a parent object/link.
optional replaceItemUniqueId int replace an existing text item (to avoid flickering of
remove/add)
optional physicsClientId int if you are connected to multiple servers, you can pick
one
addUserDebugText will return a non-negative unique id, that lets you remove the line using
removeUserDebugItem. See also pybullet/examples/debugDrawItems.py
addUserDebugParameter
addUserDebugParameter lets you add custom sliders to tune parameters. It will return a unique
id. This lets you read the value of the parameter using readUserDebugParameter. The input
parameters of addUserDebugParameter are:
optional physicsClientId int if you are connected to multiple servers, you can pick one
optional physicsClientId int if you are connected to multiple servers, you can pick one
removeUserDebugItem/All
The functions to add user debug lines, text or parameters will return a non-negative unique id if
it succeeded. You can remove the debug item using this unique id using the
removeUserDebugItem method.The input parameters are:
required itemUniqueId int unique id of the debug item to be removed (line, text etc)
optional physicsClientId int if you are connected to multiple servers, you can pick one
removeAllUserDebugItems
This API will remove all debug items (text, lines etc).
setDebugObjectColor
The built-in OpenGL visualizers have a wireframe debug rendering feature: press 'w' to toggle.
The wireframe has some default colors. You can override the color of a specific object and link
using setDebugObjectColor. The input parameters are:
addUserData
In a nutshell, add, remove and query user data, at the moment text strings, attached to any link
of a body. See the userData.py example on how to use it.
configureDebugVisualizer
You can configure some settings of the built-in OpenGL visualizer, such as enabling or disabling
wireframe, shadows and GUI rendering. This is useful since some laptops or Desktop GUIs
have performance issues with our OpenGL 3 visualizer.
optional physicsClientId int if you are connected to multiple servers, you can pick one
Example:
pybullet.configureDebugVisualizer(pybullet.COV_ENABLE_WIREFRAME,1)
get/resetDebugVisualizerCamera
resetDebugVisualizerCamera
You can reset the 3D OpenGL debug visualizer camera distance (between eye and camera
target position), camera yaw and pitch and camera target position.
required cameraTargetPosition vec3, list of 3 floats cameraTargetPosition is the camera focus point
optional physicsClientId int if you are connected to multiple servers, you can pick
one
getDebugVisualizerCamera
You can get the width and height (in pixels) of the camera, its view and projection matrix using
this command. Input parameter is the optional physicsClientId. Output information is:
cameraUp float3, list of 3 up axis of the camera, in Cartesian world space coordinates
floats
cameraForward float3, list of 3 forward axis of the camera, in Cartesian world space coordinates
floats
horizontal float3, list of 3 TBD. This is a horizontal vector that can be used to generate rays
floats (for mouse picking or creating a simple ray tracer for example)
vertical float3, list of 3 TBD.This is a vertical vector that can be used to generate rays(for
floats mouse picking or creating a simple ray tracer for example).
yaw float yaw angle of the camera, in Cartesian local space coordinates
pitch float pitch angle of the camera, in Cartesian local space coordinates
dist float distance between the camera and the camera target
target float3, list of 3 target of the camera, in Cartesian world space coordinates
floats
66
getKeyboardEvents, getMouseEvents
You can receive all keyboard events that happened since the last time you called
'getKeyboardEvents'. Each event has a keycode and a state. The state is a bit flag combination
of KEY_IS_DOWN, KEY_WAS_TRIGGERED and KEY_WAS_RELEASED. If a key is going
from 'up' to 'down' state, you receive the KEY_IS_DOWN state, as well as the
KEY_WAS_TRIGGERED state. If a key was pressed and released, the state will be
KEY_IS_DOWN and KEY_WAS_RELEASED.
optional physicsClientId int if you are connected to multiple servers, you can pick one
getMouseEvents
Similar to getKeyboardEvents, you can get the mouse events that happened since the last call
to getMouseEvents. All the mouse move events are merged into a single mouse move event
with the most up-to-date position. In addition, all mouse button events for a given button are
merged. If a button went down and up, the state will be 'KEY_WAS_TRIGGERED '. We reuse
the KEY_WAS_TRIGGERED /KEY_IS_DOWN /KEY_WAS_RELEASED for the mouse button
states.
Plugins
PyBullet allows you to write plugins in C or C++ to add customize features. Some core features
of PyBullet are written as plugins, such as PD control, rendering, gRPC server, collision filtering
and Virtual Reality sync. Most plugins that are core part of PyBullet are statically linked by
default, so you don't need to manually load and unload them.
On Linux, the eglPlugin is an example of a plugin that ships with PyBullet by default. It can be
enabled to use hardware OpenGL 3.x rendering without a X11 context, for example for cloud
rendering on the Google Cloud Platform. See the eglRenderTest.py example how to use it.
PyBullet also comes with a fileIOPlugin that can load files from a zip file directly and allows file
caching. See the fileIOPlugin.py example how to use it.
loadPlugin,executePluginCommand
required pluginPath string path, location on disk where to find the plugin
required postFix string postfix name of the plugin that is appended to each API
optional physicsClientId int if you are connected to multiple servers, you can pick one
loadPlugin will return a pluginUniqueId integer. If this pluginId is negative, the plugin is not
loaded. Once a plugin is loaded, you can send commands to the plugin using
executePluginCommand:
68
optional physicsClientId int if you are connected to multiple servers, you can pick one
unloadPlugin
You can unload a plugin using the pluginId.
The plugin API shares the same underlying C API than PyBullet and has the same features as
PyBullet.
You can browser the plugin implementation of PyBullet to get an idea what is possible.
You may need to use sudo pip install pybullet o r pip install pybullet --user.
Note that if you used pip to install PyBullet, it is still beneficial to also install the C++ Bullet
Physics SDK: it includes data files, physics servers and tools useful for PyBullet.
You can also run 'python setup.py build' and 'python setup.py install' in the root of the Bullet
Physics SDK (get the SDK from http://github.com/bulletphysics/bullet3)
Alternatively you can install PyBullet from source code using premake (Windows) or cmake:
Make sure some Python version is installed in c:\python-3.5.2 (or other version folder name)
Note that the recommended way is to use sudo pip install pybullet (or pip3). Using cmake or
premake or other build systems is only for developers who know what they are doing, and is
unsupported in general.
That's it. Test pybullet by running a python interpreter and enter 'import pybullet' to see if the
module loads. If so, you can play with the pybullet scripts in Bullet/examples/pybullet.
Question: What happens to Bullet 2.x and the Bullet 3 OpenCL implementation?
Answer: PyBullet is wrapping the Bullet C-API. We will put the Bullet 3 OpenCL GPU API
(and future Bullet 4.x API) behind this C-API. So if you use PyBullet or the C-API
you are future-proof. Not to be confused with the Bullet 2.x C++ API.
Question: The velocity of objects seems to be smaller than expected. Does PyBullet apply
some default damping? Also the velocity doesn't exceed 100 units.
Answer: Yes, PyBullet applies some angular and linear damping to increase stability. You
can modify/disable this damping using the 'changeDynamics' command, using
linearDamping=0 and angularDamping=0 as arguments.
The maximum linear/angular velocity is clamped to 100 units for stability.
Question: How to turn off gravity only for some parts of a robot (for example the arm)?
Answer:
At the moment this is not exposed, so you would need to either turn of gravity
acceleration for all objects, and manually apply gravity for the objects that need it.
Or you can actively compute gravity compensation forces, like happens on a real
robot. Since Bullet has a full constraint system, it would be trivial to compute
those anti-gravity forces: You could run a second simulation (PyBullet lets you
connect to multiple physics servers) and position the robot under gravity, set joint
position control to keep the position as desired, and gather those 'anti-gravity'
forces. Then apply those in the main simulation.
72
see the Bullet/data/sphere2.urdf for example. Instead of the cone friction, you can
enable pyramidal approximation.
Question: What kind of constant or threshold inside Bullet, that makes high speeds impossible?
Answer: By default, Bullet relies on discrete collision detection in combination with
penetration recovery. Relying purely on discrete collision detection means that an object
should not travel faster than its own radius within one timestep. PyBullet uses 1./240 as
a default timestep. Time steps larger than 1./60 can introduce instabilities for various
reasons (deep penetrations, numerical integrator). Bullet has is an option for continuous
collision detection to catch collisions for objects that move faster than their own radius
within one timestep. Unfortunately, this continuous collision detection can introduce its
own issues (performance and non-physical response, lack of restitution), hence this
experimental feature is not enabled by default.