This tutorial describes how to use the Preset Manager interface to store physics parameter profiles and switch between them.
Gazebo has many parameters that affect the performance, accuracy, and general behavior of physics simulation. Some are shared between the different physics engines supported by Gazebo, like maximum step size and target real time factor, and some are not. The physics preset manager interface offers a way to easily switch between a set of physics parameters and save them to SDF.
In SDF, a physics profile is simply a <physics>
element. As of SDF protocol version 1.5,
which was introduced in SDFormat version 3,
multiple physics elements are allowed in a world file, but they must be
differentiated by the name
attribute. When there are multiple physics elements
specified, Gazebo will choose the one with the default
attribute set to true.
If no default physics profile is set, Gazebo will choose the first one. If
multiple default profiles are set, Gazebo will choose the first set as default.
In the following world example
(downloadable here),
the ode_200iters
profile is set as the default, and the ode_70iters
and ode_500iters
profiles will be available via the C++ API or the gz
command line tool.
The following is an excerpt from the downloadable world example that shows the values for these profiles.
<sdf version="1.6">
<world name="preset_example">
<include>
<uri>model://sun</uri>
</include>
<gravity>3.0 0 -9.81</gravity>
<physics name="ode_70iters" type="ode">
<real_time_update_rate>1500</real_time_update_rate>
<ode>
<solver>
<type>quick</type>
<iters>70</iters>
</solver>
</ode>
</physics>
<physics name="ode_200iters" type="ode" default="true">
<ode>
<solver>
<type>quick</type>
<iters>200</iters>
</solver>
</ode>
</physics>
<physics name="ode_500iters" type="ode">
<ode>
<solver>
<type>quick</type>
<iters>500</iters>
</solver>
</ode>
</physics>
<!-- end physics presets, models and other world properties go here -->
If you are writing a plugin that switches between profiles, you can use the C++
API to access the PresetManager
to add, remove, and switch between profiles.
You can also get and set profile parameters and generate an SDF element
representing your physics profile.
Here's an example PresetManager
code snippet that would programmatically
construct two of the profiles form the example world shown above in SDF:
physics::WorldPtr world = physics::get_world("default");
// Get the PresetManager object from the world
physics::PresetManagerPtr presetManager = world->PresetMgr();
// Create a new profile called "ode_70iters"
// It will be populated with the default physics parameters
// Many of the PresetManager functions return a boolean for error-checking
if (!presetManager->CreateProfile("ode_70iters"))
{
gzerr << "Couldn't create profile ode_70iters" << std::endl;
return -1;
}
// Create another profile
presetManager->CreateProfile("ode_200iters");
// Set the current profile to "ode_70iters"
presetManager->CurrentProfile("ode_70iters");
// Set the solver type to quickstep in the current profile, checking for errors
// SetCurrentProfileParam will change the current state of the physics engine
if (!presetManager->SetCurrentProfileParam("solver", "quick"))
{
gzerr << "Couldn't set parameter, did you pass a valid key/value pair?"
return -1;
}
// Set the number of iterations in the current profile to 70
presetManager->SetCurrentProfileParam("iters", 70);
// Set parameters in the other profile. These changes will be stored in
// presetManager but will not change the current state of the physics engine
presetManager->SetProfileParam("ode_200iters", "solver", "quick");
presetManager->SetProfileParam("ode_200iters", "iters", 200);
boost::any iters;
// Get the number of iterations from the current profile.
presetManager->GetCurrentProfileParam(iters, "iters");
// GetProfileParam and GetCurrentProfileParam currently return a boost::any,
// which must be casted to the correct type
gzmsg << "Iterations in current preset: " << boost::any_cast<int>(iters);
// Generate an SDF Element from the profile we constructed
sdf::ElementPtr odeQuickProfileSDF =
presetManager->GenerateSDFFromPreset("ode_70iters");
A quicker and more convenient way to switch physics profiles is to use the command line interface.
To start the preset_example
world we made above with a non-default profile,
start gazebo with:
gazebo preset_example_sdf1_6.world --profile ode_70iters
For a shortcut, use -o
:
gazebo preset_example_sdf1_6.world -o ode_70iters
You can also substitute gazebo
with gzserver
to run Gazebo headless
(without the graphical client).
While Gazebo is running, you can switch the profile in another terminal
by using gz physics
:
gz physics --profile ode_200iters
gz physics -o ode_70iters
Download the
world file
preset_example_sdf1_6.world
(same as the SDF example shown above) and the
bash script
switch_profiles_sdf1_6.sh
.
#!/bin/sh
set -x
gazebo --verbose preset_example_sdf1_6.world -o ode_200iters &
echo start with 200 iterations
sleep 5
gz physics -o ode_70iters
echo switch to 70 iterations
echo simulation will go unstable
sleep 5
echo switch back to 200 iterations
gz physics -o ode_200iters
echo reset world
gz world -r
echo open plot window to show link pitch and yaw angles
sleep 10
echo
for i in $(seq 5)
do
gz physics -o ode_500iters
sleep 5
gz physics -o ode_200iters
sleep 5
done
set +x
The script launches Gazebo first with the ode_200iters
profile,
then switches to ode_70iters
and the simulation goes unstable.
The script then switches back to ode_200iters
and resets the world, then switches between
the ode_200iters
and ode_500iters
profiles 5 times, pausing for 5 seconds between each switch.
The difference between these two profiles can be seen when plotting the Pitch and Yaw angles of
upper_link
and lower_link
, since these angles should be zero with a perfect solver.
They are not perfect, but the magnitude of the angles is lower with 500 iterations
as shown in the following image:
The behavior of double pendulum model in this world illustrates the differences between the two physics profiles. A classic double pendulum consists of two links attached by a hinge joint. One of the links is attached to a fixed point via another hinge joint. In this example, the link attached to a fixed point is much smaller, and thus there is a large inertia ratio between the two links, which is significant because the large inertia ratios can cause iterative Projected-Gauss Seidel solvers (the default for gazebo's ODE solver) to converge very slowly (see our conference paper (pdf) or DOI: 10.2312/PE/vriphys/vriphys09/105-114 (pdf)). The world applies a constant force parallel to the rotation axis of the hinge joints (in the x-direction) by setting the x component of gravity to 3.0 meters per second squared. The pendulum should normally move only in the YZ plane, but the lateral force causes the pendulum to wobble in the x direction, due to the lack of sover convergence.
The ode_70iters
profile uses the "quickstep" physics constraint solver, which is faster less accurate.
The large inertia ratio of this model causes the constraint solver to converge slowly, enough to
make the simulation diverge with the pendulum swingly wildly.
This profile is also set to
run with a real time factor of 1.5, which means that simulation runs in "fast motion" while this profile is active.
The ode_200iters
and ode_500iters
profiles also use the "quickstep" solver but with increased iterations,
which gives the solver more time to converge. Thus when the profile switches, you can see the pendulum's motion
stabilize to back and forth behavior in the XZ plane. This profile runs with a real time factor of 1.0, which means
that the time passes as slowly in simulation as it does in real life.
You can also see the physics parameter changes reflected in the GUI. In the left-hand panel, under the "World" tab, click on "Physics" and look at the physics properties of the world change as the script changes profiles. You will have to close and reopen the menu to refresh the GUI.
Use this script as a base for your own experimentation and profiling with the Gazebo physics library!