World plugins - modulabs/gazebo-tutorial GitHub Wiki

Prerequisites:

Code:

Source code: gazebo/examples/plugins/factory

์‹คํ–‰์ค‘์ธ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ ์–ด๋–ค ๋ชจ๋ธ์ด ์กด์žฌํ•˜๋Š”์ง€ ๊ทธ๋ฆฌ๊ณ  ์–ธ์ œ ์‚ฝ์ž…๋˜์–ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์€ ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฒˆ ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ์‚ฌ์ „ ์ •์˜๋œ ๋ชจ๋ธ๊ณผ ์‚ฌ์šฉ์ž ์ •์˜ ๋ชจ๋ธ์„ ๊ฐ€์ œ๋ณด์— ์‚ฝ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•œ๋‹ค.

์ด์ „์— ์„ค๋ช…ํ•œ gazebo_plugin_tutorial์„ ์‚ฌ์šฉํ•œ๋‹ค

$ mkdir ~/gazebo_plugin_tutorial
$ cd ~/gazebo_plugin_tutorial

์ƒˆ๋กœ์šด ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค:

$ gedit factory.cc

factory.cc ํŒŒ์ผ์— ์•„๋ž˜ ๋‚ด์šฉ์„ ๋ณต์‚ฌํ•œ๋‹ค:

#include <ignition/math/Pose3.hh>
#include "gazebo/physics/physics.hh"
#include "gazebo/common/common.hh"
#include "gazebo/gazebo.hh"

namespace gazebo
{
class Factory : public WorldPlugin
{
  public: void Load(physics::WorldPtr _parent, sdf::ElementPtr /*_sdf*/)
  {
    // Option 1: Insert model from file via function call.
    // The filename must be in the GAZEBO_MODEL_PATH environment variable.
    _parent->InsertModelFile("model://box");

    // Option 2: Insert model from string via function call.
    // Insert a sphere model from string
    sdf::SDF sphereSDF;
    sphereSDF.SetFromString(
       "<sdf version ='1.4'>\
          <model name ='sphere'>\
            <pose>1 0 0 0 0 0</pose>\
            <link name ='link'>\
              <pose>0 0 .5 0 0 0</pose>\
              <collision name ='collision'>\
                <geometry>\
                  <sphere><radius>0.5</radius></sphere>\
                </geometry>\
              </collision>\
              <visual name ='visual'>\
                <geometry>\
                  <sphere><radius>0.5</radius></sphere>\
                </geometry>\
              </visual>\
            </link>\
          </model>\
        </sdf>");
    // Demonstrate using a custom model name.
    sdf::ElementPtr model = sphereSDF.Root()->GetElement("model");
    model->GetAttribute("name")->SetFromString("unique_sphere");
    _parent->InsertModelSDF(sphereSDF);

    // Option 3: Insert model from file via message passing.
    {
      // Create a new transport node
      transport::NodePtr node(new transport::Node());

      // Initialize the node with the world name
      node->Init(_parent->GetName());

      // Create a publisher on the ~/factory topic
      transport::PublisherPtr factoryPub =
      node->Advertise<msgs::Factory>("~/factory");

      // Create the message
      msgs::Factory msg;

      // Model file to load
      msg.set_sdf_filename("model://cylinder");

      // Pose to initialize the model to
      msgs::Set(msg.mutable_pose(),
          ignition::math::Pose3d(
            ignition::math::Vector3d(1, -2, 0),
            ignition::math::Quaterniond(0, 0, 0)));

      // Send the message
      factoryPub->Publish(msg);
    }
  }
};

// Register this plugin with the simulator
GZ_REGISTER_WORLD_PLUGIN(Factory)
}

The Code Explained

์ฝ”๋“œ์˜ ์ฒซ๋ถ€๋ถ„์— world ๋Ÿฌ๊ทธ์ธ์„ ์ƒ์„ฑํ•œ๋‹ค.

#include <ignition/math/Pose3.hh>
#include "gazebo/physics/physics.hh"
#include "gazebo/common/common.hh"
#include "gazebo/gazebo.hh"

