GUI Overlay - modulabs/gazebo-tutorial GitHub Wiki

Overview

Gazebo GUI ์˜ค๋ฒ„๋ ˆ์ด๋Š” ๋ Œ๋”๋ง ์œˆ๋„์šฐ์˜ ๊ผญ๋Œ€๊ธฐ์—์žˆ๋Š” ํˆฌ๋ช…ํ•œ 2D ๋ ˆ์ด์–ด๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. QT ์œ„์ ฏ์€ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด์ด ๋ ˆ์ด์–ด์— ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฉ”์ธ Gazebo ๋ฉ”๋‰ด ๋ฐ”์—์„œ View-> GUI Overlays๋ฅผ ํด๋ฆญํ•˜์—ฌ ๋ชจ๋“  GUI ์˜ค๋ฒ„๋ ˆ์ด๋ฅผ ๋ณด์ด๊ฑฐ๋‚˜ ๊ฐ์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ž์Šต์„œ์—์„œ๋Š” GUI ์˜ค๋ฒ„๋ ˆ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค๊ณ  ์‚ฌ์šฉํ•˜์—ฌ Gazebo์˜ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

GUI ์˜ค๋ฒ„๋ ˆ์ด ๊ธฐ๋Šฅ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ๋‘ ๊ฐ€์ง€ ์˜ˆ๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์˜ˆ์ œ์—์„œ๋Š” ๊ตฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฒ„ํŠผ์„ ๋งŒ๋“ค๊ณ  ๋‘ ๋ฒˆ์งธ ์˜ˆ์ œ์—์„œ๋Š” ํ˜„์žฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹œ๊ฐ„์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‘ ์˜ˆ์ œ๋Š” Gazebo๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๊ณ  Gazebo์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

Example 1: Spawn spheres

https://bitbucket.org/osrf/gazebo/src/gazebo9/examples/plugins/gui_overlay_plugin_spawn/ ์†Œ์Šค์ฝ”๋“œ๋Š” ์—ฌ๊ธฐ์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1.์ตœ์‹  Gazebo ๋ฒ„์ „์„ ์„ค์น˜ํ•˜์‹ญ์‹œ์˜ค.

2.์„ค์น˜ ํŽ˜์ด์ง€์˜ ์ง€์‹œ ์‚ฌํ•ญ์„ ๋”ฐ๋ฅด์‹ญ์‹œ์˜ค.

mkdir ~/gazebo_gui_spawn
cd ~/gazebo_gui_spawn
  1. GUI ์˜ค๋ฒ„๋ ˆ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์†Œ์Šค ์ฝ”๋“œ ๋‹ค์šด๋กœ๋“œ (OsX์—์„œ wget์€ curl -OL๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Œ)

    wget https://bitbucket.org/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_spawn/GUIExampleSpawnWidget.hh wget https://bitbucket.org/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_spawn/GUIExampleSpawnWidget.cc wget https://bitbucket.org/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_spawn/CMakeLists.txt

4.ํ—ค๋” ํŒŒ์ผ์„ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค.

