PyCRAM Bullet World Tutorial

Before you can work with PyCRAM you have to provide it with a robot description, so PyCRAM knows which robot is currently used. This can be done via the ROS launchfile in the launch directory. This launchfile contains an argument that specifies which robot urdf should be uploaded as the description. To launch the ROS launchfile just execute the following command:

roslaunch pycram ik_and_description.launch 



The BulletWorld comes equipped with a window that renders the current state of the simulation. To interact with this window and change the position of the camera you have to press and hold the ctrl key and the left mouse button, then you can change the position of the camera in the simulation.


When loading an Object in the BulletWorld either from a URDF, OBJ or SDF file there are some operations like resolving ROS package paths to actual paths in the file systems that have to be done. To save time on this part when loading the same Object again, PyCRAM caches the resulting file with the actual paths in resources/cached.

Keep in mind that PyCRAM does not check for changes of the original file and always loads the cached file if it exists. You can circumvent this by using the ignoreCachedFiles parameter when creating an Object.

milk = Object("milk", "milk", "milk.stl", [0, 0, 1], ignoreCachedFiles=true)

Another option would be to just remove the directory resources/cached.


The BulletWorld is PyCRAMs internal physics simulation which is used for geometric reasoning as well as executing the robot control plans. For a detailed description as well as a documentation of the API please look in the corresponding docu here.

The aim of this tutorial is to show the basics of how a user can interact with the BulletWorld, this includes loading objects and interacting with them.

To get started we need to import the BulletWorld as well as the Object class from PyCRAM. Objects are everything that you can load into the BulletWorld, there is only the Object class to give the user a simpler API such that everything in the BulletWorld provides the same methods.

from pycram.bullet_world import BulletWorld, Object

To open a BulletWorld you simply need to create an instance of the BulletWorld class. Here you can also set the gravity that should be applied when the simulation is running.

world = BulletWorld()
world.set_gravity([0, 0, -9.8])

The opening window should look like this.

This is simply an empty BulletWorld without anything inside. To load objects into this we use the Object class which we imported before.

plane = Object("floor", "environment", "plane.urdf", world=world)
milk = Object("milk", "milk", "milk.stl", [0, 0, 1])

This should spawn a static ground plane as well as a milk which is floating above the plane. The milk is floating and does not fall down even though the gravity is set to be the normal gravity on earth, this is the case since the BulletWorld is not simulating at the moment.

For the simulation in the BulletWorld to run it has to be directly called this can be done by either the “simualte” method which takes an amount of time (in seconds) that should be simulated or the “set_realtime” method which takes a boolean value and lets the BulletWorld continuously run in real time. Both methods are part of the BulletWorld class and can be called like this:



To interact with the spawned objects in the BulletWorld there are a lot of methods provided by the Object class, a detailed list can be seen here.

Here we will use the “set_position_and_orientation” method to give the milk a new position as well as orientation.

milk.set_position_and_orientation([1, 1, 1], [0, 1, 0, 1])

As you can see the new position is given as a list representing the xyz-coordinates in the Cartesian world coordinate frame and the orientation is given as a list representing the xyzw components of a quaternion.

Another interesting method of objects is the “attach” method which takes another object as parameter and creates an attachment between these two. Meaning as long as they are attached to each other they will always move simultaneously while keeping their relative positions.

Lastly, for more complex objects like robots there are methods for getting the position or orientation of specific joints or setting the value of a joint.