Skip to content

Commit 39e98e1

Browse files
chapulinamjcarroll
andauthored
Tutorial on migrating SDF files from Gazebo classic (#400)
Signed-off-by: Louise Poubel <[email protected]> Co-authored-by: Michael Carroll <[email protected]>
1 parent ebd09d4 commit 39e98e1

File tree

2 files changed

+342
-0
lines changed

2 files changed

+342
-0
lines changed

tutorials.md.in

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Ignition @IGN_DESIGNATION_CAP@ library and how to use the library effectively.
2828
**Migration from Gazebo classic**
2929

3030
* \subpage migrationplugins "Plugins": Walk through the differences between writing plugins for Gazebo classic and Ignition Gazebo
31+
* \subpage migrationsdf "SDF": Migrating SDF files from Gazebo classic to Ignition Gazebo
3132
* \subpage migrationworldapi "World API": Guide on what World C++ functions to call in Ignition Gazebo when migrating from Gazebo classic
3233
* \subpage migrationmodelapi "Model API": Guide on what Model C++ functions to call in Ignition Gazebo when migrating from Gazebo classic
3334
* \subpage migrationlinkapi "Link API": Guide on what Link C++ functions to call in Ignition Gazebo when migrating from Gazebo classic

tutorials/migration_sdf.md

+341
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
\page migrationsdf
2+
3+
# Migration from Gazebo classic: SDF
4+
5+
Both Gazebo classic and Ignition Gazebo support [SDF](http://sdformat.org/)
6+
files to describe the simulation to be loaded. An SDF file defines the world
7+
environment, the robot's characteristics and what plugins to load.
8+
9+
Despite using the same description format, users will note that the same SDF
10+
file may behave differently for each simulator. This tutorial will
11+
explain how to write SDF files in a way that they're as reusable by both
12+
simulators as possible. It will also explain when you'll need to use separate
13+
files for each simulator.
14+
15+
The minimum required versions to use this guide are:
16+
17+
* Gazebo 11.2.0
18+
* Igniton Citadel
19+
20+
## URIs
21+
22+
SDF files use URIs to refer to resources from other files, such as meshes and
23+
nested models. These are some of the SDF tags that take URIs:
24+
25+
* `<include><uri>`
26+
* `<mesh><uri>`
27+
* `<material><pbr><...><*_map>` (only on Ignition)
28+
* `<actor><skin><filename>`
29+
* `<actor><animation><filename>`
30+
31+
Here are the recommended ways to use URIs from most recommended to least:
32+
33+
### Ignition Fuel URL
34+
35+
It's possible to use URLs of resources on
36+
[Ignition Fuel](https://app.ignitionrobotics.org) within any of the tags
37+
above and both simulators will be able to load it.
38+
39+
For example, this world can be loaded into both simulators:
40+
41+
```
42+
<sdf version="1.7">
43+
<world name="demo">
44+
<!-- Included light -->
45+
<include>
46+
<uri>https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/Sun</uri>
47+
</include>
48+
49+
<!-- Included model -->
50+
<include>
51+
<uri>https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/Ground Plane</uri>
52+
</include>
53+
54+
<model name="Radio">
55+
<pose>3 -1.5 0 0 0 0</pose>
56+
<static>true</static>
57+
<link name="link">
58+
<collision name="collision">
59+
<geometry>
60+
<!-- Collision mesh -->
61+
<mesh>
62+
<uri>https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/Radio/4/files/meshes/Radio.dae</uri>
63+
</mesh>
64+
</geometry>
65+
</collision>
66+
<visual name="visual">
67+
<geometry>
68+
<!-- Visual mesh -->
69+
<mesh>
70+
<uri>https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/Radio/4/files/meshes/Radio.dae</uri>
71+
</mesh>
72+
</geometry>
73+
</visual>
74+
</link>
75+
</model>
76+
77+
<actor name="actor_talking">
78+
<skin>
79+
<filename>https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/actor - relative paths/tip/files/meshes/talk_b.dae</filename>
80+
<scale>1.0</scale>
81+
</skin>
82+
<animation name="talk_b">
83+
<filename>https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/actor - relative paths/tip/files/meshes/talk_b.dae</filename>
84+
<scale>1.0</scale>
85+
</animation>
86+
<script>
87+
<loop>true</loop>
88+
<auto_start>true</auto_start>
89+
<trajectory id="0" type="talk_b">
90+
<waypoint>
91+
<time>0</time>
92+
<pose>2 -2 0.5 0 0 0</pose>
93+
</waypoint>
94+
<waypoint>
95+
<time>5</time>
96+
<pose>2 -2 0.5 0 0 0</pose>
97+
</waypoint>
98+
</trajectory>
99+
</script>
100+
</actor>
101+
102+
</world>
103+
</sdf>
104+
```
105+
106+
\note The actor's vertical pose will be different on both simulators.
107+
That's because a hardcoded offset was removed on Ignition and
108+
maintained on Gazebo classic for backwards compatibility.
109+
110+
### Path relative to the SDF file
111+
112+
It's possible to use relative paths within SDF files to refer to other files
113+
in the same directory. This is recommended when creating files that work
114+
together and need to be relocatable.
115+
116+
For example, consider the following directory structure:
117+
118+
```
119+
/home/username/
120+
├── world.sdf
121+
└── models
122+
└── model1
123+
├── model.sdf
124+
└── meshes
125+
└── mesh.dae
126+
```
127+
128+
The world `world.sdf` can include `model1` as follows:
129+
130+
`<include>models/model1</include>`
131+
132+
And `model.sdf` can refer to `mesh.dae` as:
133+
134+
`<uri>meshes/mesh.dae</uri>`
135+
136+
### Path relative to an environment variable
137+
138+
This method is useful if you don't know where the files will be located
139+
with respect to each other, and you have some control over the simulation's
140+
runtime environment. On either simulator, you can refer to resources relative
141+
to paths set on an environment variable.
142+
143+
Each simulator uses a different environment variable:
144+
145+
* Gazebo classic:
146+
* `GAZEBO_MODEL_PATH` for models
147+
* `GAZEBO_RESOURCE_PATH` for worlds and some rendering resources
148+
* Ignition Gazebo:
149+
* `IGN_GAZEBO_RESOURCE_PATH` for worlds, models and other resources
150+
151+
For example, if you have the file structure above, you can set the environment
152+
variable to `/home/username/models`:
153+
154+
```
155+
export GAZEBO_MODEL_PATH=/home/username/models
156+
export GAZEBO_RESOURCE_PATH=/home/username/models
157+
export IGN_GAZEBO_RESOURCE_PATH=/home/username/models
158+
```
159+
160+
And inside `world.sdf` include the model with:
161+
162+
`<include>model://model1</include>`
163+
164+
Also, `model.sdf` can refer to `mesh.dae` as:
165+
166+
`<uri>model://model1/meshes/mesh.dae</uri>`
167+
168+
On both situations, the `model://` prefix will be substituted by
169+
`/home/username/models`.
170+
171+
You can also set several lookup paths separating them with `:`, for example:
172+
173+
`export IGN_GAZEBO_RESOURCE_PATH=/home/username/models:/home/username/another_project/models`
174+
175+
### Absolute paths
176+
177+
Finally, both simulators will accept absolute paths, for example:
178+
179+
`<include>/home/username/models/model1</include>`
180+
181+
This method is not recommended, because the file most likely won't work if
182+
copied to a different computer. It also becomes inconvenient to move files to
183+
different directories.
184+
185+
## Plugins
186+
187+
Plugins are binary files compiled to use with a specific simulator. Plugins
188+
for Gazebo classic and Ignition Gazebo aren't usually compatible, so plugins
189+
will need to be specified for each simulator separately.
190+
191+
It's important to note that for both simulators, plugins compiled against
192+
a major version of the simulator can't be loaded by other major versions.
193+
The shared libraries will usually have the same name, so it's important to make
194+
sure you're loading the correct plugins.
195+
196+
### Official plugins
197+
198+
Both simulators are installed with several built-in plugins.
199+
[Gazebo classic's plugins](https://github.com/osrf/gazebo/tree/gazebo11/plugins)
200+
and
201+
[Ignition Gazebo's plugins](https://github.com/ignitionrobotics/ign-gazebo/tree/ign-gazebo3/src/systems)
202+
have different file names. For example, to use Gazebo classic's differential drive
203+
plugin, the user can refer to it as follows:
204+
205+
```
206+
<model ...>
207+
<plugin filename="libDiffDrivePlugin.so" name="any_custom_name">
208+
...
209+
</plugin>
210+
</model>
211+
```
212+
213+
On Ignition, that would be:
214+
215+
```
216+
<model ...>
217+
<plugin filename="ignition-gazebo-diff-drive-system"
218+
name="ignition::gazebo::systems::DiffDrive">
219+
...
220+
</plugin>
221+
</model>
222+
```
223+
224+
Note that besides the different file name, Ignition also requires the C++ class
225+
to be defined in the `name` attribute.
226+
227+
Also keep in mind that plugins that offer similar functionality may accept
228+
different parameters for each simulator. Be sure to check the documentation of
229+
each plugin before using it.
230+
231+
### Custom plugins
232+
233+
To load custom plugins, users need to set environment variables to the directory
234+
where that plugin is located. The variables are different for each simulator:
235+
236+
* Gazebo classic:
237+
* `GAZEBO_PLUGIN_PATH` for all plugin types.
238+
* Ignition Gazebo:
239+
* `IGN_GAZEBO_SYSTEM_PLUGIN_PATH` for Ignition Gazebo systems (world, model,
240+
sensor and visual plugins).
241+
* `IGN_GUI_PLUGIN_PATH` for GUI plugins.
242+
243+
### Keeping plugins separate
244+
245+
Trying to load a plugin from one simulator into the other will:
246+
247+
* Print an error message if the simulator can't find the plugin
248+
* Potentially crash if the simulator can find the plugin and tries to load it
249+
250+
That's why it's recommended not to specify plugins for both simulators
251+
side-by-side on the same file. Instead, keep separate files and inject the plugins as
252+
needed.
253+
254+
There isn't a built-in mechanism on SDFormat to inject plugins into files yet,
255+
but users can make use of templating tools like [ERB](erb_template.html)
256+
and [xacro](http://wiki.ros.org/xacro) to generate SDF files with the correct plugins.
257+
258+
### Default plugins
259+
260+
Ignition Gazebo is more modular than Gazebo classic, so most features are optional.
261+
For example, by default, Ignition will load all the system plugins defined on
262+
the `~/.ignition/gazebo/server.config` file and all GUI plugins defined on the
263+
`~/.ignition/gazebo/gui.config` file. But the user can always remove plugins from
264+
those files, or choose different ones by adding `<plugin>` tags to the SDF file.
265+
(For more details, see the [Server configuration tutorial](server_config.html)
266+
and the [GUI configuration tutorial](gui_config.html)).
267+
268+
This is important to keep in mind when migrating your SDF files, because files
269+
that worked on Gazebo classic may need more plugins on Ignition.
270+
271+
## Materials
272+
273+
Ignition does not support Ogre material files like Classic does, because Ignition
274+
Gazebo can be used with multiple rendering engines. Therefore, materials defined
275+
within a `<script>` aren't supported on Ignition, for example:
276+
277+
```
278+
<material>
279+
<script>
280+
<uri>model://number1/materials/scripts</uri>
281+
<uri>model://number1/materials/textures</uri>
282+
<name>Number/One</name>
283+
</script>
284+
</material>
285+
```
286+
287+
To make your models compatible with both simulators, you can use these alternatives:
288+
289+
### Plain colors
290+
291+
If the material defines plain colors, use the `<ambient>`, `<specular>`,
292+
`<emissive>` and `<diffuse>` tags as needed.
293+
294+
For example, this material from
295+
[gazebo.material](https://github.com/osrf/gazebo/blob/gazebo11/media/materials/scripts/gazebo.material):
296+
297+
```
298+
<material>
299+
<script>
300+
<uri>file://media/materials/scripts/gazebo.material</uri>
301+
<name>Gazebo/Red</name>
302+
</script>
303+
</material>
304+
```
305+
306+
Can be changed to:
307+
308+
```
309+
<material>
310+
<ambient>1 0 0 1</ambient>
311+
<diffuse>1 0 0 1</diffuse>
312+
<specular>0.1 0.1 0.1 1</specular>
313+
</material>
314+
315+
```
316+
317+
### Textures
318+
319+
If an Ogre material script is being used to define a texture, there are a
320+
couple alternatives.
321+
322+
If using mesh files, the texture can be embedded into it. The advantage is that
323+
this works for both simulators. Some examples:
324+
325+
* [OBJ + MTL](https://app.ignitionrobotics.org/OpenRobotics/fuel/models/DeskChair)
326+
* [COLLADA](https://app.ignitionrobotics.org/OpenRobotics/fuel/models/Lamp%20Post)
327+
328+
For primitive shapes or even meshes, you can pass the texture as the albedo map. If you
329+
want the model to be compatible with both Classic and Ignition, you can specify both
330+
the script and the albedo map.
331+
332+
```
333+
<material>
334+
<pbr>
335+
<metal>
336+
<albedo_map>texture.png</albedo_map>
337+
</metal>
338+
</pbr>
339+
</material>
340+
```
341+

0 commit comments

Comments
 (0)