World

raisim::World class creates/manages all resources. All objects defined in the same World class instance can collide with each other unless otherwise their collision mask and group explicitly disables the collision (read Contact and Collision section for this topic).

There are two ways to generate the World instance (i.e., two constructors). The first way is to load an raisim world configuration file, which is in a form of an XML file. You can read more about the XML format in the World Configuration File section.

The second way is to generate world dynamically in code.

You can also mix the two ways, by loading an XML file and dynamically adding objects.

There is an experimental MJCF (MuJoCo file format) reader. Simple models can be constructed with an MJCF file.

Adding New Objects

To add a new object of a shape X, a method named addX is used. For example, to add a sphere

raisim::World world;
auto sphere = world.addSphere(0.5, 1.0);

Here sphere is a pointer to the internal resource. It can be used to access or to modify the internal variables.

There are three hidden arguments to all object-creation methods: material, collisionGroup and collisionMask. Descriptions of the collision variables are given in “Collision and Contact” chapter. material argument specifies the material which governs contact dynamics. It is further explained in “Material System” chapter.

The list of objects is given in “Object” chapter.

Once an object is added, a name can be set as below

sphere.setName("ball");

A pointer to an object with a specific name can be retrieved as below

auto ball = world.getObject("ball");

An object might contain multiple bodies (i.e., articulated system). To designate each body, local index can be used. To keep the interface consistent, many methods ask for the local index even for simgle body objects. In a single body object case, local index arguments are ignored and users can simply put 0 to comply with the AIP.

Save world to an XML file

raisim::World::exportToXml() lets you save the world to an XML file. EXAMPLES

MuJoCo mjcf file loader

RaiSim partially supports mjcf file. There are inherent differences between the two simulators and inevitably some features are not supported. But you can load simple mjcf files (e.g., ones provided by OpenAI).

Changing Simulation Parameters

The following parameters can be changed using the world API

  • Time step

RaiSim uses a fixed time step. The time step obtained and modified using getTimeStep and setTimeStep method.

API

class World

Public Functions

explicit World()

Create an empty world

explicit World(const std::string &configFile, const std::unordered_map<std::string, std::string> &params = {})

Create an world as specified in the xml config file

void exportToXml(const std::string &dir, const std::string &fileName)

export the world to an xml config file, which can be loaded using a constructor

Parameters
  • dir[in] directory to save the xml file

  • fileName[in] file name

inline void exportToXml(const std::string &pathIn)

export the world to an xml config file, which can be loaded using a constructor

Parameters

path[in] path to save the xml file

inline void setTimeStep(double dt)

set the time step

Parameters

dt[in] the time step

inline double getTimeStep() const
Returns

the time step