namespace gazebo
{
class Factory : public WorldPlugin
{
  public: void Load(physics::WorldPtr _parent, sdf::ElementPtr /*_sdf*/)

Load ํ•จ์ˆ˜์—์„œ๋Š” ๋ชจ๋ธ ์‚ฝ์ž…์„ ์œ„ํ•œ ์„ธ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

์ฒซ๋ฒˆ์งธ๋Š” World method๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GAZEBO_MODEL_PATH ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ •์˜๋œ ๋ฆฌ์†Œ์Šค ๊ฒฝ๋กœ์— ์žˆ๋Š” ํŒŒ์ผ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ชจ๋ธ์„ ๋กœ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

    // Option 1: Insert model from file via function call.
    // The filename must be in the GAZEBO_MODEL_PATH environment variable.
    _parent->InsertModelFile("model://box");

๋‘๋ฒˆ์งธ๋Š” World method๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด ๋ฐ์ดํ„ฐ(string data)๋กœ ์ด๋ฃจ์–ด์ง„ ๋ชจ๋ธ ํŒŒ์ผ์„ ๋กœ๋“œํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

    // Option 2: Insert model from string via function call.
    // Insert a sphere model from string
    sdf::SDF sphereSDF;
    sphereSDF.SetFromString(
       "<sdf version ='1.4'>\
          <model name ='sphere'>\
            <pose>1 0 0 0 0 0</pose>\
            <link name ='link'>\
              <pose>0 0 .5 0 0 0</pose>\
              <collision name ='collision'>\
                <geometry>\
                  <sphere><radius>0.5</radius></sphere>\
                </geometry>\
              </collision>\
              <visual name ='visual'>\
                <geometry>\
                  <sphere><radius>0.5</radius></sphere>\
                </geometry>\
              </visual>\
            </link>\
          </model>\
        </sdf>");
    // Demonstrate using a custom model name.
    sdf::ElementPtr model = sphereSDF.Root()->GetElement("model");
    model->GetAttribute("name")->SetFromString("unique_sphere");
    _parent->InsertModelSDF(sphereSDF);

์„ธ๋ฒˆ์งธ๋Š” ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ์„ ์‚ฝ์ž…ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ๊ฐ€์ œ๋ณด์™€ ํ†ต์‹ ํ•˜๋Š” ๋…๋ฆฝ ์‹คํ–‰ํ˜• ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ๊ฐ€์žฅ ์œ ์šฉํ•˜๋‹ค