gedit GUIExampleSpawnWidget.hh

   GUI ์˜ค๋ฒ„๋ ˆ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ GUIPlugin ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›์•„ Qt์˜ Q_OBJECT ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

        class GAZEBO_VISIBLE GUIExampleSpawnWidget : public GUIPlugin
        {
          Q_OBJECT

    ๋‚˜๋จธ์ง€ ํ”Œ๋Ÿฌ๊ทธ์ธ์—๋Š” ์‚ฌ์šฉ์ž์˜ ํ•„์š”์— ๋งž๊ฒŒ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์˜ˆ์—์„œ๋Š” QT ์Šฌ๋กฏ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค.

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

    Gazebo์˜ ๊ณต์žฅ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ SDF ์Šคํฐ ๋ฉ”์‹œ์ง€๋ฅผ gzserver๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.:

          /// \brief Node used to establish communication with gzserver.
          private: transport::NodePtr node;

          /// \brief Publisher of factory messages.
          private: transport::PublisherPtr factoryPub;

5.์†Œ์Šค ํŒŒ์ผ์„ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค.

gedit GUIExampleSpawnWidget.cc

    ์ด ํŒŒ์ผ์˜ ์ƒ์„ฑ์ž๋Š” QT๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฒ„ํŠผ์„ ๋งŒ๋“ค๊ณ ์ด๋ฅผ OnButton ์ฝœ๋ฐฑ์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.:

      // 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()));

    ๊ทธ ์ƒ์„ฑ์ž๋Š” ๋˜ํ•œ Gazebo์˜ ์ „์†ก ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ์—ฐ๊ฒฐํ•˜๊ณ  ๊ณต์žฅ ๊ฒŒ์‹œ์ž๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค:

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

    OnButton ์ฝœ๋ฐฑ์€ ์ƒˆ๋กœ์šด ๊ตฌํ˜• SDF ๋ฌธ์ž์—ด์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.:

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

    ๊ทธ๋ฆฌ๊ณ  ๊ฐ€์ œ๋ณด์—๊ฒŒ ๋ฌธ์ž์—ด์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.:

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

6.ํ”Œ๋Ÿฌ๊ทธ์ธ ์ปดํŒŒ์ผ

cd ~/gazebo_gui_spawn
mkdir build
cd build
cmake ../
make

7.์ด์ œ ์šฐ๋ฆฌ๋Š” Gazebo๊ฐ€ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋กํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋นŒ๋“œ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ GAZEBO_PLUGIN_PATH ํ™˜๊ฒฝ ๋ณ€์ˆ˜์— ์ถ”๊ฐ€ํ•˜์—ฌ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์œ„์˜ ๋ช…๋ น์€ ํ˜„์žฌ ์‰˜์—์„œ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ ํ„ฐ๋ฏธ๋„์„ ์—ด ๋•Œ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ / usr / local / lib์™€ ๊ฐ™์€ ์ผ๋ฐ˜์ ์ธ ๊ฒ€์ƒ‰ ๊ฒฝ๋กœ ๋‚˜ GAZEBO_PLUGIN_PATH ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ง€์ •๋œ ๊ฒฝ๋กœ ์ค‘ ํ•˜๋‚˜์— ์„ค์น˜ํ•˜์‹ญ์‹œ์˜ค.

8.๋˜ํ•œ ์˜ค๋ฒ„๋ ˆ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์„๋กœ๋“œํ•ด์•ผํ•œ๋‹ค๊ณ  Gazebo์— ์•Œ๋ฆด ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

    1.SDF world file : GUI ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํฌํ•จํ•˜๋„๋ก world SDF ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜์‹ญ์‹œ์˜ค. ์˜ˆ :

    <?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://bitbucket.org/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_spawn/spawn_widget_example.world

    2.GUI INI ํŒŒ์ผ : Gazebo๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ํ”Œ๋Ÿฌ๊ทธ์ธ์ด๋กœ๋“œ๋˜๋„๋ก ~ / .gazebo / gui.ini ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜์‹ญ์‹œ์˜ค.

    gedit ~/.gazebo/gui.ini

    Add the following lines:

    [overlay_plugins]
    filenames=libgui_example_spawn_widget.so
  1. ์ด์ œ Gazebo๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋ Œ๋”๋ง ์œˆ๋„์šฐ์˜ ์™ผ์ชฝ ์ƒ๋‹จ์— ๋ฒ„ํŠผ์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

GUI ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ์‚ฌ์šฉ์ž ์ •์˜ SDF ์›”๋“œ ํŒŒ์ผ์„ ์ƒ์„ฑ ํ•œ ๊ฒฝ์šฐ :

gazebo spawn_widget_example.world

๋˜๋Š” ~ / .gazebo / gui.ini๋ฅผ ์ˆ˜์ • ํ•œ ๊ฒฝ์šฐ

gazebo

Click on the button to spawn spheres.

Example 2: Display Simulation Time

์ด ์˜ˆ์ œ์˜ ์†Œ์Šค ์ฝ”๋“œ๋Š” ์—ฌ๊ธฐ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1.์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ ๋งŒ๋“ค๊ธฐ mkdir ~/gazebo_gui_time cd ~/gazebo_gui_time

2.GUI ์˜ค๋ฒ„๋ ˆ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์†Œ์Šค ์ฝ”๋“œ ๋‹ค์šด๋กœ๋“œ

wget https://bitbucket.org/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_time/GUIExampleTimeWidget.hh
wget https://bitbucket.org/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_time/GUIExampleTimeWidget.cc
wget https://bitbucket.org/osrf/gazebo/raw/gazebo9/examples/plugins/gui_overlay_plugin_time/CMakeLists.txt

3.ํ—ค๋” ํŒŒ์ผ์„ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค.

gedit GUIExampleTimeWidget.hh

    ์ฒซ ๋ฒˆ์งธ ์˜ˆ์ œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ GUIPlugin ํด๋ž˜์Šค์—์„œ ์ƒ์† ๋ฐ›๊ณ  Qt์˜ Q_OBJECT ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
      class GAZEBO_VISIBLE GUIExampleTimeWidget : public GUIPlugin
      {
        Q_OBJECT

   ํ‘œ์‹œ๋œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹œ๊ฐ„์„ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•ด SetSimTime ์‹ ํ˜ธ๋ฅผ ์Šค๋ ˆ๋“œ ์•ˆ์ „ ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

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

    OnStats ์ฝœ๋ฐฑ์€ Gazebo์—์„œ ์ •๋ณด๋ฅผ ์ˆ˜์‹ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

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

    ๋˜ํ•œ Gazebo์˜ ์ „์†ก ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ Gazebo์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.

        /// \brief Node used to establish communication with gzserver.
        private: transport::NodePtr node;

        /// \brief Subscriber to world statistics messages.
        private: transport::SubscriberPtr statsSub;

4.์†Œ์Šค ํŒŒ์ผ์„ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค.

gedit GUIExampleTimeWidget.cc

    ์ƒ์„ฑ์ž์—์„œ ์‹œ๊ฐ„์„ ํ‘œ์‹œํ•˜๋Š” QLabel์„ ๋งŒ๋“ค๊ณ ์ด๋ฅผ SetSimeTime ์‹ ํ˜ธ์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

      // 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);

    ์ƒ์„ฑ์ž๋Š” Gazebo์˜ ~ / world_stats ํ•ญ๋ชฉ์—๋„ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

      // 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);

    ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์œผ๋ฉด OnStats ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  ํ‘œ์‹œ๋œ ์‹œ๊ฐ„์ด ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค.

    void GUIExampleTimeWidget::OnStats(ConstWorldStatisticsPtr &_msg)
    {
      this->SetSimTime(QString::fromStdString(
            this->FormatTime(_msg->sim_time())));

5.์ด์ „ ํŠœํ† ๋ฆฌ์–ผ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„์— ๋”ฐ๋ผ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ปดํŒŒ์ผํ•˜๊ณ  Gazebo์— ์ฐพ์•„์„œ gui.ini ๋˜๋Š” SDF world ํŒŒ์ผ์„ ํ†ตํ•ด๋กœ๋“œํ•˜์‹ญ์‹œ์˜ค.

    Tip: ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‘ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋ชจ๋‘ gui.ini์— ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     gedit ~/.gazebo/gui.ini

    [overlay_plugins] ์„น์…˜์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝํ•˜์‹ญ์‹œ์˜ค.

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

    ์ด์ „ ์˜ˆ์ œ์˜ spawn sphere plugin๊ณผ์ด ์˜ˆ์ œ์˜ time plugin์„ ๋ชจ๋‘๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

6.Gazebo๊ฐ€ ์‹คํ–‰๋˜๋ฉด ์Šคํฐ ๋ฒ„ํŠผ ์˜ค๋ฅธ์ชฝ์— ์ƒˆ ํ…์ŠคํŠธ ์ƒ์ž์— ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹œ๊ฐ„์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

gazebo
โš ๏ธ **GitHub.com Fallback** โš ๏ธ