Sphere *addSphere(double radius, double mass, const std::string &material = "default", CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • radius[in] radius

  • mass[in] mass

  • material[in] material of the height map (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”.

Returns

pointer to the created box

Box *addBox(double xLength, double yLength, double zLength, double mass, const std::string &material = "default", CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • xLength[in] x dimension

  • yLength[in] y dimension

  • zLength[in] z dimension

  • mass[in] mass

  • material[in] material of the height map (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”.

Returns

pointer to the created box

Cylinder *addCylinder(double radius, double height, double mass, const std::string &material = "default", CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • radius[in] radius

  • height[in] center-to-center distance

  • mass[in] mass

  • material[in] material of the height map (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”.

Returns

pointer to the created cylinder

Capsule *addCapsule(double radius, double height, double mass, const std::string &material = "default", CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • radius[in] radius

  • height[in] center-to-center distance

  • mass[in] mass

  • material[in] material of the height map (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”.

Returns

pointer to the created capsule

Ground *addGround(double zHeight = 0.0, const std::string &material = "default", CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • zHeight[in] height of the terrain

  • material[in] material of the height map (which defines the contact dynamics)

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”. Note that collision group of a static object is CollisionGroup(1) << 61ul

Returns

pointer to the created ground

HeightMap *addHeightMap(size_t xSamples, size_t ySamples, double xSize, double ySize, double centerX, double centerY, const std::vector<double> &height, const std::string &material = "default", CollisionGroup collisionGroup = RAISIM_STATIC_COLLISION_GROUP, CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • xSamples[in] how many points along x axis

  • ySamples[in] how many points along y axis

  • xSize[in] x width of the height map

  • ySize[in] y length of the height map

  • centerX[in] x coordinate of the center of the height map

  • centerY[in] y coordinate of the center of the height map

  • height[in] a vector of doubles representing heights. the size should be xSample X ySamples

  • material[in] material of the height map (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

Returns

pointer to the created height map

HeightMap *addHeightMap(const std::string &raisimHeightMapFileName, double centerX, double centerY, const std::string &material = "default", CollisionGroup collisionGroup = RAISIM_STATIC_COLLISION_GROUP, CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • raisimHeightMapFileName[in] the raisim text file which will be used to create the height map

  • centerX[in] x coordinate of the center of the height map

  • centerY[in] y coordinate of the center of the height map

  • material[in] material of the height map (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

Returns

pointer to the created height map

HeightMap *addHeightMap(const std::string &pngFileName, double centerX, double centerY, double xSize, double ySize, double heightScale, double heightOffset, const std::string &material = "default", CollisionGroup collisionGroup = RAISIM_STATIC_COLLISION_GROUP, CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • pngFileName[in] the png file which will be used to create the height map

  • centerX[in] x coordinate of the center of the height map

  • centerY[in] y coordinate of the center of the height map

  • xSize[in] x width of the height map

  • ySize[in] y length of the height map

  • heightScale[in] a png file (if 8-bit) has pixel values from 0 to 255. This parameter scales the pixel values to the actual height

  • heightOffset[in] height of the 0-value pixel

  • material[in] material of the height map (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

Returns

pointer to the created height map

HeightMap *addHeightMap(double centerX, double centerY, TerrainProperties &terrainProperties, const std::string &material = "default", CollisionGroup collisionGroup = RAISIM_STATIC_COLLISION_GROUP, CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • centerX[in] x coordinate of the center of the height map

  • centerY[in] y coordinate of the center of the height map

  • terrainProperties[in] perlin noise parameters which will be used to create the height map

  • material[in] material of the height map (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

Returns

pointer to the created height map

HeightMap *addHeightMap(const HeightMap *heightmapToBeCloned, CollisionGroup collisionGroup = RAISIM_STATIC_COLLISION_GROUP, CollisionGroup collisionMask = CollisionGroup(-1))
Parameters
  • heightmapToBeCloned[in] Another height map to be cloned

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

Returns

pointer to the created height map

ArticulatedSystem *addArticulatedSystem(const std::string &filePathOrURDFScript, const std::string &resPath = "", const std::vector<std::string> &jointOrder = {}, CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1), ArticulatedSystemOption options = ArticulatedSystemOption())
Parameters
  • filePathOrURDFScript[in] Path to urdf file or a URDF string. Depending on the contents of the string, RaiSim will interpret it as an xml string or a file path.

  • resPath[in] Path to the resource directory. Leave it empty (“”) if it is the urdf file directory

  • jointOrder[in] this can be used to redefine the joint order. A child cannot precede its parent. Leave it empty ({}) to use the joint order defined in the URDF file.

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

  • options[in] Currently only support “doNotCollideWithParent”

Returns

pointer to the articulated system

ArticulatedSystem *addArticulatedSystem(const std::string &xmlFileTemplate, const std::unordered_map<std::string, std::string> &params, const std::string &resPath = "", const std::vector<std::string> &jointOrder = {}, CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1), ArticulatedSystemOption options = ArticulatedSystemOption())
Parameters
  • xmlFileTemplate[in] xml template file.

  • params[in] parameters for the xml file.

  • resPath[in] Path to the resource directory. Leave it empty (“”) if it is the urdf file directory

  • jointOrder[in] this can be used to redefine the joint order. A child cannot precede its parent. Leave it empty ({}) to use the joint order defined in the URDF file.

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

  • options[in] Currently only support “doNotCollideWithParent”

Returns

pointer to the articulated system

ArticulatedSystem *addArticulatedSystem(const Child &child, const std::string &resPath = "", CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1), ArticulatedSystemOption options = ArticulatedSystemOption())

This method programmatically creates an articulated system without an URDF file.

Parameters
  • child[in] an instance of Child class which has an articulated system structure.

  • resPath[in] Path to the resource directory. Leave it empty (“”) if it is the urdf file directory

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

  • options[in] Currently only support “doNotCollideWithParent”

Returns

pointer to the articulated system

Compound *addCompound(const std::vector<Compound::CompoundObjectChild> &children, double mass, Vec<3> COM, const Mat<3, 3> &inertia, CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1))

Add a single body which is composed of multiple primitive collision shapes

Parameters
  • children[in] a vector of CompoundObjectChild which contains each primitive shape’s position, orientation, material and shape parameters

  • mass[in] mass of the composite body

  • COM[in] center of the composite body

  • inertia[in] inertia of the composite body

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

Returns

pointer to the created compound object

Mesh *addMesh(const std::string &meshFileInObjFormat, double mass, const Mat<3, 3> &inertia, const Vec<3> &COM, double scale = 1, const std::string &material = "", CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1))

create mesh collision body. only the obj format is supported

Parameters
  • meshFileInObjFormat[in] obj file of the mesh

  • mass[in] mass

  • inertia[in] inertia

  • COM[in] the center of the mass

  • scale[in] rescale the mesh

  • material[in] material of the mesh (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

Returns

pointer to the created wire

Mesh *addMesh(const std::string &meshFileInObjFormat, double mass, double scale = 1, const std::string &material = "", CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1))

create mesh collision body. only the obj format is supported. Inertia and COM are estimated from the mesh geometry assuming that it is a box.

Parameters
  • meshFileInObjFormat[in] obj file of the mesh

  • mass[in] mass

  • scale[in] rescale the mesh

  • material[in] material of the mesh (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

Returns

pointer to the created wire

Mesh *addMesh(const Mesh *meshToClone, const std::string &material = "", CollisionGroup collisionGroup = 1, CollisionGroup collisionMask = CollisionGroup(-1))

create mesh collision body. only the obj format is supported

Parameters
  • meshToClone[in] mesh to copy

  • material[in] material of the mesh (which defines the contact dynamics)

  • collisionGroup[in] read “Contact and Collision/ Collision Group and Mask”

  • collisionMask[in] read “Contact and Collision/ Collision Group and Mask”

Returns

pointer to the created wire

StiffLengthConstraint *addStiffWire(Object *obj1, size_t localIdx1, Vec<3> pos1_b, Object *obj2, size_t localIdx2, Vec<3> pos2_b, double length)

Stiff unilateral constraint. It cannot push. It can only pull.

Parameters
  • obj1[in] the first object the wire is attached to

  • localIdx1[in] the body index (0 for a SingleBodyObject) for the first object

  • pos1_b[in] location of the cable attachment on the first object

  • obj2[in] the second object the wire is attached to

  • localIdx2[in] the body index (0 for a SingleBodyObject) for the second object

  • pos2_b[in] location of the cable attachment on the second object

  • length[in] length of the wire

Returns

pointer to the created wire

CompliantLengthConstraint *addCompliantWire(Object *obj1, int localIdx1, Vec<3> pos1_b, Object *obj2, int localIdx2, Vec<3> pos2_b, double length, double stiffness)

soft unilateral constraint. It cannot push. It can only pull.

Parameters
  • obj1[in] the first object the wire is attached to

  • localIdx1[in] the body index (0 for a SingleBodyObject) for the first object

  • pos1_b[in] location of the cable attachment on the first object

  • obj2[in] the second object the wire is attached to

  • localIdx2[in] the body index (0 for a SingleBodyObject) for the second object

  • pos2_b[in] location of the cable attachment on the second object

  • length[in] length of the wire

  • stiffness[in] stiffness of the wire

Returns

pointer to the created wire

CustomLengthConstraint *addCustomWire(Object *obj1, int localIdx1, Vec<3> pos1_b, Object *obj2, int localIdx2, Vec<3> pos2_b, double length)

Custom wire that applies user-set tension between two points.

Parameters
  • obj1[in] the first object the wire is attached to

  • localIdx1[in] the body index (0 for a SingleBodyObject) for the first object

  • pos1_b[in] location of the cable attachment on the first object

  • obj2[in] the second object the wire is attached to

  • localIdx2[in] the body index (0 for a SingleBodyObject) for the second object

  • pos2_b[in] location of the cable attachment on the second object

  • length[in] length of the wire. You can use this to compute how much it stretched from a nominal length. It might not be necessary for some wire types.

Returns

pointer to the created wire

Object *getObject(const std::string &name)
Returns

object with the given name. returns nullptr if the object doesn’t exist. The name can be set by Object::setName()

inline Object *getObject(std::size_t worldIndex)
Returns

object with the given index. This index can be retrieved by Object::getIndexInWorld()

std::vector<Object*> &getObjList()
Returns

returns a non-const vector of the objects

Constraints *getConstraint(const std::string &name)
Returns

a constraint (e.g., wires) with the given name. returns nullptr if the object doesn’t exist. The name can be set by Wire::setName(). This is equivalent to getWire(const std::string&)

LengthConstraint *getWire(const std::string &name)
Returns

a wire with the given name. returns nullptr if the object doesn’t exist. The name can be set by Wire::setName()

inline unsigned long getConfigurationNumber()
Returns

the configuration number. this number is updated every time an object is added or removed

const RayCollisionList &rayTest(const Eigen::Vector3d &start, const Eigen::Vector3d &direction, double length, bool closestOnly = true, size_t objectId = size_t(-10), size_t localId = size_t(-10), CollisionGroup collisionMask = CollisionGroup(-1))

Returns the internal reference of the ray collision list it contains the geoms (position, normal, object world/local id) and the number of intersections This returns

Parameters
  • start[in] The start position of the ray.

  • direction[in] The direction of the ray.

  • length[in] The length of the ray.

  • closestOnly[in] Only stores the first collision.

  • objectId[in] Collision with objects with both matching objectId and localId will be ignored. This can be useful if the sensor is attached to a robot.

  • localId[in] Collision with objects with both matching objectId and localId will be ignored. This can be useful if the sensor is attached to a robot.

  • collisionMask[in] Collision mask to filter collisions. By default, it records collisions with all collision groups.

Returns

A reference to the internal container which contains all ray collisions.

void removeObject(Object *obj)

removes an object

Parameters

obj[in] object to be removed

void removeObject(LengthConstraint *wire)

removes a wire (i.e., LengthConstraint)

Parameters

wire[in] the wire to be removed

void integrate()

integrate the world It is equivalent to “integrate1(); integrate2();”

void integrate1()

It performs 1) deletion contacts from previous time step 2) collision detection 3) register contacts to each body 4) calls “preContactSolverUpdate1()” of each object

void integrate2()

It performs 1) calls “preContactSolverUpdate2()” of each body 2) run collision solver 3) calls “integrate” method of each object

inline const contact::ContactProblems *getContactProblem() const

It performs 1) calls “preContactSolverUpdate2()” of each body 2) run collision solver 3) calls “integrate” method of each object

void setGravity(const Vec<3> &gravity)

Set gravity

Parameters

gravity[in] gravitational acceleration of the world

void updateMaterialProp(const MaterialManager &prop)

this deletes the existing material props and replace them with the argument

Parameters

prop – new material prop

void setMaterialPairProp(const std::string &mat1, const std::string &mat2, double friction, double restitution, double resThreshold)

Add a new material pair property. In RaiSim, material property is defined by the pair.

Parameters
  • mat1[in] name of the first material (the order of mat1 and mat2 is not important)

  • mat2[in] name of the first material

  • friction[in] the coefficient of friction

  • restitution[in] the coefficient of restitution

  • resThreshold[in] the minimum impact velocity to make the object bounce

void setMaterialPairProp(const std::string &mat1, const std::string &mat2, double friction, double restitution, double resThreshold, double staticFriction, double staticFrictionThresholdVelocity)

Add a new material pair property. In RaiSim, material property is defined by the pair.

Parameters
  • mat1[in] name of the first material (the order of mat1 and mat2 is not important)

  • mat2[in] name of the first material

  • friction[in] the dynamic coefficient of friction

  • restitution[in] the coefficient of restitution

  • resThreshold[in] the minimum impact velocity to make the object bounce

  • staticFriction[in] the static coefficient of friction

  • staticFrictionThresholdVelocity[in] if the relative velocity of two points is bigger than this value, then the dynamic coefficient of friction is applied. Otherwise, the coefficient of friction is interpolated between the static and dynamic one proportional to the relative velocity.

void setDefaultMaterial(double friction, double restitution, double resThreshold)

this default material property is used if a material pair property is not defined for the specific collision

Parameters
  • friction[in] the coefficient of friction

  • restitution[in] the coefficient of restitution

  • resThreshold[in] the minimum impact velocity to make the object bounce

void setDefaultMaterial(double friction, double restitution, double resThreshold, double staticFriction, double staticFrictionThresholdVelocity)

this default material property is used if a material pair property is not defined for the specific collision

Parameters
  • friction[in] the coefficient of friction

  • restitution[in] the coefficient of restitution

  • resThreshold[in] the minimum impact velocity to make the object bounce

  • staticFriction[in] the static coefficient of friction

  • staticFrictionThresholdVelocity[in] if the relative velocity of two points is bigger than this value, then the dynamic coefficient of friction is applied. Otherwise, the coefficient of friction is interpolated between the static and dynamic one proportional to the relative velocity.

inline const Vec<3> &getGravity() const
Returns

gravitational acceleration of the world

void setERP(double erp, double erp2 = 0)

Changes the Error Reduction Parameter. It often has very minimalistic impact on simulation

Parameters
  • erp[in] spring constant between object. This constant is scaled by the apparent inertia so it has no well-defined physical meaning

  • erp2[in] damping constant between object. This constant is scaled by the apparent inertia so it has no well-defined physical meaning

void setContactSolverParam(double alpha_init, double alpha_min, double alpha_decay, int maxIter, double threshold)

Changes the contact solver parameter. For details, please check “Hwangbo, Jemin, Joonho Lee, and Marco Hutter. “Per-contact iteration method for solving contact dynamics.” IEEE Robotics and Automation Letters 3.2 (2018): 895-902.” We found that the three default alpha values are always the best. So they are hardcoded now. So only the maxIter and threshold will affect the simulation. The three input alpha values will be ignored

Parameters
  • alpha_init[in] NOT_USED_ANYMORE (default: 1.0) how aggressive the solver is initially

  • alpha_min[in] NOT_USED_ANYMORE (default: 1.0) how aggressive the solver is after an infinite number of solver iterations

  • alpha_decay[in] NOT_USED_ANYMORE (default: 1.0) how fast alpha converges from alpha_init to alpha_min

  • threshold[in] (default: 1e-8) error threshold for termination

  • maxIter[in] (default: 150) the maximum number of iterations allowed

inline double getWorldTime() const
Returns

the total integrated time (which is updated at every integrate2() call)

inline void setWorldTime(double time)

manually adjust the world time

Parameters

time[in] the world time

inline raisim::contact::BisectionContactSolver &getContactSolver()
Returns

a non-const ref of the contact solver. contact::BisectionContactSolver::setOrder(bool) can be used to make the solver deterministic

inline void setContactSolverIterationOrder(bool order)

This sets the iteration order (e.g., forward and backward) of the contact solver. Given this order, Raisim is deterministic. Without an explicit order, the order flips in every integrate call.

Parameters

order

inline const raisim::contact::BisectionContactSolver &getContactSolver() const
Returns

a const ref of the contact solver. Internal states can be retrieved using this method

inline const std::string &getConfigFile()

get the config file if the world was created using a xml config file

Returns

the path to the xml config file

inline std::vector<std::unique_ptr<LengthConstraint>> &getWires()

get a vector wires in the world

Returns

a vector of unique_ptrs of wires

inline const MaterialPairProperties &getMaterialPairProperties(const std::string &mat1, const std::string &mat2) const

get the material pair properties. The order of materials does not matter.

Parameters
  • mat1[in] material name

  • mat2[in] material name

Returns

material pair properties

inline void lockMutex()

locks world mutex. This can be used if you use raisim in a multi-threaded environment.

inline void unlockMutex()

unlock world mutex. This can be used if you use raisim in a multi-threaded environment.

Public Static Functions

static inline void setActivationKey(const std::string &activationKey)

export the world to an xml config file, which can be loaded using a constructor

Parameters

activationKey[in] path to the license file