Gazebo Physics

API Reference

6.5.1
Use a custom engine with Gazebo Physics

Prerequisites

How to interface with physics engine

In the previous Implement custom feature tutorial, we walked through how to define and implement a custom feature using an already supported physics engine. This tutorial will explain step-by-step how to interface with any physics engine using Gazebo Physics. We will use TPE as an example in this tutorial.

Structure of a physics plugin

Depending on what physics engine you would like to use, the folder structure could be slightly different from what's shown below. Here's the plugin folder structure of TPE, within the Gazebo Physics library.

gz-physics
├── tpe
│ ├── plugin Implementation of the plugin features interfacing the physics engines API
│ │ ├── src
│ │ | ├── plugin.cc Main file for the plugin declaration and plugin registering.
│ │ | ├── <FEATURES>.hh The FeatureList header file.
│ │ | ├── <FEATURES>.cc Implementation of the FeatureList using physics engine API
│ │ | └── <FEATURES_TEST>.cc Tests
│ │ └── CMakeLists.txt CMake build script for the plugin features.
│ └── CMakeLists.txt CMake build script for the plugin.
└── CMakeList.txt CMake build script for Gazebo Physics library.

We link the external physics engine library in CMakeLists.txt of the plugin, assuming the physics engine library is already installed. In our case, TPE is placed inside Gazebo Physics and hence there is a lib folder under tpe.

We declare and implement the FeatureList interfacing with the physics engine API inside plugin/src folder (please see Implement custom feature for the plugin feature requirements). Depending on design target, a FeatureList is generally a packing of related Features. For example in TPE's EntityManagementFeatures , there are GetEngineInfo, GetWorldFromEngine, etc. features defined in the "FeatureList" structure for entity management purpose.

Conventionally, a FeatureList can be implemented as:

  • <FEATURES>.hh for the "FeatureList" declaration.
  • <FEATURES>.cc for the "FeatureList" implementation corresponding to each of the Features member functions, using the physics engine API to realize the feature behavior. For a list of common pre-defined features in Gazebo Physics, please refer to Understand physics plugin tutorial.
  • <FEATURES_TEST>.cc for unit tests of the "FeatureList".

Next, we will use a simplified TPE plugin example to explain important components needed to interface with any physics engine. All code examples used below can be downloaded from examples under the simple_plugin folder:

simple_plugin
├── CMakeLists.txt
├── plugin.cc
├── EntityManagementFeatures.hh
├── EntityManagementFeatures.cc
└── EntityManagementFeatures_TEST.cc

plugin.cc

In this tutorial, we will show how to construct a simple simulation world using TPE physics engine. For this purpose, we will implement the pre-defined ConstructEmptyWorldFeature and include this feature into an empty FeatureList named EntityManagementFeatureList defined in EntityManagementFeatures.hh. We first include the EntityManagementFeatureList in plugin.cc main file and register the example TPE physics plugin as follow:

namespace gz {
namespace physics {
namespace simpleplugin {
struct SimplePluginFeatures : FeatureList<
EntityManagementFeatureList
> { };
class Plugin :
public virtual EntityManagementFeatures,
public virtual Implements3d<SimplePluginFeatures>
{
using Identity = gz::physics::Identity;
public: Identity InitiateEngine(std::size_t /*_engineID*/) override
{
return this->GenerateIdentity(0);
}
};
GZ_PHYSICS_ADD_PLUGIN(Plugin, FeaturePolicy3d, SimplePluginFeatures)
}
}
}

Those are 3 things needed to be specified in plugin.cc:

  • Define the conclusive FeatureList including all required "FeatureLists" and Base class. In TPE case, it is TpePluginFeatures.
  • Define the dimension of the simulation, ex. Implements class implementing FeaturePolicy 2D or 3D and different scalar type.
  • Register the physics plugin using GZ_PHYSICS_ADD_PLUGIN macro (See Implement physics plugin for more detail).

Implement features with physics engine's API

Now we would like to implement the EntityManagementFeatures. In the simple_plugin folder, we will create two files EntityManagementFeatures.hh and EntityManagementFeatures.cc to implement a single feature ConstructEmptyWorldFeature in EntityManagementFeatures "FeatureList" using TPE API from tpe/lib in Gazebo Physics library.

Before we dive into the feature implementation, we need to understand how the features are defined.

The ConstructEmptyWorldFeature is declared in a function template file gz-physics/include/gz/physics/ConstructEmpty.hh.

Gazebo Physics library uses function templates to specify features that accept generic types. The use of templates makes it easier to implement features using different physics engine APIs, without having to repeat the entire code for a function.

The ConstructEmptyWorldFeature example here is implemented with TPE API, but a similar feature can also be implemented using DART API.

In this case, we are implementing a feature that is already defined by Gazebo Physics, thus we do not need to write our own template function, and can just include the template in our header file.

But first, let's include the basics:

#include <string>

Then, we include the specific feature template file and add it to the feature list:

namespace gz {
namespace physics {
namespace simpleplugin {
struct EntityManagementFeatureList : FeatureList<
ConstructEmptyWorldFeature
> { };

We also need to declare the feature function in the header file, but since the function is already declared in the template file we just included, we need to override the generic declaration instead:

class EntityManagementFeatures :
public virtual Implements3d<EntityManagementFeatureList>
{
public: Identity ConstructEmptyWorld(
const Identity &_engineID, const std::string &_name) override;
};
}
}
}

The EntityManagementFeatures "FeatureList" here inherits from:

  • (optionally) Base class for foundation metadata definitions of Models, Joints, Links, and Shapes objects of TPE to provide easy access to tpelib structures in the TPE library.
  • Implements3d for implementing the custom feature with FeaturePolicy3d ("FeaturePolicy" of 3 dimensions and scalar type double).

Then we can go ahead with the implementation of ConstructEmptyWorldFeature:

Identity EntityManagementFeatures::ConstructEmptyWorld(
const Identity &, const std::string &_name)
{
// Generate dummy identity
return this->GenerateIdentity(0);
}

Here we show the overriding of ConstructEmptyWorld member function of ConstructEmptyWorldFeature, this is where we use the physics engine API to implement this member function. We simply instantiate World object, set the world name and call AddWorld function which was defined in Base.hh.

Simple unit tests are good practice for sanity checks. While we won't go into detail, here is an example to test our new ConstructEmptyWorldFeature:

struct TestFeatureList : gz::physics::FeatureList<
gz::physics::simpleplugin::EntityManagementFeatureList
> { };
int main(int argc, char *argv[])
{
// Load the custom plugin
loader.LoadLib(simple_plugin_LIB);
auto simplePlugin =
loader.Instantiate("gz::physics::simpleplugin::Plugin");
// Get the engine pointer
auto engine =
if (nullptr == engine)
{
std::cerr << "Something went wrong, the engine is null" << std::endl;
return -1;
}
auto world = engine->ConstructEmptyWorld("empty world");
if (nullptr == world)
{
std::cerr << "Failed to create empty world" << std::endl;
return -1;
}
std::cout << "Created empty world!" << std::endl;
return 0;
}

To get a more comprehensive view of how EntityManagementFeatures are constructed in TPE and Dartsim, feel free to take a look here:

Load and test

Please follow the previous tutorial Installation to build gz-physics from source again for our new feature to be compiled.

Now we can load the new physics plugin named gz-physics-tpe-plugin to test it on Gazebo by following this Use different physics engines tutorial.