GUI Overlay


Overview

The Gazebo GUI overlay can be thought of as a transparent 2D layer that sits on top of the render window. QT widgets can be added to this layer through a plugin interface. You can show or hide all GUI overlays by clicking on View->GUI Overlays on the main Gazebo menu bar. This tutorial describes how to create and use GUI overlay plugins to create custom interfaces for Gazebo.

Two examples will be used to demonstrate the GUI Overlay functionality. The first example creates a button that spawns a sphere, and the second displays the current simulation time. These two examples show how to send data to Gazebo and receive data from Gazebo.

Example 1: Spawn spheres

The source code for this example is found here.

  1. Install the latest Gazebo version: follow the instructions of the install page

  2. Start by creating a working directory

    mkdir ~/gazebo_gui_spawn
    cd ~/gazebo_gui_spawn
    
  3. Download the source code for the GUI overlay plugin (On OsX, wget can be replaced with curl -OL)

    wget https://github.com/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_spawn/GUIExampleSpawnWidget.hh
    wget https://github.com/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_spawn/GUIExampleSpawnWidget.cc
    wget https://github.com/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_spawn/CMakeLists.txt
    
  4. Take a look at the header file.

    gedit GUIExampleSpawnWidget.hh
    

    A GUI overlay plugin must inherit from the GUIPlugin class, and use Qt's Q_OBJECT macro.

        class GAZEBO_VISIBLE GUIExampleSpawnWidget : public GUIPlugin
        {
          Q_OBJECT
    

    The rest of the plugin may contain any code that is required to make the plugin meet your needs. In this example, we will use a QT slot to receive button presses:

          /// \brief Callback trigged when the button is pressed.
          protected slots: void OnButton()
    

    We will also use Gazebo's factory functionality to send SDF spawn messages to gzserver:

          /// \brief Node used to establish communication with gzserver.
          private: transport::NodePtr node;
    
          /// \brief Publisher of factory messages.
          private: transport::PublisherPtr factoryPub;
    
  5. Take a look at the source file.

    gedit GUIExampleSpawnWidget.cc
    

    The constructor in this file uses QT to create a button and attach it to our OnButton callback:

      // Create a push button, and connect it to the OnButton function
      QPushButton *button = new QPushButton(tr("Spawn Sphere"));
      connect(button, SIGNAL(clicked()), this, SLOT(OnButton()));
    

    The constructor also connects to Gazebo's transport mechanism and creates a factory publisher:

      // Create a node for transportation
      this->node = transport::NodePtr(new transport::Node());
      this->node->Init();
      this->factoryPub = this->node->Advertise<msgs::Factory>("~/factory");
    

    The OnButton callback creates a new sphere SDF string:

      std::ostringstream newModelStr;
      newModelStr << "<sdf version='" << SDF_VERSION << "'>"
        << msgs::ModelToSDF(model)->ToString("")
        << "</sdf>";
    

    and sends the string to Gazebo:

      msgs::Factory msg;
      msg.set_sdf(newModelStr.str());
      this->factoryPub->Publish(msg);
    }
    
  6. Compile the plugin

    cd ~/gazebo_gui_spawn
    mkdir build
    cd build
    cmake ../
    make
    
  7. Now we need to make sure Gazebo can find the plugin. You can do this by appending the build directory to the GAZEBO_PLUGIN_PATH environment variable:

    cd ~/gazebo_gui_spawn/build
    export GAZEBO_PLUGIN_PATH=`pwd`:$GAZEBO_PLUGIN_PATH
    

    Note that the command above works only for the current shell. To make sure the plugin will work when opening new terminals, install the plugin into a common search path, such as /usr/local/lib, or into one of the paths specified by the GAZEBO_PLUGIN_PATH library.

  8. We also need to tell Gazebo that it should load the overlay plugin.

    There are two methods to accomplish this.

    1. SDF world file: Modify a world SDF file to contain the GUI plugin. For example:

      <?xml version="1.0" ?>
      <sdf version="1.5">
        <world name="default">
      
          <gui>
            <plugin name="sample" filename="libgui_example_spawn_widget.so"/>
          </gui>
      
          <!-- A global light source -->
          <include>
            <uri>model://sun</uri>
          </include>
          <!-- A ground plane -->
          <include>
            <uri>model://ground_plane</uri>
          </include>
        </world>
      </sdf>
      

      Tip: Download the world file above:

      cd ~/gazebo_gui_spawn
      wget https://github.com/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_spawn/spawn_widget_example.world
      
    2. GUI INI file: Modify the ~/.gazebo/gui.ini file so the plugin is loaded every time Gazebo is run:

      gedit ~/.gazebo/gui.ini
      

      Add the following lines:

      [overlay_plugins]
      filenames=libgui_example_spawn_widget.so
      
  9. Now when Gazebo is run, a button should appear in the upper left of the render window.

    If you created a custom SDF world file with with GUI plugin:

    gazebo spawn_widget_example.world
    

    or if you modified ~/.gazebo/gui.ini

    gazebo
    

  10. Click on the button to spawn spheres.

