Using Gazebo#
Added in version Jazzy: This section.
Warning
This topic is under construction and this might not even be its final form. Please feel free to open an issue if you spot any typos or other problems.
Hint
You can start the simulator with the following command.
gz sim
In this section we will see the basic operations related to Gazebo and create our own sdf file.
Basic functionality#
These two official tutorials cover the basic functionality of Gazebo. They are very well made with up-to-date images and videos. Please go through them to familiarise yourself with the basic functionality.
Fun with plugins#
Check the guides below for basic functionality.
World files .sdf#
See also
Official documentation: https://gazebosim.org/docs/harmonic/sdf_worlds/
Let us start with the sample scene shapes.sdf. This example is available in the official repository. It is shown
below to save you a click. The format is xml, which should be a familiar file format by now.
Contents of shapes.sdf
<?xml version="1.0" ?>
<sdf version="1.11">
<!--
Try moving a model using the command in the following CDATA block::
-->
<![CDATA[
gz service -s /world/shapes/set_pose \
--reqtype gz.msgs.Pose --reptype gz.msgs.Boolean \
--timeout 300 --req 'name: "box", position: {z: 5.0}'
]]>
<world name="shapes">
<scene>
<ambient>1.0 1.0 1.0</ambient>
<background>0.8 0.8 0.8</background>
</scene>
<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>
<model name="ground_plane">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
</collision>
<visual name="visual">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
<material>
<ambient>0.8 0.8 0.8 1</ambient>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.8 0.8 0.8 1</specular>
</material>
</visual>
</link>
</model>
<model name="box">
<pose>0 0 0.5 0 0 0</pose>
<link name="box_link">
<inertial>
<inertia>
<ixx>0.16666</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.16666</iyy>
<iyz>0</iyz>
<izz>0.16666</izz>
</inertia>
<mass>1.0</mass>
</inertial>
<collision name="box_collision">
<geometry>
<box>
<size>1 1 1</size>
</box>
</geometry>
</collision>
<visual name="box_visual">
<geometry>
<box>
<size>1 1 1</size>
</box>
</geometry>
<material>
<ambient>1 0 0 1</ambient>
<diffuse>1 0 0 1</diffuse>
<specular>1 0 0 1</specular>
</material>
</visual>
</link>
</model>
<model name="cylinder">
<pose>0 -1.5 0.5 0 0 0</pose>
<link name="cylinder_link">
<inertial>
<inertia>
<ixx>0.1458</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.1458</iyy>
<iyz>0</iyz>
<izz>0.125</izz>
</inertia>
<mass>1.0</mass>
</inertial>
<collision name="cylinder_collision">
<geometry>
<cylinder>
<radius>0.5</radius>
<length>1.0</length>
</cylinder>
</geometry>
</collision>
<visual name="cylinder_visual">
<geometry>
<cylinder>
<radius>0.5</radius>
<length>1.0</length>
</cylinder>
</geometry>
<material>
<ambient>0 1 0 1</ambient>
<diffuse>0 1 0 1</diffuse>
<specular>0 1 0 1</specular>
</material>
</visual>
</link>
</model>
<model name="sphere">
<pose>0 1.5 0.5 0 0 0</pose>
<link name="sphere_link">
<inertial>
<inertia>
<ixx>0.1</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.1</iyy>
<iyz>0</iyz>
<izz>0.1</izz>
</inertia>
<mass>1.0</mass>
</inertial>
<collision name="sphere_collision">
<geometry>
<sphere>
<radius>0.5</radius>
</sphere>
</geometry>
</collision>
<visual name="sphere_visual">
<geometry>
<sphere>
<radius>0.5</radius>
</sphere>
</geometry>
<material>
<ambient>0 0 1 1</ambient>
<diffuse>0 0 1 1</diffuse>
<specular>0 0 1 1</specular>
</material>
</visual>
</link>
</model>
<model name="capsule">
<pose>0 -3.0 0.5 0 0 0</pose>
<link name="capsule_link">
<inertial>
<inertia>
<ixx>0.074154</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.074154</iyy>
<iyz>0</iyz>
<izz>0.018769</izz>
</inertia>
<mass>1.0</mass>
</inertial>
<collision name="capsule_collision">
<geometry>
<capsule>
<radius>0.2</radius>
<length>0.6</length>
</capsule>
</geometry>
</collision>
<visual name="capsule_visual">
<geometry>
<capsule>
<radius>0.2</radius>
<length>0.6</length>
</capsule>
</geometry>
<material>
<ambient>1 1 0 1</ambient>
<diffuse>1 1 0 1</diffuse>
<specular>1 1 0 1</specular>
</material>
</visual>
</link>
</model>
<model name="ellipsoid">
<pose>0 3.0 0.5 0 0 0</pose>
<link name="ellipsoid_link">
<inertial>
<inertia>
<ixx>0.068</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.058</iyy>
<iyz>0</iyz>
<izz>0.026</izz>
</inertia>
<mass>1.0</mass>
</inertial>
<collision name="ellipsoid_collision">
<geometry>
<ellipsoid>
<radii>0.2 0.3 0.5</radii>
</ellipsoid>
</geometry>
</collision>
<visual name="ellipsoid_visual">
<geometry>
<ellipsoid>
<radii>0.2 0.3 0.5</radii>
</ellipsoid>
</geometry>
<material>
<ambient>1 0 1 1</ambient>
<diffuse>1 0 1 1</diffuse>
<specular>1 0 1 1</specular>
</material>
</visual>
</link>
</model>
<model name="cone">
<pose>0 4.5 0.5 0 0 0</pose>
<link name="cone_link">
<inertial auto="true">
<density>1</density>
</inertial>
<collision name="cone_collision">
<geometry>
<cone>
<radius>0.5</radius>
<length>1.0</length>
</cone>
</geometry>
</collision>
<visual name="cone_visual">
<geometry>
<cone>
<radius>0.5</radius>
<length>1.0</length>
</cone>
</geometry>
<material>
<ambient>1 0.47 0 1</ambient>
<diffuse>1 0.47 0 1</diffuse>
<specular>1 0.47 0 1</specular>
</material>
</visual>
</link>
</model>
</world>
</sdf>
As you could have noticed, even simple world files can have a relatively complex format. The example shapes.sdf, that has only a few simple
objects, is difficult to parse visually. For most things, it is easier to use Gazebo itself and limit
and direct changes in .sdf files.
Adding or removing things directly on Gazebo is sometimes not repeatable with possible GUI changes across versions. In addition, it is not as natural for a text-based tutorial such as this one. In those scenarios, I will show how to edit the file directly.
This tutorial will limit itself on using default .sdf files and making small modifications. Our interest is to be
able obtain and send useful information from Gazebo to ROS.
You will notice in this file some of the most common elements of .sdf. These are not the only elements and this
list is not meant to be comprehensive.
<sdf>is the highest-level element, defining the entire.sdf.<world name="world_name">encloses the elements in this world and gives it a name. This name, rather than the name of the file, will be used when exposing topics and services.<scene>has broad elements of the scene, such as background color.- Entities can include:
<light>a source of light<model>a model in the simulation, such as simple shapes or a robot, that can include other information such as<link>,<visual>, and<collision>.
Note
If your application demands it, you will need specialised programs to create 3D models, such as Blender. It won’t be usually manageable to create complicated models directly on Gazebo.
In this example, because we’re using simple shapes supported by Gazebo, they are defined with <geometry>
elements.
Gazebo topics and services#
Caution
Internal Gazebo topics and services are not the same as ROS2 topics and services.
A Gazebo scene will have a number of internal topics and services. We can interact with them using gz commands. The messages that flow through Gazebo are based on protobuf, not ROS2 IDL.
Let us use an example with sensors. This example is available in the official repository.
Contents of sensors_demo.sdf
1<?xml version="1.0" ?>
2<!--
3 Load several rendering sensors.
4-->
5<sdf version="1.6">
6 <world name="lidar_sensor">
7 <physics name="1ms" type="ignored">
8 <max_step_size>0.001</max_step_size>
9 <real_time_factor>1.0</real_time_factor>
10 </physics>
11 <plugin
12 filename="gz-sim-physics-system"
13 name="gz::sim::systems::Physics">
14 </plugin>
15 <plugin
16 filename="gz-sim-sensors-system"
17 name="gz::sim::systems::Sensors">
18 <render_engine>ogre2</render_engine>
19 </plugin>
20 <plugin
21 filename="gz-sim-user-commands-system"
22 name="gz::sim::systems::UserCommands">
23 </plugin>
24 <plugin
25 filename="gz-sim-scene-broadcaster-system"
26 name="gz::sim::systems::SceneBroadcaster">
27 </plugin>
28
29
30 <gui fullscreen="0">
31
32 <!-- 3D scene -->
33 <plugin filename="MinimalScene" name="3D View">
34 <gz-gui>
35 <title>3D View</title>
36 <property type="bool" key="showTitleBar">false</property>
37 <property type="string" key="state">docked</property>
38 </gz-gui>
39
40 <engine>ogre2</engine>
41 <scene>scene</scene>
42 <ambient_light>0.4 0.4 0.4</ambient_light>
43 <background_color>0.8 0.8 0.8</background_color>
44 <camera_pose>-6 0 6 0 0.5 0</camera_pose>
45 </plugin>
46
47 <!-- Plugins that add functionality to the scene -->
48 <plugin filename="EntityContextMenuPlugin" name="Entity context menu">
49 <gz-gui>
50 <property key="state" type="string">floating</property>
51 <property key="width" type="double">5</property>
52 <property key="height" type="double">5</property>
53 <property key="showTitleBar" type="bool">false</property>
54 </gz-gui>
55 </plugin>
56 <plugin filename="GzSceneManager" name="Scene Manager">
57 <gz-gui>
58 <property key="resizable" type="bool">false</property>
59 <property key="width" type="double">5</property>
60 <property key="height" type="double">5</property>
61 <property key="state" type="string">floating</property>
62 <property key="showTitleBar" type="bool">false</property>
63 </gz-gui>
64 </plugin>
65 <plugin filename="InteractiveViewControl" name="Interactive view control">
66 <gz-gui>
67 <property key="resizable" type="bool">false</property>
68 <property key="width" type="double">5</property>
69 <property key="height" type="double">5</property>
70 <property key="state" type="string">floating</property>
71 <property key="showTitleBar" type="bool">false</property>
72 </gz-gui>
73 </plugin>
74 <plugin filename="CameraTracking" name="Camera Tracking">
75 <gz-gui>
76 <property key="resizable" type="bool">false</property>
77 <property key="width" type="double">5</property>
78 <property key="height" type="double">5</property>
79 <property key="state" type="string">floating</property>
80 <property key="showTitleBar" type="bool">false</property>
81 </gz-gui>
82 </plugin>
83 <!-- World control -->
84 <plugin filename="WorldControl" name="World control">
85 <gz-gui>
86 <title>World control</title>
87 <property type="bool" key="showTitleBar">false</property>
88 <property type="bool" key="resizable">false</property>
89 <property type="double" key="height">72</property>
90 <property type="double" key="z">1</property>
91
92 <property type="string" key="state">floating</property>
93 <anchors target="3D View">
94 <line own="left" target="left"/>
95 <line own="bottom" target="bottom"/>
96 </anchors>
97 </gz-gui>
98
99 <play_pause>true</play_pause>
100 <step>true</step>
101 <start_paused>true</start_paused>
102 <use_event>true</use_event>
103
104 </plugin>
105
106 <!-- World statistics -->
107 <plugin filename="WorldStats" name="World stats">
108 <gz-gui>
109 <title>World stats</title>
110 <property type="bool" key="showTitleBar">false</property>
111 <property type="bool" key="resizable">false</property>
112 <property type="double" key="height">110</property>
113 <property type="double" key="width">290</property>
114 <property type="double" key="z">1</property>
115
116 <property type="string" key="state">floating</property>
117 <anchors target="3D View">
118 <line own="right" target="right"/>
119 <line own="bottom" target="bottom"/>
120 </anchors>
121 </gz-gui>
122
123 <sim_time>true</sim_time>
124 <real_time>true</real_time>
125 <real_time_factor>true</real_time_factor>
126 <iterations>true</iterations>
127 </plugin>
128
129 <!-- Inspector -->
130 <plugin filename="ComponentInspector" name="Component inspector">
131 <gz-gui>
132 <property type="string" key="state">docked</property>
133 </gz-gui>
134 </plugin>
135
136 <!-- Entity tree -->
137 <plugin filename="EntityTree" name="Entity tree">
138 <gz-gui>
139 <property type="string" key="state">docked</property>
140 </gz-gui>
141 </plugin>
142
143 <plugin filename="ImageDisplay" name="Image Display">
144 <gz-gui>
145 <title>RGB camera</title>
146 <property key="state" type="string">floating</property>
147 <property type="double" key="width">350</property>
148 <property type="double" key="height">315</property>
149 </gz-gui>
150 <topic>camera</topic>
151 <topic_picker>false</topic_picker>
152 </plugin>
153 <plugin filename="ImageDisplay" name="Image Display 2">
154 <gz-gui>
155 <title>Depth camera</title>
156 <property key="state" type="string">floating</property>
157 <property type="double" key="width">350</property>
158 <property type="double" key="height">315</property>
159 <property type="double" key="x">500</property>
160 </gz-gui>
161 <topic>depth_camera</topic>
162 <topic_picker>false</topic_picker>
163 </plugin>
164 <plugin filename="ImageDisplay" name="Image Display 3">
165 <gz-gui>
166 <title>RGBD: image</title>
167 <property key="state" type="string">floating</property>
168 <property type="double" key="width">350</property>
169 <property type="double" key="height">315</property>
170 <property type="double" key="y">320</property>
171 </gz-gui>
172 <topic>rgbd_camera/image</topic>
173 <topic_picker>false</topic_picker>
174 </plugin>
175 <plugin filename="ImageDisplay" name="Image Display 3">
176 <gz-gui>
177 <title>RGBD: depth</title>
178 <property key="state" type="string">floating</property>
179 <property type="double" key="width">350</property>
180 <property type="double" key="height">315</property>
181 <property type="double" key="x">500</property>
182 <property type="double" key="y">320</property>
183 </gz-gui>
184 <topic>rgbd_camera/depth_image</topic>
185 <topic_picker>false</topic_picker>
186 </plugin>
187 <plugin filename="ImageDisplay" name="Image Display 5">
188 <gz-gui>
189 <title>Thermal camera</title>
190 <property key="state" type="string">floating</property>
191 <property type="double" key="width">350</property>
192 <property type="double" key="height">315</property>
193 <property type="double" key="x">500</property>
194 <property type="double" key="y">640</property>
195 </gz-gui>
196 <topic>thermal_camera</topic>
197 <topic_picker>false</topic_picker>
198 </plugin>
199 </gui>
200
201 <light type="directional" name="sun">
202 <cast_shadows>true</cast_shadows>
203 <pose>0 0 10 0 0 0</pose>
204 <diffuse>0.8 0.8 0.8 1</diffuse>
205 <specular>0.2 0.2 0.2 1</specular>
206 <attenuation>
207 <range>1000</range>
208 <constant>0.9</constant>
209 <linear>0.01</linear>
210 <quadratic>0.001</quadratic>
211 </attenuation>
212 <direction>-0.5 0.1 -0.9</direction>
213 </light>
214
215 <model name="ground_plane">
216 <static>true</static>
217 <link name="link">
218 <collision name="collision">
219 <geometry>
220 <!--plane>
221 <normal>0 0 1</normal>
222 <size>100 100</size>
223 </plane-->
224 <box>
225 <size>20 20 0.1</size>
226 </box>
227 </geometry>
228 </collision>
229 <visual name="visual">
230 <geometry>
231 <!--plane>
232 <normal>0 0 1</normal>
233 <size>100 100</size>
234 </plane-->
235 <box>
236 <size>20 20 0.1</size>
237 </box>
238 </geometry>
239 <material>
240 <ambient>0.8 0.8 0.8 1</ambient>
241 <diffuse>0.8 0.8 0.8 1</diffuse>
242 <specular>0.8 0.8 0.8 1</specular>
243 </material>
244 </visual>
245 </link>
246 </model>
247
248 <model name="box">
249 <pose>0 -1 0.5 0 0 0</pose>
250 <link name="box_link">
251 <inertial>
252 <inertia>
253 <ixx>1</ixx>
254 <ixy>0</ixy>
255 <ixz>0</ixz>
256 <iyy>1</iyy>
257 <iyz>0</iyz>
258 <izz>1</izz>
259 </inertia>
260 <mass>1.0</mass>
261 </inertial>
262 <collision name="box_collision">
263 <geometry>
264 <box>
265 <size>1 1 1</size>
266 </box>
267 </geometry>
268 </collision>
269
270 <visual name="box_visual">
271 <geometry>
272 <box>
273 <size>1 1 1</size>
274 </box>
275 </geometry>
276 <material>
277 <ambient>1 0 0 1</ambient>
278 <diffuse>1 0 0 1</diffuse>
279 <specular>1 0 0 1</specular>
280 </material>
281 </visual>
282 </link>
283 </model>
284
285 <model name="cameras_alone">
286 <pose>2.5 0 1.5 0 0.0 3.14</pose>
287 <link name="link">
288 <pose>0.05 0.05 0.05 0 0 0</pose>
289 <inertial>
290 <mass>0.1</mass>
291 <inertia>
292 <ixx>0.000166667</ixx>
293 <iyy>0.000166667</iyy>
294 <izz>0.000166667</izz>
295 </inertia>
296 </inertial>
297 <collision name="collision">
298 <geometry>
299 <box>
300 <size>0.1 0.1 0.1</size>
301 </box>
302 </geometry>
303 </collision>
304 <visual name="visual">
305 <geometry>
306 <box>
307 <size>0.1 0.1 0.1</size>
308 </box>
309 </geometry>
310 </visual>
311 <sensor name="cameras_alone" type="camera">
312 <camera>
313 <horizontal_fov>1.047</horizontal_fov>
314 <image>
315 <width>320</width>
316 <height>240</height>
317 </image>
318 <clip>
319 <near>0.1</near>
320 <far>100</far>
321 </clip>
322 </camera>
323 <always_on>1</always_on>
324 <update_rate>30</update_rate>
325 <visualize>true</visualize>
326 <topic>camera_alone</topic>
327 <enable_metrics>true</enable_metrics>
328 </sensor>
329 <sensor name="depth_camera1" type="depth_camera">
330 <update_rate>10</update_rate>
331 <topic>depth_camera</topic>
332 <enable_metrics>true</enable_metrics>
333 <camera>
334 <horizontal_fov>1.05</horizontal_fov>
335 <image>
336 <width>320</width>
337 <height>240</height>
338 <format>R_FLOAT32</format>
339 </image>
340 <clip>
341 <near>0.1</near>
342 <far>10.0</far>
343 </clip>
344 </camera>
345 </sensor>
346 </link>
347 <static>true</static>
348 </model>
349
350 <model name="camera_with_lidar">
351 <pose>4 0 0.5 0 0.0 3.14</pose>
352 <link name="link">
353 <pose>0.05 0.05 0.05 0 0 0</pose>
354 <inertial>
355 <mass>0.1</mass>
356 <inertia>
357 <ixx>0.000166667</ixx>
358 <iyy>0.000166667</iyy>
359 <izz>0.000166667</izz>
360 </inertia>
361 </inertial>
362 <collision name="collision">
363 <geometry>
364 <box>
365 <size>0.1 0.1 0.1</size>
366 </box>
367 </geometry>
368 </collision>
369 <visual name="visual">
370 <geometry>
371 <box>
372 <size>0.1 0.1 0.1</size>
373 </box>
374 </geometry>
375 </visual>
376 <sensor name="camera" type="camera">
377 <camera>
378 <horizontal_fov>1.047</horizontal_fov>
379 <image>
380 <width>320</width>
381 <height>240</height>
382 </image>
383 <clip>
384 <near>0.1</near>
385 <far>100</far>
386 </clip>
387 </camera>
388 <always_on>1</always_on>
389 <update_rate>30</update_rate>
390 <visualize>true</visualize>
391 <topic>camera</topic>
392 </sensor>
393
394 <sensor name='gpu_lidar' type='gpu_lidar'>"
395 <topic>lidar</topic>
396 <update_rate>10</update_rate>
397 <enable_metrics>true</enable_metrics>
398 <ray>
399 <scan>
400 <horizontal>
401 <samples>640</samples>
402 <resolution>1</resolution>
403 <min_angle>-1.396263</min_angle>
404 <max_angle>1.396263</max_angle>
405 </horizontal>
406 <vertical>
407 <samples>1</samples>
408 <resolution>0.01</resolution>
409 <min_angle>0</min_angle>
410 <max_angle>0</max_angle>
411 </vertical>
412 </scan>
413 <range>
414 <min>0.08</min>
415 <max>10.0</max>
416 <resolution>0.01</resolution>
417 </range>
418 </ray>
419 <visualize>true</visualize>
420 </sensor>
421 </link>
422
423 <static>true</static>
424 </model>
425
426 <model name="rgbd_camera">
427 <pose>5 0 0.5 0 0.0 3.14</pose>
428 <link name="link">
429 <pose>0.05 0.05 0.05 0 0 0</pose>
430 <inertial>
431 <mass>0.1</mass>
432 <inertia>
433 <ixx>0.000166667</ixx>
434 <iyy>0.000166667</iyy>
435 <izz>0.000166667</izz>
436 </inertia>
437 </inertial>
438 <collision name="collision">
439 <geometry>
440 <box>
441 <size>0.1 0.1 0.1</size>
442 </box>
443 </geometry>
444 </collision>
445 <visual name="visual">
446 <geometry>
447 <box>
448 <size>0.1 0.1 0.1</size>
449 </box>
450 </geometry>
451 </visual>
452 <sensor name="rgbd_camera" type="rgbd_camera">
453 <camera>
454 <horizontal_fov>1.047</horizontal_fov>
455 <image>
456 <width>320</width>
457 <height>240</height>
458 </image>
459 <clip>
460 <near>0.1</near>
461 <far>100</far>
462 </clip>
463 </camera>
464 <always_on>1</always_on>
465 <update_rate>30</update_rate>
466 <visualize>true</visualize>
467 <topic>rgbd_camera</topic>
468 <enable_metrics>true</enable_metrics>
469 </sensor>
470 </link>
471 </model>
472
473 <model name="thermal_camera">
474 <pose>3 0 0.5 0 0.0 3.14</pose>
475 <link name="link">
476 <pose>0.05 0.05 0.05 0 0 0</pose>
477 <inertial>
478 <mass>0.1</mass>
479 <inertia>
480 <ixx>0.000166667</ixx>
481 <iyy>0.000166667</iyy>
482 <izz>0.000166667</izz>
483 </inertia>
484 </inertial>
485 <collision name="collision">
486 <geometry>
487 <box>
488 <size>0.1 0.1 0.1</size>
489 </box>
490 </geometry>
491 </collision>
492 <visual name="visual">
493 <geometry>
494 <box>
495 <size>0.1 0.1 0.1</size>
496 </box>
497 </geometry>
498 </visual>
499 <sensor name="thermal_camera" type="thermal_camera">
500 <camera>
501 <horizontal_fov>1.047</horizontal_fov>
502 <image>
503 <width>320</width>
504 <height>240</height>
505 </image>
506 <clip>
507 <near>0.1</near>
508 <far>100</far>
509 </clip>
510 </camera>
511 <always_on>1</always_on>
512 <update_rate>30</update_rate>
513 <visualize>true</visualize>
514 <topic>thermal_camera</topic>
515 </sensor>
516 </link>
517 </model>
518
519 <include>
520 <pose>0 1 3 0.0 0.0 1.57</pose>
521 <uri>
522 https://fuel.gazebosim.org/1.0/OpenRobotics/models/Construction Cone
523 </uri>
524 </include>
525
526 </world>
527</sdf>
To enable physical simulation, including sensor, we can see that a new tag, <plugins> is added. These are paramount
to guarantee that sensors will work. Further, they create important topics and services in Gazebo. Here are
the plugins active on this file.
<physics name="1ms" type="ignored">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
</physics>
<plugin
filename="gz-sim-physics-system"
name="gz::sim::systems::Physics">
</plugin>
<plugin
filename="gz-sim-sensors-system"
name="gz::sim::systems::Sensors">
<render_engine>ogre2</render_engine>
</plugin>
<plugin
filename="gz-sim-user-commands-system"
name="gz::sim::systems::UserCommands">
</plugin>
<plugin
filename="gz-sim-scene-broadcaster-system"
name="gz::sim::systems::SceneBroadcaster">
</plugin>
We will now start to interact with Gazebo. For this section, suppose that we have the scene always open with the following command.
Tip
You will see online, very frequently, the command using -v4. For instance, as follows. This allows Gazebo
to output many messages to the terminal in which it was opened to help you understand what is happening.
gz sim -v4 sensors_demo.sdf
gz sim sensors_demo.sdf
A frequently used tool to allow us to inspect internal Gazebo topics will be, in another terminal, to run the following
command. The -l flag allows us to list Gazebo topics.
gz topic -l
If the correct scene is running on Gazebo, the output should be similar to the following output.
/camera
/camera_alone
/camera_info
/clock
/depth_camera
/depth_camera/performance_metrics
/depth_camera/points
/gazebo/resource_paths
/gui/camera/pose
/gui/currently_tracked
/gui/track
/lidar
/lidar/points
/rgbd_camera/camera_info
/rgbd_camera/depth_image
/rgbd_camera/image
/rgbd_camera/performance_metrics
/rgbd_camera/points
/sensors/marker
/stats
/thermal_camera
/world/lidar_sensor/clock
/world/lidar_sensor/dynamic_pose/info
/world/lidar_sensor/pose/info
/world/lidar_sensor/scene/deletion
/world/lidar_sensor/scene/info
/world/lidar_sensor/state
/world/lidar_sensor/stats
/world/lidar_sensor/light_config
/world/lidar_sensor/material_color
Further information can be obtained about topics, for instance, the type of message that flows through them. We can check what is the message type used in one of the sensors as follows.
gz topic -i --topic /rgbd_camera/image
The output of that command should be similar to the following.
Publishers [Address, Message Type]:
tcp://172.16.191.128:40679, gz.msgs.Image
Subscribers [Address, Message Type]:
tcp://172.16.191.128:40229, gz.msgs.Image
Information about services, similarly, can be obtained with the following command.
gz service -l
Resulting in the following output.
Services in sensors_demo.sdf
/camera/set_rate
/camera_alone/set_rate
/depth_camera/set_rate
/gazebo/resource_paths/add
/gazebo/resource_paths/get
/gazebo/resource_paths/resolve
/gazebo/worlds
/gui/camera/view_control
/gui/camera/view_control/reference_visual
/gui/camera/view_control/sensitivity
/gui/follow
/gui/follow/offset
/gui/move_to
/gui/move_to/pose
/lidar/set_rate
/rgbd_camera/set_rate
/sensors/marker
/sensors/marker/list
/sensors/marker_array
/server_control
/thermal_camera/set_rate
/world/lidar_sensor/control
/world/lidar_sensor/control/state
/world/lidar_sensor/create
/world/lidar_sensor/create/blocking
/world/lidar_sensor/create_multiple
/world/lidar_sensor/create_multiple/blocking
/world/lidar_sensor/declare_parameter
/world/lidar_sensor/disable_collision
/world/lidar_sensor/disable_collision/blocking
/world/lidar_sensor/enable_collision
/world/lidar_sensor/enable_collision/blocking
/world/lidar_sensor/entity/system/add
/world/lidar_sensor/generate_world_sdf
/world/lidar_sensor/get_parameter
/world/lidar_sensor/gui/info
/world/lidar_sensor/level/set_performer
/world/lidar_sensor/light_config
/world/lidar_sensor/light_config/blocking
/world/lidar_sensor/list_parameters
/world/lidar_sensor/playback/control
/world/lidar_sensor/remove
/world/lidar_sensor/remove/blocking
/world/lidar_sensor/scene/graph
/world/lidar_sensor/scene/info
/world/lidar_sensor/set_parameter
/world/lidar_sensor/set_physics
/world/lidar_sensor/set_physics/blocking
/world/lidar_sensor/set_pose
/world/lidar_sensor/set_pose/blocking
/world/lidar_sensor/set_pose_vector
/world/lidar_sensor/set_pose_vector/blocking
/world/lidar_sensor/set_spherical_coordinates
/world/lidar_sensor/set_spherical_coordinates/blocking
/world/lidar_sensor/state
/world/lidar_sensor/state_async
/world/lidar_sensor/system/info
/world/lidar_sensor/visual_config
/world/lidar_sensor/visual_config/blocking
/world/lidar_sensor/wheel_slip
/world/lidar_sensor/wheel_slip/blocking
We can also obtain information about each service. For instance, with the command.
gz service -i --service /rgbd_camera/set_rate
Resulting in the following output.
Service providers [Address, Request Message Type, Response Message Type]:
tcp://172.16.191.128:36013, gz.msgs.Double, gz.msgs.Empty
There are multiple ways to interact with the Gazebo internal topics. This can be, for instance, done through the commandline using similar commands to the ones we have shown so far. Nonetheless, if you have spent so much time learning ROS2, it would be more convenient to find a way to bridge the topics and services from Gazebo and ROS2.
Nonetheless, when some piece of information is not flowing as expected, remember these commands to help troubleshoot.
The package ros_gz_sim#
See also
The official repository: gazebosim/ros_gz
The package ros_gz_sim has a few tools allowing us to control Gazebo over ROS2.
Namely, the ability to start Gazebo and spawn (add) objects. These might depend on Gazebo
topics and services, therefore make sure that the necessary plugins are enabled.
Launching Gazebo#
For example, we can launch Gazebo directly from a launch file.
ros2 launch ros_gz_sim gz_sim.launch.py gz_args:=shapes.sdf
In this command, gz_args we add a representation file known to Gazebo. In this case, shapes.sdf.
You can specify other scenes.
Spawn models#
You can use the following command to spawn models in Gazebo.
ros2 launch ros_gz_sim gz_sim.launch.py gz_args:=shapes.sdf
ros2 launch ros_gz_sim gz_spawn_model.launch.py world:=shapes file:=$(ros2 pkg prefix --share ros_gz_sim_demos)/models/vehicle/model.sdf entity_name:=my_vehicle x:=5.0 y:=5.0 z:=0.5
As arguments we have the
model filename
name for the entity inside Gazebo
position coordinates of the model
Note
The scene specified in the argument world must be active in Gazebo for the command above to work.
This will add the model, in this case, model.sdf to the scene shapes.sdf. The output on the terminal
will be as follows.
[INFO] [launch]: All log files can be found below /home/murilo/.ros/log/2025-11-06-11-19-14-321361-murilo-VMware20-1-14158
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [create-1]: process started with pid [14161]
[create-1] [WARN] [1762427959.367373569] [ros_gz_sim]: Waiting for service [/world/shapes/create] to become available ...
[create-1] [INFO] [1762427959.598035759] [ros_gz_sim]: Entity creation successful.
[INFO] [create-1]: process has finished cleanly [pid 14161]
The package ros_gz_sim_demos#
See also
The official repository: gazebosim/ros_gz
This official package has many examples integrating Gazebo and ROS2. It showcases many functionalities that are useful for robotics applications.
You can verify all files usable for Gazebo demos in the following folder.
cd $(ros2 pkg prefix --share ros_gz_sim_demos)
nautilus .
The current file structure is shown in the dropdown below. There are many launch files, rviz configuration files, and a few
.sdf models.
The structure of ros_gz_sim_demos.
/opt/ros/jazzy/share/ros_gz_sim_demos
├── cmake
│ ├── ros_gz_sim_demosConfig.cmake
│ └── ros_gz_sim_demosConfig-version.cmake
├── environment
│ ├── ament_prefix_path.dsv
│ ├── ament_prefix_path.sh
│ ├── path.dsv
│ ├── path.sh
│ └── ros_gz_sim_demos.dsv
├── launch
│ ├── air_pressure.launch.py
│ ├── battery.launch.py
│ ├── camera.launch.py
│ ├── depth_camera.launch.py
│ ├── diff_drive.launch.py
│ ├── gpu_lidar_bridge.launch.py
│ ├── gpu_lidar.launch.py
│ ├── image_bridge.launch.py
│ ├── imu.launch.py
│ ├── joint_states.launch.py
│ ├── magnetometer.launch.py
│ ├── navsat_gpsfix.launch.py
│ ├── navsat.launch.py
│ ├── rgbd_camera_bridge.launch.py
│ ├── rgbd_camera.launch.py
│ ├── robot_description_publisher.launch.py
│ ├── sdf_parser.launch.py
│ ├── tf_bridge.launch.py
│ └── triggered_camera.launch.py
├── local_setup.bash
├── local_setup.dsv
├── local_setup.sh
├── local_setup.zsh
├── models
│ ├── cardboard_box
│ │ ├── materials
│ │ │ └── textures
│ │ │ └── cardboard_box.png
│ │ ├── meshes
│ │ │ └── cardboard_box.dae
│ │ ├── model.config
│ │ ├── model.sdf
│ │ └── thumbnails
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ └── 5.png
│ ├── double_pendulum_model.sdf
│ ├── rrbot.xacro
│ └── vehicle
│ ├── model.config
│ └── model.sdf
├── package.dsv
├── package.xml
├── rviz
│ ├── camera.rviz
│ ├── depth_camera.rviz
│ ├── diff_drive.rviz
│ ├── gpu_lidar_bridge.rviz
│ ├── gpu_lidar.rviz
│ ├── imu.rviz
│ ├── joint_states.rviz
│ ├── rgbd_camera_bridge.rviz
│ ├── rgbd_camera.rviz
│ ├── robot_description_publisher.rviz
│ ├── tf_bridge.rviz
│ └── vehicle.rviz
└── worlds
├── default.sdf
└── vehicle.sdf
Note
The contents above are not retrieved automatically so they might not represent the latest version of the repository. See gazebosim/ros_gz .
The camera.launch.py demo#
We can run this example with the following command.
ros2 launch ros_gz_sim_demos camera.launch.py
This will show Gazebo, with a couple of objects and a camera. The camera view is being rendered by Gazebo. The simulation is started. At the same time, rviz2 is executed. This demo is important because cameras are difficult to simulate otherwise and being able to access them via ROS2 allows you to create powerful image-based robot controllers and planners.
We can take a look at the topics created, while those programs are running, with the following command.
ros2 topic list
This will output the following.
/camera
/camera_info
/clicked_point
/initialpose
/move_base_simple/goal
/parameter_events
/rosout
/tf
/tf_static
The launch file, camera.launch.py, is currently performing the following steps.
Starting Gazebo with the built-in scene
camera_sensor.sdf.Running rviz2 with the configuration file
camera.rviz.Running
ros_gz_bridgewith the correct parameters to expose the camera sensor from Gazebo to ROS2.
This demo shows the camera simulation results on rviz2 because it’s possibly the most convenient way of showing that the information is correctly flowing through ROS2.
Note
Some unused topics such as /tf are defined in camera.rviz, but don’t worry about those.
Below are the contents of the launch file.
The contents of launch/camera.launch.py
1# Copyright 2019 Open Source Robotics Foundation, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import os
16
17from ament_index_python.packages import get_package_share_directory
18
19from launch import LaunchDescription
20from launch.actions import DeclareLaunchArgument
21from launch.actions import IncludeLaunchDescription
22from launch.conditions import IfCondition
23from launch.launch_description_sources import PythonLaunchDescriptionSource
24from launch.substitutions import LaunchConfiguration
25
26from launch_ros.actions import Node
27
28
29def generate_launch_description():
30
31 pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos')
32 pkg_ros_gz_sim = get_package_share_directory('ros_gz_sim')
33
34 gz_sim = IncludeLaunchDescription(
35 PythonLaunchDescriptionSource(
36 os.path.join(pkg_ros_gz_sim, 'launch', 'gz_sim.launch.py')),
37 launch_arguments={'gz_args': '-r camera_sensor.sdf'}.items(),
38 )
39
40 # RViz
41 rviz = Node(
42 package='rviz2',
43 executable='rviz2',
44 arguments=['-d', os.path.join(pkg_ros_gz_sim_demos, 'rviz', 'camera.rviz')],
45 condition=IfCondition(LaunchConfiguration('rviz'))
46 )
47
48 # Bridge
49 bridge = Node(
50 package='ros_gz_bridge',
51 executable='parameter_bridge',
52 arguments=['/camera@sensor_msgs/msg/Image@gz.msgs.Image',
53 '/camera_info@sensor_msgs/msg/CameraInfo@gz.msgs.CameraInfo'],
54 output='screen'
55 )
56
57 return LaunchDescription([
58 DeclareLaunchArgument('rviz', default_value='true',
59 description='Open RViz.'),
60 gz_sim,
61 bridge,
62 rviz
63 ])
Below are the contents of the rviz file.
The contents of rviz/camera.rviz
1Panels:
2 - Class: rviz_common/Displays
3 Help Height: 0
4 Name: Displays
5 Property Tree Widget:
6 Expanded:
7 - /Global Options1
8 - /Camera1
9 - /Camera1/Status1
10 - /Image1
11 Splitter Ratio: 0.5
12 Tree Height: 557
13 - Class: rviz_common/Selection
14 Name: Selection
15 - Class: rviz_common/Tool Properties
16 Expanded:
17 - /2D Nav Goal1
18 - /Publish Point1
19 Name: Tool Properties
20 Splitter Ratio: 0.5886790156364441
21 - Class: rviz_common/Views
22 Expanded:
23 - /Current View1
24 Name: Views
25 Splitter Ratio: 0.5
26Visualization Manager:
27 Class: ""
28 Displays:
29 - Alpha: 0.5
30 Cell Size: 1
31 Class: rviz_default_plugins/Grid
32 Color: 160; 160; 164
33 Enabled: true
34 Line Style:
35 Line Width: 0.029999999329447746
36 Value: Lines
37 Name: Grid
38 Normal Cell Count: 0
39 Offset:
40 X: 0
41 Y: 0
42 Z: 0
43 Plane: XY
44 Plane Cell Count: 10
45 Reference Frame: <Fixed Frame>
46 Value: true
47 - Class: rviz_default_plugins/Camera
48 Enabled: true
49 Image Rendering: background and overlay
50 Name: Camera
51 Overlay Alpha: 0.5
52 Queue Size: 10
53 Topic: /camera
54 Unreliable: false
55 Value: true
56 Visibility:
57 Grid: true
58 Image: true
59 Value: true
60 Zoom Factor: 1
61 - Class: rviz_default_plugins/Image
62 Enabled: true
63 Max Value: 1
64 Median window: 5
65 Min Value: 0
66 Name: Image
67 Normalize Range: true
68 Queue Size: 10
69 Topic: /camera
70 Unreliable: false
71 Value: true
72 Enabled: true
73 Global Options:
74 Background Color: 48; 48; 48
75 Fixed Frame: camera/link/camera
76 Frame Rate: 30
77 Name: root
78 Tools:
79 - Class: rviz_default_plugins/MoveCamera
80 - Class: rviz_default_plugins/Select
81 - Class: rviz_default_plugins/FocusCamera
82 - Class: rviz_default_plugins/Measure
83 Line color: 128; 128; 0
84 - Class: rviz_default_plugins/SetInitialPose
85 Topic: /initialpose
86 - Class: rviz_default_plugins/SetGoal
87 Topic: /move_base_simple/goal
88 - Class: rviz_default_plugins/PublishPoint
89 Single click: true
90 Topic: /clicked_point
91 Transformation:
92 Current:
93 Class: rviz_default_plugins/TF
94 Value: true
95 Views:
96 Current:
97 Class: rviz_default_plugins/Orbit
98 Distance: 19.73822784423828
99 Enable Stereo Rendering:
100 Stereo Eye Separation: 0.05999999865889549
101 Stereo Focal Distance: 1
102 Swap Stereo Eyes: false
103 Value: false
104 Focal Point:
105 X: 0
106 Y: 0
107 Z: 0
108 Focal Shape Fixed Size: true
109 Focal Shape Size: 0.05000000074505806
110 Invert Z Axis: false
111 Name: Current View
112 Near Clip Distance: 0.009999999776482582
113 Pitch: 0.7903980016708374
114 Target Frame: <Fixed Frame>
115 Value: Orbit (rviz)
116 Yaw: 0.785398006439209
117 Saved: ~
118Window Geometry:
119 Camera:
120 collapsed: false
121 Displays:
122 collapsed: false
123 Height: 702
124 Hide Left Dock: false
125 Hide Right Dock: false
126 Image:
127 collapsed: false
128 QMainWindow State: 000000ff00000000fd00000004000000000000015600000268fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003b00000268000000c700fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c0000026100000001000001c700000268fc0200000005fb0000000c00430061006d006500720061010000003b0000011f0000002800fffffffb0000000a0049006d0061006700650100000160000001430000002800fffffffb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003b000002f8000000a000fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004420000003efc0100000002fb0000000800540069006d00650100000000000004420000000000000000fb0000000800540069006d00650100000000000004500000000000000000000000320000026800000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
129 Selection:
130 collapsed: false
131 Tool Properties:
132 collapsed: false
133 Views:
134 collapsed: false
135 Width: 859
136 X: 517
137 Y: 361
The launch file uses the package ros_gz_bridge, which is used to create the interfaces,
for instance topics, between Gazebo and ROS2.
We will see this package in more detail in the following section.
References#
The official documentation for Gazebo is overall good. Here are some main topics where this tutorial borrowed from.