2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

IgnitionGazebo講座02 GUIプラグインを作成する

Posted at

環境

この記事は以下の環境で動いています。

項目
CPU Core i5-3470
Ubuntu 22.04
GPU GTX 1050 Ti
GPU driver 535.86.05
ROS2 Humble
Ignition Gazebo Fortress

概要

IgnitionではPluginを使用することで、機能を拡張することが出来ます。今回はGUIプラグインを作成・使用をします。
Ignition GazeboのGUIはGazebo Classicから大きく変更されていて、画面上のほぞすべての表示要素をプラグインで制御できるようになっています。

予備知識

QtQuick

QtQuickとはQtの新たなUIフレームワークです。QML(Qt Meta-Object Language)というファイルを使ってUIを実装します。追加のパッケージが必要なため以下のコマンドでインストールします。

extrasのインストール
sudo apt install qml-module-qtquick-extras

GUIプラグインの作成

QML

ignition_plugin_lecture/src/switch_panel/SwitchPanel.qml
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import QtQuick.Extras 1.4
import "qrc:/qml"

Rectangle 
{
  Layout.minimumWidth: 400
  Layout.minimumHeight: 110

  Row {
    spacing: 5
    
    Button {
      text: "Forward"
      onPressed: { SwitchPanel.OnForwardButton(); }
    }

    Button {
      text: "Stop"
      onPressed: { SwitchPanel.OnStopButton(); }
    }

    Button {
      text: "Reverse"
      onPressed: { SwitchPanel.OnReverseButton(); }
    }
  }
}
  • qmlファイルを用いてUIを設計します。

  • トップにはRectangle要素を、その下にRow要素を置きます。

    • Layout.minimumWidth/Layout.minimumHeightは設定しないとGUIが正しく表示されないことがあります。
  • RowはQtでいうLayoutに近いもので配下の要素を水平に並べます。

  • Buttonは押しボタンの要素です。

    • onPressed以下にはボタンを押した時に実行される処理を書きます。この処理は後のccファイルに書きます。

c++コード

ignition_plugin_lecture/src/switch_panel/SwitchPanel.hpp
#include <ignition/gui/qt.h>
#include <ignition/transport/Node.hh>
#include <ignition/gui/Plugin.hh>

namespace iginition_plugin_lecture
{

class SwitchPanel : public ignition::gui::Plugin
{
  Q_OBJECT

public:
  SwitchPanel();
  virtual ~SwitchPanel();
  void LoadConfig(const tinyxml2::XMLElement * _pluginElem) override;

protected slots:
  void OnForwardButton(void);
  void OnStopButton(void);
  void OnReverseButton(void);

private:
  void CreateIgnitionIf(void);

private:
  ignition::transport::Node node_;
  ignition::transport::Node::Publisher speed_pub_;
  float forward_speed_{1.0f};
  float reverse_speed_{1.0f};
};

}  // namespace iginition_plugin_lecture
ignition_plugin_lecture/src/switch_panel/SwitchPanel.cpp
#include "SwitchPanel.hpp"

#include <ignition/msgs/float.pb.h>
#include <ignition/plugin/Register.hh>

namespace iginition_plugin_lecture
{

SwitchPanel::SwitchPanel() : Plugin()
{
  CreateIgnitionIf();
}

SwitchPanel::~SwitchPanel()
{
}

void SwitchPanel::LoadConfig(const tinyxml2::XMLElement * _pluginElem)
{
  if (!_pluginElem) {
    return;
  }

  auto forward_speed_elem = _pluginElem->FirstChildElement("forward_speed");
  if (nullptr != forward_speed_elem)
  {
    forward_speed_ = forward_speed_elem->FloatText();
  }

  auto reverse_speed_elem = _pluginElem->FirstChildElement("reverse_speed");
  if (nullptr != reverse_speed_elem)
  {
    reverse_speed_ = reverse_speed_elem->FloatText();
  }
}

void SwitchPanel::OnForwardButton(void) {
  ignition::msgs::Float float_msg;
  float_msg.set_data(forward_speed_);
  speed_pub_.Publish(float_msg);
}

void SwitchPanel::OnStopButton(void) {
  ignition::msgs::Float float_msg;
  float_msg.set_data(0.0f);
  speed_pub_.Publish(float_msg);
}

void SwitchPanel::OnReverseButton(void) {
  ignition::msgs::Float float_msg;
  float_msg.set_data(reverse_speed_);
  speed_pub_.Publish(float_msg);
}

void SwitchPanel::CreateIgnitionIf(void){
  this->speed_pub_ = this->node_.Advertise<ignition::msgs::Float>("target_speed");
}

}

// Register this plugin
IGNITION_ADD_PLUGIN(iginition_plugin_lecture::SwitchPanel, ignition::gui::Plugin)
  • ignition::gui::Pluginクラスを継承したクラスを作成します。
  • 起動時にLoadConfig()が呼ばれます。SDFファイルで子要素で書いた値が読めます。
  • OnForwardButton()OnStopButton()OnReverseButton()UIで作ったボタンの押した時の処理slots関数です。

ビルド系

