Gazebo logo

HOWTO: Creating a Plugin Model

The are two distinct type of models in Gazebo:

Plugin models have serveral advantanges over their static counterparts:

Developers are advised to read Coding Standards and Conventions before creating new models.

Plugin Model Example

Sample code for a very basic plugin model in provided in the examples directory; for a default install, this will be:

/usr/local/src/gazebo/examples/plugins/ExampleModel/

Copy the files from this directory and rename Makefile.example to Makefile. Try building the example:

$ make 

This produces a plugin model names ExampleModel.so. You can test the model using the included world file:

$ gazebo ./example.world

The world file model tag has an additional attribute specifying the path to the plugin, i.e.,:

  <model:ExampleModel>
    <plugin>ExampleModel.so</plugin>
    ...
  </model:ExampleModel>

Note that the same plugin can be specified by more than one model.

Note that the server will search for plugin models according to the following algorithm. Given a request to load the plugin <foo>:

  1. If <foo> is an absolute path, then try to load it, and exit with an error if that fails. If <foo> is a relative path, go to (2).
  2. If the environment variable GAZEBOPATH is set, it is interpreted as a colon-separated list of directores; try to load <foo> from each directory in turn. If <foo> is found, great. If not (or if GAZEBOPATH is not set), go to (3).
  3. Try to load <foo> by interpreting it as relative to the directory in which the config file resides. If that doesn't work, go to (4).
  4. Try to load <foo> from <prefix>/lib/gazebo/plugins, where <prefix> is the installation prefix determined at configure time. The default prefix is /usr/local.
If a plugin cannot be loaded, Gazebo quits with an error.

Writing a simple driver

To make a model, create a new class that inherits the Gazebo Model class. This base class defines the standard API that all models must support. The basic elements of the new model class are as follows.

Load(...)
The Load() method is responsible for creating the physical, visual and sensing elements of the model. For a very simple robot model, at least two elements must be created:

The Load() method has two arguments:

The node argument is used to access the worldfile settings for this particular model; one can read user-defined model dimensions, motor settings, update rates and so on using the methods provided in the WorldFileNode class.

Init(...)
The Init() method is called after all models have been loaded, and provides models the opportunity to perform additional initialization. By convention, any libgazebo interfaces supported by the model are allocated at this stage. For example, if the model supports the position interface, the Init() method will create the interface as follows:

this->position = gz_position_alloc();
if (gz_position_create(this->position, this->world->gz_server, this->GetId(),
                       "ExampleModel", (int) this, (int) this->parent) != 0)
  return -1;

Models may support more than one interface at the same time.

Fini(...)
The Fini() method is called when the server exits, an provides models an opportunity to clean up after themselves. By convention, libgazebo interface are deallocated at this time; e.g.:

gz_position_destroy( this->position );
gz_position_free( this->position );
this->position = NULL;

Update(...)
The Update() method is the heart of any model: this function is called periodically by the main simulation loop to update the model state. Note that the physics of the model are handled automatically by the server; the Update() method is generally used to update the libgazebo interface (get new commands and write new data). Since the simulator update rate is a user-settable parameter, models should always check the current simulator time before taking any action. The following idiom is recommended:

if (this->world->GetSimTime() - this->updateTime > this->updatePeriod)
{
  this->updateTime = this->world->GetSimTime();

  // Get commands from the external interface
  this->GetPositionCmd();

  // Set joint motor speeds and/or torques
  ...

  // Update the interface
  this->PutPositionData();
}

Thus, for example, if the device being simulated has a communication frequency of 10Hz, we should only check for new commands (and update outgoing data) once every 100ms. Failure to limit the update rate in this manner will result in a very slow simulation, and/or a poor fidelity simulation. Note also the use of the World::GetSimTime() function; this is the elapsed simulation time, which may be very different from the elapsed real time. Always use the simulation time when updating models.

Other Examples
The following built-in models provide good examples to work from:

Gazebo also makes heavy use of both OpenGL and the ODE (Open Dynamics Engine); the documentation for these projects provides valuable insight into the many important concepts:

Registration and instantiation

In order to use a plugin model, the Gazebo server needs to know two things:

The ModelFactory.hh header provides a macro that will automatically handle model registration and instantiation. Use this macro at the top of the model file:

GZ_REGISTER_PLUGIN("ExampleModel", ExampleModel)

The first argument gives the model name as it appears in the world file; the second argument gives the class name.

Building the shared library

The example model includes a Makefile for building shared objects. To manually build a shared object, try:

$ g++ -Wall -g3 -c ExampleModel.cc
$ g++ -shared -nostartfiles -o ExampleModel.so ExampleModel.o

While the above method will probably work, it is recommended that you use pkg-config to get the compile flags; i.e.,

$ g++ -Wall -g3 `pkg-config --cflags gazebo` -c ExampleModel.cc
$ g++ -shared -nostartfiles -o ExampleModel.so ExampleModel.o

Todo:
  • Add example of building plugin using libtool.

Last updated 12 September 2005 21:38:45