SDF worlds#
In this tutorial we will learn how to build our world using SDF, and how to add models to it. Open your text editor and add code as you follow along with this tutorial. You can also download the finished world for this tutorial from here.
Defining a world#
Every SDF world starts with these tags.
<?xml version="1.0" ?>
<sdf version="1.8">
<world name="world_demo">
...
...
</world>
</sdf>
The first two tags define the version of the XML
and the SDF
. Then we have the <world> </world>
tags between which everything goes.
Physics#
<physics name="1ms" type="ignored">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
</physics>
The physics tag specifies the type and properties of the dynamic engine. We chose the name
1ms
as the step size is 1 millisecond. The type
is the type of the dynamic engine (physics library). There are options like, Ode, Bullet, Simbody and Dart. We set it to ignored
, as choosing the type of the physics engine is not done through this tag yet.
<max_step_size>
is the maximum time at which every system in simulation can interact with the states of the world. The smaller the value, the more accurate your calculations, but more computation power is needed.
<real_time_factor>
is the ratio of simulation time to real time.
Plugins#
Plugins are a dynamically loaded chunk of code. For example:
<plugin
filename="gz-sim-physics-system"
name="gz::sim::systems::Physics">
</plugin>
The Physics
plugin is very important for simulating the dynamics of the world.
<plugin
filename="gz-sim-user-commands-system"
name="gz::sim::systems::UserCommands">
</plugin>
The UserCommands
plugin is responsible for creating models, moving models, deleting them and many other user commands.
<plugin
filename="gz-sim-scene-broadcaster-system"
name="gz::sim::systems::SceneBroadcaster">
</plugin>
SceneBroadcaster
shows our world scene.
GUI#
Now let’s define the GUI. Under the <gui>
tag we specify anything related to the GUI
of Gazebo.
<gui fullscreen="0">
...
...
</gui>
gazebo-gui has a bunch of plugins to choose from. We will add the ones that are necessary to get our world up and running with basic functionality.
<!-- 3D scene -->
<plugin filename="MinimalScene" name="3D View">
<gz-gui>
<title>3D View</title>
<property type="bool" key="showTitleBar">false</property>
<property type="string" key="state">docked</property>
</gz-gui>
<engine>ogre2</engine>
<scene>scene</scene>
<ambient_light>0.4 0.4 0.4</ambient_light>
<background_color>0.8 0.8 0.8</background_color>
<camera_pose>-6 0 6 0 0.5 0</camera_pose>
<camera_clip>
<near>0.25</near>
<far>25000</far>
</camera_clip>
</plugin>
<plugin filename="GzSceneManager" name="Scene Manager">
<gz-gui>
<property key="resizable" type="bool">false</property>
<property key="width" type="double">5</property>
<property key="height" type="double">5</property>
<property key="state" type="string">floating</property>
<property key="showTitleBar" type="bool">false</property>
</gz-gui>
</plugin>
MinimalScene
and GzSceneManager
are responsible for displaying the 3D scene of our world.
It has the following properties (most of the GUI plugins have them):
showTitleBar
if true it will show the blue title bar over the plugin with the name mentioned in the<title>
tag.state
is the state of the plugin it can be docked in its place usingdocked
or it can befloating
.
For the rendering engine we can choose ogre
or ogre2
. The <ambient_light>
and the <background_color>
specify the ambient and the background color of the scene. <camera_pose>
specifies the X Y Z
position of the camera followed by its rotation in Roll Pitch Yaw
.
World control plugin#
<!-- World control -->
<plugin filename="WorldControl" name="World control">
<gz-gui>
<title>World control</title>
<property type="bool" key="showTitleBar">false</property>
<property type="bool" key="resizable">false</property>
<property type="double" key="height">72</property>
<property type="double" key="width">121</property>
<property type="double" key="z">1</property>
<property type="string" key="state">floating</property>
<anchors target="3D View">
<line own="left" target="left"/>
<line own="bottom" target="bottom"/>
</anchors>
</gz-gui>
<play_pause>true</play_pause>
<step>true</step>
<start_paused>true</start_paused>
<service>/world/world_demo/control</service>
<stats_topic>/world/world_demo/stats</stats_topic>
</plugin>
The World control
plugin is responsible for controlling the world. Some of its properties are the following:
<play_pause>
iftrue
we will have the play-pause button on the bottom left corner.<stats_topic>
tag specifies the topic at which the world stats like simulation time and real time are published on.<start_paused>
iftrue
the simulation will be paused at the start of Gazebo.
World stats plugin#
<!-- World statistics -->
<plugin filename="WorldStats" name="World stats">
<gz-gui>
<title>World stats</title>
<property type="bool" key="showTitleBar">false</property>
<property type="bool" key="resizable">false</property>
<property type="double" key="height">110</property>
<property type="double" key="width">290</property>
<property type="double" key="z">1</property>
<property type="string" key="state">floating</property>
<anchors target="3D View">
<line own="right" target="right"/>
<line own="bottom" target="bottom"/>
</anchors>
</gz-gui>
<sim_time>true</sim_time>
<real_time>true</real_time>
<real_time_factor>true</real_time_factor>
<iterations>true</iterations>
<topic>/world/world_demo/stats</topic>
</plugin>
The World stats
plugin is responsible for displaying the world statistics,
<sim_time>
, <real_time>
, <real_time_factor>
and <iterations>
.
With these tags we can choose what values to display (expand the bottom right corner to see these values). We can choose which <topic>
these values will be published on. Let’s try to run the world and listen to that topic.
Run the world:
gz sim world_demo.sdf
Press the play button and in another terminal listen to the messages:
gz topic -e -t /world/world_demo/stats
The message should look like this:
Entity tree#
<!-- Entity tree -->
<plugin filename="EntityTree" name="Entity tree">
</plugin>
In this plugin we can see all the entities of our world (everything in simulation is considered an “entity”). We can see the different models, sun and also their links, visuals and collisions.
It is blank because we didn’t add anything to our world yet.
There are a bunch of useful gz-gui plugins like the Transform control
plugin that allows us to manipulate different components of our world, and translate and rotate the entities. Check out this tutorial explaining how to manipulate models.
The plugins can also be added from the GUI using the plugin drop-down menu in the top right corner of Gazebo. Now that we are done with the GUI, let’s add different elements to our world. Don’t forget to add the closing tag </gui>
.
Light#
<light type="directional" name="sun">
<cast_shadows>true</cast_shadows>
<pose>0 0 10 0 0 0</pose>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<attenuation>
<range>1000</range>
<constant>0.9</constant>
<linear>0.01</linear>
<quadratic>0.001</quadratic>
</attenuation>
<direction>-0.5 0.1 -0.9</direction>
</light>
<light>
specifies the light source in the world. The<type>
of the light can bepoint
,directional
orspot
.<pose>
is the position (x,y,z) and orientation (roll, pitch, yaw) of the light element with respect to the frame mentioned in therelative_to attribute
; in our case (relative_to
attribute is ignored) it is relative to the world.<cast_shadows>
when true the light will cast shadows.<diffuse>
and<specular>
are the diffuse and specular light color.<attenuation>
specifies the light attenuation properties, which are:<range>
is range of light.<constant>
is the constant attenuation factor,1
never attenuate and0
complete attenuation.<linear>
is the linear attenuation factor,1
means attenuate evenly over the distance.<quadratic>
is the quadratic attenuation factor. It adds curvature to the attenuation.<direction>
is direction of the light, only applicable to spot and directional light.
Adding models#
Instead of building our own models we can use already built ones. Gazebo Fuel hosts hundreds of models that can easily be added to an Gazebo world. Models can be added as follows.
Spawning a model#
For adding various models from fuel to your world chekout this tutorial.
Include the model URI#
Another way of adding the model to your world is to use the model link. Visit the Gazebo Fuel website. Choose the model you like and click on the <>
icon on the model description page. This will copy an SDF snippet to your clipboard, then paste it in your world right above the closing </world>
tag, like this:
<include>
<uri>
https://fuel.gazebosim.org/1.0/OpenRobotics/models/Coke
</uri>
</include>
Download the model#
The previous methods download your model on run time. For saving the model permanently you can download the model from fuel, and then refer to it like this:
<include>
<uri>
model://Coke
</uri>
</include>
We need to set GZ_SIM_RESOURCE_PATH
environment variable to the parent folder of our model. For example, if our directory looks like this:
world_tutorial<br/>
├── Coke <br/>
└── world_demo.sdf
Then we have to set it to the world_tutorial
directory, like this:
export GZ_SIM_RESOURCE_PATH="$HOME/world_tutorial"
Run your world:
gz sim world_demo.sdf
You should see the model in the origin of the world.
You can also set its coordinates using the <pose>
tag.
If you want to spawn multiple instances of the same model you must give them different names with the <name>
tag.
<include>
<name>Coke0</name>
<pose>0 0 0 0 0 0</pose>
<uri>https://fuel.gazebosim.org/1.0/OpenRobotics/models/Coke</uri>
</include>
<include>
<name>Coke1</name>
<pose>0 0.1 0 0 0 0</pose>
<uri>https://fuel.gazebosim.org/1.0/OpenRobotics/models/Coke</uri>
</include>
Now that you have a custom world, the next tutorial will teach you how to add sensors to a robot to allow it to interact with the world around it.
Video walk-through#
A video walk-through of this tutorial is available from our YouTube channel: Gazebo tutorials: Creating worlds.