Example 2: Display Simulation Time

The source code for this example is found here.

  1. Start by creating a working directory

    mkdir ~/gazebo_gui_time
    cd ~/gazebo_gui_time
    
  2. Download the source code for the GUI overlay plugin

    wget https://github.com/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_time/GUIExampleTimeWidget.hh
    wget https://github.com/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_time/GUIExampleTimeWidget.cc
    wget https://github.com/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_time/CMakeLists.txt
    
  3. Take a look at the header file.

    gedit GUIExampleTimeWidget.hh
    

    Just as in the first example, this plugin inherits from the GUIPlugin class, and use Qt's Q_OBJECT macro.

      class GAZEBO_VISIBLE GUIExampleTimeWidget : public GUIPlugin
      {
        Q_OBJECT
    

    We use SetSimTime signal as a thread safe mechanism to update the displayed simulation time.

        /// \brief A signal used to set the sim time line edit.
        /// \param[in] _string String representation of sim time.
        signals: void SetSimTime(QString _string);
    

    An OnStats callback is used to receive information from Gazebo.

        /// \brief Callback that received world statistics messages.
        /// \param[in] _msg World statistics message that is received.
        protected: void OnStats(ConstWorldStatisticsPtr &_msg);
    

    We will also use Gazebo's transport mechanism to receive messages from Gazebo.

        /// \brief Node used to establish communication with gzserver.
        private: transport::NodePtr node;
    
        /// \brief Subscriber to world statistics messages.
        private: transport::SubscriberPtr statsSub;
    
  4. Take a look at the source file.

    gedit GUIExampleTimeWidget.cc
    

    In the constructor, we create a QLabel to display the time, and connect it to the SetSimeTime signal.

      // Create a time label
      QLabel *timeLabel = new QLabel(tr("00:00:00.00"));
    
      // Add the label to the frame's layout
      frameLayout->addWidget(label);
      frameLayout->addWidget(timeLabel);
      connect(this, SIGNAL(SetSimTime(QString)),
          timeLabel, SLOT(setText(QString)), Qt::QueuedConnection);
    

    The constructor also connects to Gazebo's ~/world_stats topic.

      // Create a node for transportation
      this->node = transport::NodePtr(new transport::Node());
      this->node->Init("default");
      this->statsSub = this->node->Subscribe("~/world_stats",
          &GUIExampleTimeWidget::OnStats, this);
    

    When a message is received, the OnStats function is called and the displayed time is updated.

    void GUIExampleTimeWidget::OnStats(ConstWorldStatisticsPtr &_msg)
    {
      this->SetSimTime(QString::fromStdString(
            this->FormatTime(_msg->sim_time())));
    
  5. Follow the same steps as the previous tutorial to compile the plugin, tell Gazebo where to find it and load it via gui.ini or an SDF world file.

    Tip: You can add both plugins to gui.ini as follows:

     gedit ~/.gazebo/gui.ini
    

    Change the [overlay_plugins] section to be:

     [overlay_plugins]
     filenames=libgui_example_spawn_widget.so:libgui_example_time_widget.so
    

    This will load both the spawn sphere plugin from the previous example and the time plugin from this example.

  6. When Gazebo is run, a new text box to the right of the spawn button should show the simulation time.

    gazebo