Webots Reference Manual - chapter 6 - section 3

Webots Reference Manual


6.3 Callback Functions

The plugin code must contain user-implemented functions that will be called by Webots during the simulation. These user-implemented functions and their interfaces are described in this section. The implementation of the webots_physics_step() and webots_physics_cleanup() functions is mandatory. The implementation of the other callback functions is optional.

6.3.1 void webots_physics_init(dWorldID, dSpaceID, dJointGroupID)

This function is called upon initialization of the world. It provides your physics plugin with some global ODE variables used by the simulation, such as a pointer to the world (dWorldID), a pointer to the geometry space (dSpaceID) and a pointer to the contact joints group (dJointGroupID). These parameters should generally be stored in global variables in order to be used later by the other callback functions. This function is a good place to call the dWebotsGetBodyFromDEF() and dWebotsGetGeomFromDEF() functions (see below for details) to get pointers to the objects for which you want to control the physics. Before calling this function, Webots sets the current directory to where the plugin's .dll, .so or .dylib was found. This is useful for reading config files or writing log files in this directory.

This function is also the preferred place to initialize/reinitialize the random number generator (via srand()). Reinitializing the generator with a constant seed allows Webots to run reproducible (deterministic) simulations. If you don't need deterministic behavior you should initialize srand() with the current time: srand(time(NULL)). Webots itself does not invoke srand(); however, it uses rand(), for example to add noise to sensor measurements. In order to have reproducible simulations, it is also required that all controllers run in synchronous mode. That means that the synchronization field of every Robot, DifferentialWheels or Supervisor must be set to TRUE. Finally, note that ODE uses its own random number generator that you might also want to reinitialize separately via the dRandSetSeed() function.

6.3.2 int webots_physics_collide(dGeomID, dGeomID)

This function is called whenever a collision occurs between two geoms. It may be called several times (or not at all) during a single simulation step, depending on the number of collisions. Generally, you should test whether the two colliding geoms passed as arguments correspond to objects for which you want to control the collision. If you don't wish to handle a particular collision you should return 0 to inform Webots that the default collision handling code must be used.

Otherwise you should use ODE's dCollide() function to find the contact points between the colliding objects and then you can create contact joints using ODE's dJointCreateContact() function. Normally the contact joints should be created within the contact joint group passed as argument to the webots_physics_init() function. Note that this contact joint group is automatically emptied after each simulation step, see here. Then the contact joints should be attached to the corresponding bodies in order to prevent them from inter-penetrating. Finally, the webots_physics_collide() function should return 1 to inform Webots that this collision was handled.

An implementation example for this function is provided in the projects/robots/shrimp/plugins/physics/shrimp/shrimp.c file.

6.3.3 void webots_physics_step()

This function is called before every physics simulation step (call to the ODE dWorldStep() function). For example it can contain code to read the position and orientation of bodies or add forces and torques to bodies.

6.3.4 void webots_physics_step_end()

This function is called right after every physics simulation step (call to the ODE dWorldStep() function). It can be used to read values out of dJointFeedback structures. ODE's dJointFeedback structures are used to know how much torque and force is added by a specific joint to the joined bodies (see ODE User Guide for more information). For example, if the plugin has registered dJointFeedback structures (using ODE's function dJointSetFeedback()), then the structures will be filled during dWorldStep() and the result can be read straight afterwards in webots_physics_step_end().

6.3.5 void webots_physics_cleanup()

This function is the counterpart to the webots_physics_init() function. It is called once, when the world is destroyed, and can be used to perform cleanup operations, such as closing files and freeing the objects that have been created in the plugin.

6.3.6 void webots_physics_draw()

This function is used to add user-specified OpenGL graphics to the 3D view. For example, this can be used to draw robots trajectories, force vectors, etc. This function is called right after the regular OpenGL rendering of the world. The function should normally contain OpenGL function calls. Here is an implementation example:

void webots_physics_draw() {
  /* modify OpenGL context */
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_LIGHTING);
  glLineWidth(2.0);

  /* draw 1 meter yellow line */
  glBegin(GL_LINES);
  glColor3f(1, 1, 0);
  glVertex3f(0, 0, 0);
  glVertex3f(0, 1, 0);
  glEnd();
}

The above example will draw a meter high yellow line in the center of the world. Note that Webots loads the world (global) coordinates matrix right before calling this function. Therefore the arguments passed to glVertex() are expected to be specified in world coordinates. Note that the default OpenGL states should be restored before leaving this function otherwise the rendering in Webots 3D view may be altered.

6.3.7 void webots_physics_predraw()

This function is similar to webots_physics_draw(), except that it is called before the world is displayed. It may be useful, for example, for drawing solid objects visible through transparent or semi-transparent objects in the world.

release 7.0.2
Copyright © 2012 Cyberbotics Ltd. All right reserved.