Skip to content

Creating Heightmaps for Gazebo

Matthew Verbryke edited this page Jun 2, 2022 · 6 revisions

In order to have more realistic environments for robotics scenarios, Gazebo is capable of using 3D terrain heightmaps created from greyscale images. This guide runs through the process of creating such heightmaps and using them in Gazebo.

(This tutorial is heavily based on this video)

A Python program which handles a lot of this process can be found here.

Table of Contents

What You'll Need

This tutorial was performed on a computer running Ubuntu 16.04 LTS and Gazebo 7.

The GNU Image Manipulation Program (GIMP) was used for editing the grayscale image. If you do not already have it, install it on your machine.

Creating a Heightmap Image

Several sites exist to download terrain data, but any kind of data can theoretically be used, even those which don't represent topography. Before a terrain model can be created, you will need to retrieve or create your heightmap file as a grayscale raster image (preferably a PNG).

Once you have retrieved a suitable grayscale image, open it up in GIMP.

In order for Gazebo to use a grayscale as a heightmap, it must meet three conditions:

  1. The height and width must be equal (i.e. image must be square)
  2. The size of a side must satisfy pixels = 2^n+1, n = 1,2,3,... ; Based on these, the gray-scale can be of sizes 3 x 3, 5 x 5, 9 x 9, and so on. (129 x 129, 257 x 257, 513 x 513 are good sizes)
  3. The image must be an 8-bit image (pixels of are 8-bit unsigned integers a.k.a. 'uint8')
To resize an image in GIMP: right click menu --> image --> scale image...

The image can then be saved by right click menu --> file --> export as..., and exporting it to the desktop as "YOURFILENAME.png". You can then exit GIMP.

Note: GIMP seems to automatically save the image as an 8-bit integer if you follow the above steps. Be careful, though, as not all image editors seem do this.

Creating a Gazebo Model File

Open up a terminal and change the directory to gazebo's model directory:

cd .gazebo/models

The easiest way to create a new model is to copy an existing model, and then modify it. The best model in the directory to do this with is ground_plane:

cp -r ground_plane/ YOURFILENAME

Go into the directory and list the files within:

cd YOURFILENAME/
ls

Two of the files in this directory should be model.config and model.sdf. First open up model.config in a text editor and change the meta information contained within to something appropriate for this model. It is important to note that the entry in the <name> space will be the name that appears in Gazebo's model menu. When you're done, save and close the file.

Next we need to modify model.sdf. Within the file at this point is the collision and visual definitions of the ground_plane model (standard to SDF and URDF files) from which we copied it. These are significantly different from what we need for a heightmap, and so we will need to copy from a more appropriate source. Enter the following into the terminal:

cp /usr/share/gazebo-7/worlds/heightmap.world model.sdf

When you open model.sdf, you will need to delete several portions that are not part of the heightmap defintion. Delete the <world> items (both at the beginning and the end), the entire <include> block, and all of the box objects. When you are done, the file will look like this:

<?xml version="1.0" ?>
<sdf version="1.5">
    <model name="heightmap">
      <static>true</static>
      <link name="link">
        <collision name="collision">
          <geometry>
            <heightmap>
              <uri>file://media/materials/textures/heightmap_bowl.png</uri>
              <size>129 129 10</size>
              <pos>0 0 0</pos>
            </heightmap>
          </geometry>
        </collision>
        <visual name="visual_abcedf">
          <geometry>
            <heightmap>
              <use_terrain_paging>false</use_terrain_paging>
              <texture>
                <diffuse>file://media/materials/textures/dirt_diffusespecular.png</diffuse>
                <normal>file://media/materials/textures/flat_normal.png</normal>
                <size>1</size>
              </texture>
              <texture>
                <diffuse>file://media/materials/textures/grass_diffusespecular.png</diffuse>
                <normal>file://media/materials/textures/flat_normal.png</normal>
                <size>1</size>
              </texture>
              <texture>
                <diffuse>file://media/materials/textures/fungus_diffusespecular.png</diffuse>
                <normal>file://media/materials/textures/flat_normal.png</normal>
                <size>1</size>
              </texture>
              <blend>
                <min_height>2</min_height>
                <fade_dist>5</fade_dist>
              </blend>
              <blend>
                <min_height>4</min_height>
                <fade_dist>5</fade_dist>
              </blend>
              <uri>file://media/materials/textures/heightmap_bowl.png</uri>
              <size>129 129 10</size>
              <pos>0 0 0</pos>
            </heightmap>
          </geometry>
        </visual>
      </link>
    </model>
</sdf>

Next, you will need to add the appropriate <uri> and <size> for the heightmap. In both the collision and visual definitions, change the <uri> so that it points to the model folder (don't worry that we don't yet have a /materials/textures/ path and the greyscale is not yet in the directory), and change the <size> to the desired size (in meters) for the simulation; the third number is the elevation of the highest point:

<uri>model://YOURFILENAME/materials/textures/YOURFILENAME.png</uri>
<size>YOURSIZE1 YOURSIZE2 YOURHEIGHT</size>

(Note: the two sizes here do not have to match)

Now we will move the greyscale image into the correct location. Create the materials/textures directory and move the greyscale image into it

mkdir -p materials/textures/ 
mv ~/Desktop/YOURFILENAME.png materials/textures

Open in Gazebo

Now we can try to load it into Gazebo. Run gazebo:

gazebo

In the insert tab on the right side of the screen, find your model.

When you find it, click its name and then click in the simulation window. The model will then spawn into the world (this may take a while depending on the size of your heightmap). You should now have a terrain heightmap in your Gazebo world.