qrcはリソースファイルで実行に必要なファイルを列挙するファイルです。のちのCMakeで指定します。画像ファイルなどを使うときはこれも記載に追加します。

ignition_plugin_lecture/src/switch_panel/SwitchPanel.qrc
<!DOCTYPE RCC><RCC version="1.0">
  <qresource prefix="SwitchPanel/">
    <file>SwitchPanel.qml</file>
  </qresource>
</RCC>

CmakeではQt特有の記述が入ります。

ignition_plugin_lecture/CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(ignition_plugin_lecture)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

set(CMAKE_AUTOMOC ON)

find_package(ament_cmake REQUIRED)
find_package(ignition-plugin1 REQUIRED COMPONENTS register)
find_package(ignition-gazebo6 REQUIRED)

include_directories(SYSTEM
  ${IGNITION-COMMON_INCLUDE_DIRS}
  ${IGNITION-GUI_INCLUDE_DIRS}
)

# gui plugin
qt5_add_resources(resources_rcc src/switch_panel/SwitchPanel.qrc)
add_library(SwitchPanel SHARED
  src/switch_panel/SwitchPanel.cpp
  ${resources_rcc}
)
target_link_libraries(SwitchPanel
  ${IGNITION-COMMON_LIBRARY_DIRS}
  ${IGNITION-GUI_LIBRARIES}
)

# system plugin
add_library(RotateAxis SHARED
  src/rotate_axis/rotate_axis.cpp
)
target_link_libraries(RotateAxis
  ${IGNITION-PLUGIN_LIBRARIES}
  ${IGNITION-GAZEBO_LIBRARIES}
)

install(
  TARGETS SwitchPanel RotateAxis
  LIBRARY DESTINATION lib
)

ament_environment_hooks("${CMAKE_CURRENT_SOURCE_DIR}/hooks/${PROJECT_NAME}.dsv.in")

ament_package()
  • set(CMAKE_AUTOMOC ON)を書いてQt用のMOCを有効にします。
  • qt5_add_resources()でqrcファイルを指定します。qmlファイルや画像を取り込んだc++ファイルが生成されます。
  • ターゲット名とQMLファイル名は一緒にします。
  • ament_environment_hooks()で環境変数を設定します。

GUIプラグインの使用

ignition_lecture/worlds/gui_example1.sdf
<?xml version="1.0" ?>

<sdf version="1.6">
  <world name="visualize_lidar_world">
    
    <gui fullscreen="0">
      <plugin filename="GzScene3D" name="3D View">
        <camera_pose>10 0 6 0 0.5 3.14</camera_pose>
        <ignition-gui>
          <title>3D View</title>
          <property type="bool" key="showTitleBar">false</property>
          <property type="string" key="state">docked</property>
        </ignition-gui>
      </plugin>

      <plugin filename="SwitchPanel" name="iginition_plugin_lecture::SwitchPanel">
        <forward_speed>0.3</forward_speed>
        <reverse_speed>-0.1</reverse_speed>
        <ignition-gui>
          <title>SwitchPanel</title>
          <property type="bool" key="showTitleBar">true</property>
          <property type="string" key="state">docked</property>
          <property key="resizable" type="bool">true</property>
        </ignition-gui>
      </plugin>

      <plugin filename="Teleop" name="ignition::gui::plugins::Teleop">
        <topic>/cmd_vel</topic>
        <ignition-gui>
          <property type="bool" key="showTitleBar">true</property>
          <property type="string" key="state">docked</property>
          <property key="resizable" type="bool">true</property>
        </ignition-gui>
      </plugin>
    </gui>

    <physics name="1ms" type="ignored">
      <max_step_size>0.001</max_step_size>
      <real_time_factor>1.0</real_time_factor>
    </physics>
    <plugin
      filename="libignition-gazebo-physics-system.so"
      name="ignition::gazebo::systems::Physics">
    </plugin>
    <plugin
      filename="libignition-gazebo-sensors-system.so"
      name="ignition::gazebo::systems::Sensors">
      <render_engine>ogre2</render_engine>
    </plugin>
    <plugin
      filename="libignition-gazebo-scene-broadcaster-system.so"
      name="ignition::gazebo::systems::SceneBroadcaster">
    </plugin>

    <light name="sun" type="directional">
      <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>

  </world>
</sdf>
  • <gui>タグの中でGUIの設定を書きます。このタグがない場合はignitionのデフォルトのGUIが適用されます。
    • <ignition-gui>以下ではパネルの設定を指定します。
      • <title>パネルのタイトルの文字を指定します。
      • 他はパネルのサイズの設定です。

ビルド&実行

ビルド
source /opt/ros/humble/setup.bash
cd ros2_ws
colcon build
実行
source ~/ros2_ws/install/setup.bash
ros2 launch ignition_lecture sim.launch.py
ros2 launch ignition_lecture gazebo.launch.py world:=gui_example1.sdf
ignトピックのecho
ign topic -e -t target_speed

gui_plugin.gif

参考

ignition pluginパス
gui pluginリファレンス

目次ページへのリンク

ROS2講座の目次へのリンク

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?