    // Option 3: Insert model from file via message passing.
    {
      // Create a new transport node
      transport::NodePtr node(new transport::Node());

      // Initialize the node with the world name
      node->Init(_parent->GetName());

      // Create a publisher on the ~/factory topic
      transport::PublisherPtr factoryPub =
      node->Advertise<msgs::Factory>("~/factory");

      // Create the message
      msgs::Factory msg;

      // Model file to load
      msg.set_sdf_filename("model://cylinder");

      // Pose to initialize the model to
      msgs::Set(msg.mutable_pose(),
          ignition::math::Pose3d(
            ignition::math::Vector3d(1, -2, 0),
            ignition::math::Quaterniond(0, 0, 0)));

      // Send the message
      factoryPub->Publish(msg);

Compile

Plugin Overview Tutorial ๊ณผ์ •์„ ๊ฑฐ์ณค๋‹ค๋ฉด, ์œ„ ์ฝ”๋“œ๋ฅผ ~/gazebo_plugin_tutorial/factory.cc๋กœ ์ €์žฅํ•˜๊ณ  ~/gazebo_plugin_tutorial/CMakeLists.txt์— ๋‹ค์Œํ–‰์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

add_library(factory SHARED factory.cc)
target_link_libraries(factory ${GAZEBO_LIBRARIES})

์ด ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผ ํ•˜๋ฉด, ๊ฐ€์ œ๋ณด ์‹œ๋ฎฌ๋ ˆ์ด์…˜์— ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ๊ณต์œ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ~/gazebo_plugin_tutorial/build/libfactory.so๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค

$ mkdir ~/gazebo_plugin_tutorial/build
$ cd ~/gazebo_plugin_tutorial/build
$ cmake ../
$ make

Make the shapes

๋ชจ๋ธ ๋””๋ ‰ํ† ๋ฆฌ์™€ ๋ฐ•์Šค, ์‹ค๋ฆฐ๋”๋ฅผ ๋งŒ๋“ ๋‹ค

$ mkdir ~/gazebo_plugin_tutorial/models
$ cd ~/gazebo_plugin_tutorial/models
$ mkdir box cylinder

๋ฐ•์Šค ๋ชจ๋ธ์„ ๋งŒ๋“ ๋‹ค

$ cd box
$ gedit model.sdf

box/model.sdf์— ์•„๋ž˜ ๋‚ด์šฉ์„ ๋ณต์‚ฌํ•œ๋‹ค

<?xml version='1.0'?>
<sdf version ='1.6'>
  <model name ='box'>
    <pose>1 2 0 0 0 0</pose>
    <link name ='link'>
      <pose>0 0 .5 0 0 0</pose>
      <collision name ='collision'>
        <geometry>
          <box><size>1 1 1</size></box>
        </geometry>
      </collision>
      <visual name ='visual'>
        <geometry>
          <box><size>1 1 1</size></box>
        </geometry>
      </visual>
    </link>
  </model>
</sdf>

model.config ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค

$ gedit model.config

model.config์— ์•„๋ž˜ ๋‚ด์šฉ์„ ๋ณต์‚ฌํ•œ๋‹ค

<?xml version='1.0'?>

<model>
  <name>box</name>
  <version>1.0</version>
  <sdf >model.sdf</sdf>

  <author>
    <name>me</name>
    <email>[email protected]</email>
  </author>

  <description>
    A simple Box.
  </description>
</model>

์‹ค๋ฆฐ๋” ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™ํ•˜์—ฌ ์ƒˆ๋กœ์šด model.sdf ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค

$ cd ~/gazebo_plugin_tutorial/models/cylinder
$ gedit model.sdf

model.sdf์— ์•„๋ž˜ ๋‚ด์šฉ์„ ๋ณต์‚ฌํ•œ๋‹ค

<?xml version='1.0'?>
<sdf version ='1.6'>
  <model name ='cylinder'>
    <pose>1 2 0 0 0 0</pose>
    <link name ='link'>
      <pose>0 0 .5 0 0 0</pose>
      <collision name ='collision'>
        <geometry>
          <cylinder><radius>0.5</radius><length>1</length></cylinder>
        </geometry>
      </collision>
      <visual name='visual'>
        <geometry>
          <cylinder><radius>0.5</radius><length>1</length></cylinder>
        </geometry>
      </visual>
    </link>
  </model>
</sdf>

model.config ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค

$ gedit model.config

model.config ํŒŒ์ผ์— ์•„๋ž˜ ๋‚ด์šฉ์„ ๋ณต์‚ฌํ•œ๋‹ค

<?xml version='1.0'?>

<model>
  <name>cylinder</name>
  <version>1.0</version>
  <sdf>model.sdf</sdf>

  <author>
    <name>me</name>
    <email>[email protected]</email>
  </author>

  <description>
    A simple cylinder.
  </description>
</model>

Run the code

$GAZEBO_MODEL_PATH๊ฐ€ ์ƒˆ ๋ชจ๋ธ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ฐธ์กฐํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค

$ export GAZEBO_MODEL_PATH=$HOME/gazebo_plugin_tutorial/models:$GAZEBO_MODEL_PATH

GAZEBO_PLUGIN_PATH์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค:

$ export GAZEBO_PLUGIN_PATH=$HOME/gazebo_plugin_tutorial/build:$GAZEBO_PLUGIN_PATH

world SDF ํŒŒ์ผ ~/gazebo_plugin_tutorial/factory.world์„ ์ƒ์„ฑํ•œ๋‹ค

$ cd ~/gazebo_plugin_tutorial
$ gedit factory.world

world์— ์•„๋ž˜ ๋‚ด์šฉ์„ ๋ณต์‚ฌํ•œ๋‹ค

<?xml version="1.0"?>
<sdf version="1.4">
  <world name="default">
    <include>
      <uri>model://ground_plane</uri>
    </include>

    <include>
      <uri>model://sun</uri>
    </include>

    <plugin name="factory" filename="libfactory.so"/>
  </world>
</sdf>

๊ฐ€์ œ๋ณด ์‹คํ–‰

$ gazebo ~/gazebo_plugin_tutorial/factory.world

๊ฐ€์ œ๋ณด ์ฐฝ์—๋Š” ๊ตฌ, ์ƒ์ž, ์‹ค๋ฆฐ๋”๊ฐ€ ์—ฐ์†์œผ๋กœ ๋ฐฐ์น˜๋œ ํ™˜๊ฒฝ์ด ๋ณด์—ฌ์•ผ ํ•œ๋‹ค.

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