Custom messages - modulabs/gazebo-tutorial GitHub Wiki

Introduction

Gazebo ํ•ญ๋ชฉ์€ Google ํ”„๋กœํ† ์ฝœ ๋ฉ”์‹œ์ง€๋ฅผ ํ†ตํ•ด ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์ œ๋ณด๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ด‘๋ฒ”์œ„ํ•œ ๋ฉ”์‹œ์ง€ ์œ ํ˜• ๋ชฉ๋ก์ด ๊ฐ€์ œ๋ณด ์ฃผ์ œ ๊ตฌ๋… ๋ฐ ๊ฒŒ์‹œ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ๋‹น์‹ ์ด ๋‹น์‹  ์ž์‹ ์˜ ๊ฒƒ์„ ๋งŒ๋“ค๊ณ  ์‹ถ์–ดํ•˜๋Š” ๋งŽ์€ ์ƒํ™ฉ๋“ค์ด์žˆ๋‹ค.

์ด ์ž์Šต์„œ๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ Gazebo ํ”Œ๋Ÿฌ๊ทธ์ธ์—์„œ ๊ตฌ๋…ํ•˜๊ณ  ๊ฒŒ์‹œํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค.

About this code

์ด ํ”„๋กœ์ ํŠธ๊ฐ€ ๋๋‚˜๋ฉด Gazebo World์˜ 2D ์ถฉ๋Œ ๋งต์„ ๋งŒ๋“ค ์ˆ˜์žˆ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ ์ธ์€ Gazebo์—์„œ ์„ธ๊ณ„๋ฅผ ๋ž˜์Šคํ„ฐ ํ™”ํ•ฉ๋‹ˆ๋‹ค. RayShape๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ์ด ๊ฒฉ์ž ์•„๋ž˜์—์„œ ๊ด‘์„  ๊ต์ฐจ๋ฅผํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ ๋œ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉ์ž ์ •์˜ ํ•ญ๋ชฉ์— ๊ฒŒ์‹œํ•˜๊ณ  ํŒŒ์ผ๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์†Œ์Šค ์ฝ”๋“œ๋Š” BitBucket์— ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ์„ ์„ ์œ„ํ•ด ๋ฌธ์ œ๋ฅผ ์ œ๊ธฐํ•˜๊ฑฐ๋‚˜ ์š”์ฒญ์„ ์ œ์ถœํ•˜์‹ญ์‹œ์˜ค. ์ฝ”๋“œ์˜ ์›๋ž˜ ์ž‘์„ฑ์ž๋Š” Stephen Brawner์ž…๋‹ˆ๋‹ค.

mercurial์„ ์‚ฌ์šฉํ•˜์—ฌ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

hg clone https://bitbucket.org/osrf/collision_map_creator_plugin

๋˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ์•„๋ž˜ ์„ค๋ช… ๋œ๋Œ€๋กœ ํŒŒ์ผ์— ๋ถ™์—ฌ ๋„ฃ์œผ์‹ญ์‹œ์˜ค.

Writing your own message

Gazebo์˜ ์ด๋ฏธ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฉ”์‹œ์ง€ ์œ ํ˜• ์ค‘ ํ•˜๋‚˜์— ๊ตฌ๋…์ž / ๊ฒŒ์‹œ์ž ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ€์–ด ๋„ฃ๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ์–ด๋ ต๋‹ค๋ฉด ์ž์‹ ์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ณต์žกํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ž‘์„ฑํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋‹ค์–‘ํ•œ ๋ฉ”์‹œ์ง€ ์œ ํ˜•์„ ๊ฒฐํ•ฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Gazebo์—๋Š” ์ด๋ฏธ ๋ฉ”์‹œ์ง€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์„ค์น˜๋œ ๋ฉ”์‹œ์ง€๋Š” ๋ฐ๋น„์•ˆ ์„ค์น˜๋ฅผ ์œ„ํ•ด / usr / include / gazebo- / gazebo / msgs / proto์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ž์Šต์„œ์—์„œ๋Š” vector2d.proto ๋ฉ”์‹œ์ง€๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

~ / collision_map_creator_plugin / msgs / collision_map_request.proto๋ฅผ๋ณด๊ณ  ๋งž์ถค ๋ฉ”์‹œ์ง€๊ฐ€ ์–ด๋–ป๊ฒŒ ์„ ์–ธ๋˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

package collision_map_creator_msgs.msgs;
import "vector2d.proto";

message CollisionMapRequest
{
  required gazebo.msgs.Vector2d   upperLeft  = 1;
  required gazebo.msgs.Vector2d   upperRight = 2;
  required gazebo.msgs.Vector2d   lowerRight = 3;
  required gazebo.msgs.Vector2d   lowerLeft  = 4;
  required double                 height     = 5;
  required double                 resolution = 6;
  optional string                 filename   = 7 [default = ""];
  optional int32                  threshold  = 8 [default = 255];
}

Code explained

๋จผ์ € package ์„ ์–ธ๊ณผ ํ•จ๊ป˜์ด ๋ฉ”์‹œ์ง€๊ฐ€ ์‚ด์•„์žˆ๋Š” ๋„ค์ž„ ์ŠคํŽ˜์ด์Šค๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

package collision_map_creator_msgs.msgs;

Gazebo์˜ vector2d๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ํฌํ•จํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค (๋ฉ”์‹œ์ง€์˜ ์œ„์น˜๋Š” CMakeLists.txt์—์„œ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค).

import "vector2d.proto";

์ด๊ฒƒ์ด ์‹ค์ œ ๋ฉ”์‹œ์ง€ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

message CollisionMapRequest{}

๊ฐ ๋ฉ”์„ธ์ง€ ํ•„๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ ์–ธํ•˜์‹ญ์‹œ์˜ค.

["optional"/"required"] [field type] [field name] = [enum];

๊ฐ ์—ด๊ฑฐ ํ˜•์€ ๊ณ ์œ  ํ•œ ์ˆซ์ž ์—ฌ์•ผํ•ฉ๋‹ˆ๋‹ค. ์ „์ฒด ํŒจํ‚ค์ง€ ์ด๋ฆ„์€ ์™ธ๋ถ€ ๋ฉ”์‹œ์ง€ (์ด ๊ฒฝ์šฐ gazebo.msgs)๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

required gazebo.msgs.Vector2d upperLeft = 1; required gazebo.msgs.Vector2d upperRight = 2; required gazebo.msgs.Vector2d lowerRight = 3; required gazebo.msgs.Vector2d lowerLeft = 4; required double height = 5; required double resolution = 6;

๋ฉ”์‹œ์ง€์—๋Š” ์„ ํƒ์  ํ•„๋“œ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ ํƒ์  ํ•„๋“œ๊ฐ€ ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์„ ํƒ์  ํ•„๋“œ์— ๊ธฐ๋ณธ๊ฐ’์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์–ด๋–ป๊ฒŒ ๊ทธ ๋ฐฉ๋ฒ•์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค.

optional string filename = 7 [default = ""]; optional int32 threshold = 8 [default = 255];

CMakeLists for custom messages

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” protobuf ๋ฉ”์‹œ์ง€ ์ •์˜์—์„œ C ++ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑ ํ•  ~/collision_map_creator/msgs/CMakeLists.txt ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Code explained

CMake์—๊ฒŒ Protobuf ํŒจํ‚ค์ง€๋ฅผ ํฌํ•จํ•˜๋„๋ก ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

find_package(Protobuf REQUIRED)

์ด ์„น์…˜์—์„œ๋Š” ๋ฉ”์‹œ์ง€๊ฐ€ ์„ค์น˜๋œ ์œ„์น˜๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. ๋ฉ”์‹œ์ง€ ํŒŒ์ผ์€ ๋ฐ๋น„์•ˆ ์„ค์น˜๋ฅผ ์œ„ํ•ด /usr/include/gazebo-<YOUR_GAZEBO_VERSION>/gazebo/msgs/proto ์— ์ €์žฅ๋˜์ง€๋งŒ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค๋ฅธ ๊ณณ์— ์„ค์น˜ํ–ˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” gazebo-XX ํด๋”๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์ด์— ๋”ฐ๋ผ PROTOBUF_IMPORT_DIRS ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. PROTOBUF_IMPORT_DIRS ๋Š” ์ถ”๊ฐ€ ๋ฉ”์‹œ์ง€ ํŒŒ์ผ์˜ ์œ„์น˜๋ฅผ โ€‹โ€‹์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

set(PROTOBUF_IMPORT_DIRS)
foreach(ITR ${GAZEBO_INCLUDE_DIRS})
  if(ITR MATCHES ".*gazebo-[0-9.]+$")
    set(PROTOBUF_IMPORT_DIRS "${ITR}/gazebo/msgs/proto")
  endif()
endforeach()

vector2d.proto ๋ฉ”์‹œ์ง€, dependencies time.proto ๋ฐ header.proto ๋ฐ collision_map_request.proto ๋ฉ”์‹œ์ง€์™€ ํ•จ๊ป˜ msgs ๋ผ๋Š” ๋ชฉ๋ก์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

set (msgs
  collision_map_request.proto
  ${PROTOBUF_IMPORT_DIRS}/vector2d.proto
  ${PROTOBUF_IMPORT_DIRS}/header.proto
  ${PROTOBUF_IMPORT_DIRS}/time.proto
)

๋ฉ”์‹œ์ง€์— ํ•„์š”ํ•œ C ++ ํ—ค๋”์™€ ์†Œ์Šค ํŒŒ์ผ์„ ๋นŒ๋“œํ•˜์‹ญ์‹œ์˜ค.

PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${msgs})

์ด ๋ฉ”์‹œ์ง€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์˜ ๋งํฌ์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด๋ฆ„์€ ์•„๋ž˜์˜ ๋‹ค๋ฅธ CMakeLists.txt ์ง€์ •๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด๋ฆ„๊ณผ ๋™์ผํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

add_library(collision_map_creator_msgs SHARED ${PROTO_SRCS})
target_link_libraries(collision_map_creator_msgs ${PROTOBUF_LIBRARY})

Collision Map Creator Plugin

์ด๊ฒƒ์€ ์‚ฌ์šฉ์ž ์ •์˜ Gazebo ์›”๋“œ ํ”Œ๋Ÿฌ๊ทธ์ธ ( ~/collision_map_creator_plugin/collision_map_creator.cc )์˜ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

#include <iostream>
#include <math.h>
#include <boost/gil/gil_all.hpp>
#include <boost/gil/extension/io/png_dynamic_io.hpp>
#include <boost/shared_ptr.hpp>        
#include <sdf/sdf.hh>
#include <ignition/math/Vector3.hh>

#include "gazebo/gazebo.hh"
#include "gazebo/common/common.hh"
#include "gazebo/msgs/msgs.hh"
#include "gazebo/physics/physics.hh"
#include "gazebo/transport/transport.hh"
#include "collision_map_request.pb.h"

namespace gazebo
{
typedef const boost::shared_ptr<
  const collision_map_creator_msgs::msgs::CollisionMapRequest>
    CollisionMapRequestPtr;

class CollisionMapCreator : public WorldPlugin
{
  transport::NodePtr node;
  transport::PublisherPtr imagePub;
  transport::SubscriberPtr commandSubscriber;
  physics::WorldPtr world;

  public: void Load(physics::WorldPtr _parent, sdf::ElementPtr _sdf)
  {
    node = transport::NodePtr(new transport::Node());
    world = _parent;
    // Initialize the node with the world name
    node->Init(world->Name());
    std::cout << "Subscribing to: " << "~/collision_map/command" << std::endl;
    commandSubscriber = node->Subscribe("~/collision_map/command",
      &CollisionMapCreator::create, this);
    imagePub = node->Advertise<msgs::Image>("~/collision_map/image");
  }

  public: void create(CollisionMapRequestPtr &msg)
  {
    std::cout << "Received message" << std::endl;

    std::cout << "Creating collision map with corners at (" <<
      msg->upperleft().x() << ", " << msg->upperleft().y() << "), (" <<
      msg->upperright().x() << ", " << msg->upperright().y() << "), (" <<
      msg->lowerright().x() << ", " << msg->lowerright().y() << "), (" <<
      msg->lowerleft().x() << ", " << msg->lowerleft().y() <<
        ") with collision projected from z = " <<
      msg->height() << "\nResolution = " << msg->resolution() << " m\n" <<
        "Occupied spaces will be filled with: " << msg->threshold() <<
        std::endl;

    double dX_vertical = msg->upperleft().x() - msg->lowerleft().x();
    double dY_vertical = msg->upperleft().y() - msg->lowerleft().y();
    double mag_vertical =
      sqrt(dX_vertical * dX_vertical + dY_vertical * dY_vertical);
    dX_vertical = msg->resolution() * dX_vertical / mag_vertical;
    dY_vertical = msg->resolution() * dY_vertical / mag_vertical;

    double dX_horizontal = msg->upperright().x() - msg->upperleft().x();
    double dY_horizontal = msg->upperright().y() - msg->upperleft().y();
    double mag_horizontal =
      sqrt(dX_horizontal * dX_horizontal + dY_horizontal * dY_horizontal);
    dX_horizontal = msg->resolution() * dX_horizontal / mag_horizontal;
    dY_horizontal = msg->resolution() * dY_horizontal / mag_horizontal;

    int count_vertical = mag_vertical / msg->resolution();
    int count_horizontal = mag_horizontal / msg->resolution();

    if (count_vertical == 0 || count_horizontal == 0)
    {
      std::cout << "Image has a zero dimensions, check coordinates"
                << std::endl;
      return;
    }
    double x,y;

    boost::gil::gray8_pixel_t fill(255-msg->threshold());
    boost::gil::gray8_pixel_t blank(255);
    boost::gil::gray8_image_t image(count_horizontal, count_vertical);

    double dist;
    std::string entityName;
    ignition::math::Vector3d start, end;
    start.Z(msg->height());
    end.Z(0.001);

    gazebo::physics::PhysicsEnginePtr engine = world->Physics();
    engine->InitForThread();
    gazebo::physics::RayShapePtr ray =
      boost::dynamic_pointer_cast<gazebo::physics::RayShape>(
        engine->CreateShape("ray", gazebo::physics::CollisionPtr()));

    std::cout << "Rasterizing model and checking collisions" << std::endl;
boost::gil::fill_pixels(image._view, blank);

    for (int i = 0; i < count_vertical; ++i)
    {
  std::cout << "Percent complete: " << i * 100.0 / count_vertical
            << std::endl;
  x = i * dX_vertical + msg->lowerleft().x();
  y = i * dY_vertical + msg->lowerleft().y();
      for (int j = 0; j < count_horizontal; ++j)
  {
    x += dX_horizontal;
    y += dY_horizontal;

    start.X(x);
    end.X(x);
    start.Y(y);
    end.Y(y);
    ray->SetPoints(start, end);
    ray->GetIntersection(dist, entityName);
    if (!entityName.empty())
    {
      image._view(i,j) = fill;
    }
  }
}

std::cout << "Completed calculations, writing to image" << std::endl;
if (!msg->filename().empty())
{
  boost::gil::gray8_view_t view = image._view;
  boost::gil::png_write_view(msg->filename(), view);
    }
  }
};

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

Code Explained

ํฌํ•จ ํ•  ํ•„์ˆ˜ ์‹œ์Šคํ…œ ํ—ค๋”

#include <iostream>
#include <math.h>
#include <boost/shared_ptr.hpp>

์ด๊ฒƒ๋“ค์€ ์šฐ๋ฆฌ๊ฐ€ ํ•„์š”๋กœํ•˜๋Š” ํ•„์š”ํ•œ ๊ฐ€์ œ๋ณด (Gazebo) ํ—ค๋”์ž…๋‹ˆ๋‹ค.

#include "gazebo/gazebo.hh"
#include "gazebo/common/common.hh"
#include "gazebo/math/Vector3.hh"
#include "gazebo/msgs/msgs.hh"
#include "gazebo/physics/physics.hh"
#include "gazebo/transport/transport.hh"
#include "collision_map_request.pb.h"

์šฐ๋ฆฌ์˜ collision_map_request ๋ฉ”์‹œ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ƒ์„ฑ ๋œ ํ—ค๋” ํŒŒ์ผ์„ ํฌํ•จ์‹œ์ผœ์•ผํ•ฉ๋‹ˆ๋‹ค.

#include "collision_map_request.pb.h"

์ด๋“ค์€ .png ํŒŒ์ผ์„ ์“ฐ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

#include <boost/gil/gil_all.hpp>
#include <boost/gil/extension/io/png_dynamic_io.hpp>

ํ”Œ๋Ÿฌ๊ทธ์ธ์€ Gazebo ๋„ค์ž„ ์ŠคํŽ˜์ด์Šค์— ์žˆ์Šต๋‹ˆ๋‹ค.

namespace gazebo
{

์ด๊ฒƒ์€ ์ฝœ๋ฐฑ ๋ฉ”์†Œ๋“œ์— ์ „์†ก ๋  ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ์œ„ํ•œ typedef๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

typedef const boost::shared_ptr<const collision_map_creator_msgs::msgs::CollisionMapRequest>             CollisionMapRequestPtr;

Gazebo WorldPlugin์˜ ํŒŒ์ƒ ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ. NodePtr , PublisherPtr , SubcriberPtr ๋ฐ WorldPtr ์„ ์œ ์ง€ํ•ด์•ผํ•˜๋ฏ€๋กœ ํด๋ž˜์Šค ๋ณ€์ˆ˜๋กœ ์ถ”๊ฐ€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

class CollisionMapCreator : public WorldPlugin { transport::NodePtr node; transport::PublisherPtr imagePub; transport::SubscriberPtr commandSubscriber; physics::WorldPtr world;

World Plugin์˜ Load ๋ฉ”์†Œ๋“œ. ๋…ธ๋“œ, ์„ธ๊ณ„, ๊ตฌ๋…์ž ๋ฐ ๊ฒŒ์‹œ์ž๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

public: void Load(physics::WorldPtr _parent, sdf::ElementPtr _sdf)
{
  node = transport::NodePtr(new transport::Node());
  world = _parent;
  // Initialize the node with the world name
  node->Init(world->GetName());
  std::cout << "Subscribing to: " << "~/collision_map/command" << std::endl;

node->Subscribe ์€ ์ฃผ์ œ, ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋ฐ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. node->Advertise , ๋ฉ”์‹œ์ง€ ์œ ํ˜•์˜ ํ…œํ”Œ๋ฆฌํŠธ ์ธ์ˆ˜ ๋ฐ ๊ด‘๊ณ  ํ•  ์ฃผ์ œ ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

    commandSubscriber = node->Subscribe("~/collision_map/command", &CollisionMapCreator::create, this);
    imagePub = node->Advertise<msgs::Image>("~/collision_map/image");

์ด๊ฒƒ์€ ์ฝœ๋ฐฑ ๋ฉ”์†Œ๋“œ์ž…๋‹ˆ๋‹ค. ์ด์ „์— ์‚ฌ์šฉํ•œ typedef๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ์—๋Š” ์ฐธ์กฐ๊ฐ€ ์ „๋‹ฌ๋˜๋ฏ€๋กœ &msg ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

public: void create(CollisionMapRequestPtr &msg)

CollisionMapRequestPtr ์€ shared_ptr์„ ๋†’์ด๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ ํ•„๋“œ๋ฅผ ์–ป์œผ๋ ค๋ฉด ์•„๋ž˜์—์„œ์™€ ๊ฐ™์ด ๊ตฌ์กฐ ์ฐธ์กฐ ( '.') ๋Œ€์‹  ๊ตฌ์กฐ์ฒด ์ฐธ์กฐ ํ•ด์ œ ( '->')๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์ฒด์˜ ํ•„๋“œ๋ฅผ ์–ป์œผ๋ ค๋ฉด get ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค (์˜ˆ : field() ).

    double z = msg->height();

๊ทธ๋Ÿฌ๋‚˜ ์ž ๊น ๋ฌผ์–ด๋ณด์‹ญ์‹œ์˜ค. ์™œ ์ง์ ‘ ํ•˜์œ„ ํ•„๋“œ๋ฅผ ์ฐธ์กฐ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๊ฒƒ์€ shared_ptrs๊ฐ€ ๋‚ด๋ถ€์— ์—†๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋‚ธ ๋ฉ”์‹œ์ง€์ž…๋‹ˆ๋‹ค.

    double dX_vertical = msg->upperleft().x() - msg->lowerleft().x();
    double dY_vertical = msg->upperleft().y() - msg->lowerleft().y();
    double mag_vertical = sqrt(dX_vertical * dX_vertical + dY_vertical * dY_vertical);
    dX_vertical = msg->resolution() * dX_vertical / mag_vertical;
    dY_vertical = msg->resolution() * dY_vertical / mag_vertical;

์ด๊ฒƒ์€ ์‚ฌ์šฉ ๋œ ๋ฌผ๋ฆฌ ์—”์ง„์„ ํ˜ธ์ถœํ•˜์—ฌ ๋‹จ์ผ ๊ด‘์„  ์ถ”์ ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” gazebo::physics::World::GetEntityBelowPoint(Vector3)

    gazebo::physics::PhysicsEnginePtr engine = world->GetPhysicsEngine();
    engine->InitForThread();
    gazebo::physics::RayShapePtr ray = boost::dynamic_pointer_cast<gazebo::physics::RayShape>(
          engine->CreateShape("ray", gazebo::physics::CollisionPtr()));

๊ฐ์ฒด๊ฐ€์žˆ๋Š” ๊ณณ๊ณผ์—†๋Š” ๊ณณ์„ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ๊ฒฉ์ž๋ฅผ ๋ž˜์Šคํ„ฐ ํ™”ํ•ฉ๋‹ˆ๋‹ค.

    for (int i = 0; i < count_vertical; ++i)
    {

... for (int j = 0; j < count_horizontal; ++j) { ... } ... }

์ด๋ ‡๊ฒŒํ•˜๋ฉด ์ด๋ฏธ์ง€ ๋ฉ”์‹œ์ง€๊ฐ€ ๋งŒ๋“ค์–ด์ง€๊ณ  ํ•„์š”ํ•œ ํ•„๋“œ๊ฐ€ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค. ๊ฐ ํ•„๋“œ์— ๋Œ€ํ•œ setter ๋ฉ”์†Œ๋“œ๋Š” set_field(something) ์™€ ๊ฐ™์€ ํ˜•์‹์œผ๋กœ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

    msgs::Image image;
    image.set_width(count_horizontal);
    image.set_height(count_vertical);
    image.set_pixel_format(0);
    image.set_step(count_horizontal);
    image.set_data(data);

    imagePub->Publish(image);

ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์— ๋“ฑ๋กํ•˜์‹ญ์‹œ์˜ค.

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

Request Publisher Executable

์ด ์‹คํ–‰ ํŒŒ์ผ์€ ์ „๋ง๋Œ€ ์™ธ๋ถ€์—์„œ ์‹คํ–‰๋˜์ง€๋งŒ Gazebo์—์„œ ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ ธ ์™€์„œ ์‚ฌ์šฉ์ž ์ •์˜ ๋นŒ๋“œ ๋œ ๋ฉ”์‹œ์ง€ ์œ ํ˜•์œผ๋กœ ์ „๋ง๋Œ€ ํ•ญ๋ชฉ์— ๊ฒŒ์‹œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ์ธ ์ž์Šต์„œ์—์„œ ์„ค๋ช…ํ•˜์ง€ ์•Š์€ ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๋‹จ๊ณ„๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ~/collision_map_creator_plugin/request_publisher.cc ํŒŒ์ผ์„ ์—ด์–ด ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

#include #include <math.h> #include #include <sdf/sdf.hh>

#include "gazebo/gazebo.hh" #include "gazebo/common/common.hh" #include "gazebo/transport/transport.hh" #include "gazebo/physics/physics.hh" #include "gazebo/msgs/msgs.hh"

#include "collision_map_request.pb.h" #include "vector2d.pb.h"

using namespace std;

bool createVectorArray(const char * vectorString, dequegazebo::msgs::Vector2d* corners) { dequegazebo::msgs::Vector2d*::iterator it;

string cornersStr = vectorString;
size_t opening=0;
size_t closing=0;
for (it = corners.begin(); it != corners.end(); ++it)
{
    opening = cornersStr.find('(', closing);
    closing = cornersStr.find(')', opening);
    if (opening == string::npos || closing == string::npos)
    {
        std::cout << "Poorly formed string: " << cornersStr << std::endl;
        std::cout << "( found at: " << opening << " ) found at: " << closing << std::endl;
        return false;
    }
    string oneCornerStr = cornersStr.substr(opening + 1, closing - opening - 1);
    size_t commaLoc = oneCornerStr.find(",");
    string x = oneCornerStr.substr(0,commaLoc);
    string y = oneCornerStr.substr(commaLoc + 1, oneCornerStr.length() - commaLoc);
    (*it)->set_x(atof(x.c_str()));
    (*it)->set_y(atof(y.c_str()));
}
return true;

}

int main(int argc, char * argv[]) { if (argc > 4) { collision_map_creator_msgs::msgs::CollisionMapRequest request; dequegazebo::msgs::Vector2d* corners;

    corners.push_back(request.mutable_upperleft());
    corners.push_back(request.mutable_upperright());
    corners.push_back(request.mutable_lowerright());
    corners.push_back(request.mutable_lowerleft());

    if (!createVectorArray(argv[1],corners))
    {
        return -1;
    }

    request.set_height(atof(argv[2]));
    request.set_resolution(atof(argv[3]));
    request.set_filename(argv[4]);

    if (argc == 6)
    {
        request.set_threshold(atoi(argv[5]));
    }

    gazebo::transport::init();
    gazebo::transport::run();
    gazebo::transport::NodePtr node(new gazebo::transport::Node());
    node->Init("default");

    std::cout << "Request: " <<
                 " UL.x: " << request.upperleft().x() <<
                 " UL.y: " << request.upperleft().y() <<
                 " UR.x: " << request.upperright().x() <<
                 " UR.y: " << request.upperright().y() <<
                 " LR.x: " << request.lowerright().x() <<
                 " LR.y: " << request.lowerright().y() <<
                 " LL.x: " << request.lowerleft().x() <<
                 " LL.y: " << request.lowerleft().y() <<
                 " Height: " << request.height() <<
                 " Resolution: " << request.resolution() <<
                 " Filename: " << request.filename() <<
                 " Threshold: " << request.threshold() << std::endl;

    gazebo::transport::PublisherPtr imagePub =
            node->Advertise<collision_map_creator_msgs::msgs::CollisionMapRequest>(
                                                        "~/collision_map/command");
    imagePub->WaitForConnection();
    imagePub->Publish(request);

    gazebo::transport::fini();
    return 0;
}
return -1;

}

Code Explained

ํ•„์š”ํ•œ ํ‘œ์ค€ c ++ ํ—ค๋” ํฌํ•จ

#include #include <math.h> #include <boost/shared_ptr.hpp> #include <sdf/sdf.hh> #include <boost/gil/gil_all.hpp> #include <boost/gil/extension/io/png_dynamic_io.hpp> ์ด๊ฒƒ๋“ค์€ ์šฐ๋ฆฌ ์‹คํ–‰ ํŒŒ์ผ์— ํ•„์š”ํ•œ ์ „๋ง๋Œ€ ํ—ค๋”์ž…๋‹ˆ๋‹ค. #include "gazebo/gazebo.hh" #include "gazebo/common/common.hh" #include "gazebo/math/Vector3.hh" #include "gazebo/transport/transport.hh" #include "gazebo/physics/physics.hh" #include "gazebo/msgs/msgs.hh" #include "collision_map_request.pb.h" ์ด๊ฒƒ์€ ์‚ฌ์šฉ์ž ์ •์˜ ๋ฉ”์‹œ์ง€ ์œ ํ˜•๊ณผ ์—ฐ๊ด€๋œ ํ—ค๋”์ž…๋‹ˆ๋‹ค. #include "collision_map_request.pb.h"

์ด ํ•จ์ˆ˜๋Š” "(x1, y1) (x2, y2) (x3, y3) (x4, y4)"์— ์˜ํ•ด ์ •์˜ ๋œ ์ขŒํ‘œ ๋ฌธ์ž์—ด์„ Vector2d ๋ฉ”์‹œ์ง€์˜ ์–‘ํ‚ค๋กœ ํŒŒ์‹ฑํ•ฉ๋‹ˆ๋‹ค.

bool createVectorArray(const char * vectorString, dequegazebo::msgs::Vector2d* corners) deque ๋ฐ˜๋ณต์ž๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. dequegazebo::msgs::Vector2d*::iterator it;

Iterate through the corners deque

... for (it = corners.begin(); it != corners.end(); ++it) { ... } ์ฝ”๋„ˆ ์ธ Vector2d์— ๋Œ€ํ•ด ์šฐ๋ฆฌ๋Š” x์™€ y์— ๋Œ€ํ•ด ๋ฐœ๊ฒฌ ๋œ ๋ฌธ์ž์—ด์„ float๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ X์™€ Y๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค (*it)->set_x(atof(x.c_str())); (*it)->set_y(atof(y.c_str()));

The main function, which is called when the executable is run.

int main(int argc, char * argv[]) { ... } ์ด ์‹คํ–‰ ํŒŒ์ผ์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ธ์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ์ ์–ด๋„ 4 ๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ์—๋งŒ ์ง„ํ–‰ํ•˜์‹ญ์‹œ์˜ค. if (argc > 4) { ... } CollisionMapRequest ๋ฉ”์‹œ์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ธฐ ์ „์— ์ž‘์„ฑํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ Vector2d ๋ฉ”์‹œ์ง€์˜ deque๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ createVectorArray ํ•จ์ˆ˜์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. collision_map_creator_msgs::msgs::CollisionMapRequest request; dequegazebo::msgs::Vector2d* corners; ๋ฉ”์‹œ์ง€ ํ•„๋“œ๊ฐ€ ๋‹จ์ˆœํ•œ ๊ฒฝ์šฐ (double, int32, string) ์—ฐ๊ด€๋œ set_field() ๋ฉ”์†Œ๋“œ๋กœ ์ง์ ‘ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•„๋“œ๊ฐ€ ๋ฉ”์‹œ์ง€ ์œ ํ˜• ์ž์ฒด ์ธ ๊ฒฝ์šฐ, ํ•ด๋‹น mutable_field() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์•ก์„ธ์Šคํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. Vector2d๋Š” ๊ทธ ์ž์ฒด๋กœ ๋ณ„๋„์˜ ๋ฉ”์‹œ์ง€์ด๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๊ฐ€ ์—ฌ๊ธฐ์—์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๊ฐ€๋ณ€ ํ•จ์ˆ˜ ํ˜ธ์ถœ๋กœ๋ถ€ํ„ฐ ๋จผ์ € ํฌ์ธํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•ฉ๋‹ˆ๋‹ค.

    corners.push_back(request.mutable_upperleft());
    corners.push_back(request.mutable_upperright());
    corners.push_back(request.mutable_lowerright());
    corners.push_back(request.mutable_lowerleft());

Vector2d ํฌ์ธํ„ฐ์˜ deque์™€ ์ฒซ ๋ฒˆ์งธ argv ๋ฌธ์ž์—ด์„ createVectorArray ํ•ฉ๋‹ˆ๋‹ค. ์‹คํŒจ ํ•  ๊ฒฝ์šฐ ์ž…๋ ฅ ํ˜•์‹์ด ์ž˜๋ชป ์ง€์ •๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•˜์‹ญ์‹œ์˜ค. if (!createVectorArray(argv[1],corners)) { return -1; } ๊ฐ„๋‹จํ•œ ํ•„๋“œ์˜ ๊ฒฝ์šฐ set_field ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฐ’์„ ์ง์ ‘ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    request.set_height(atof(argv[2]));
    request.set_resolution(atof(argv[3]));
    request.set_filename(argv[4]);

์„ ํƒ์  ์ž„๊ณ„ ๊ฐ’ ํ•„๋“œ์˜ ๊ฒฝ์šฐ ๋ช…๋ น ์ธ์ˆ˜์— ์ง€์ •๋œ ๊ฒฝ์šฐ์ด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. if (argc == 6) { request.set_threshold(atoi(argv[6])); }

์ด๊ฒƒ์€ ์ฃผ์š” ๋ฐฉ๋ฒ•์˜ ๋งค์šฐ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ gazebo ์ „์†ก ์‹œ์Šคํ…œ์„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์œ„ํ•ด, Gazebo๋Š” ์ด๋ฏธ ์ด๊ฒƒ์„ ์ฒ˜๋ฆฌํ•˜์ง€๋งŒ, ์šฐ๋ฆฌ ์ž์‹ ์˜ ์‹คํ–‰ ํŒŒ์ผ์„ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” ์Šค์Šค๋กœ ํ•ด๊ฒฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์šฐ๋ฆฌ๊ฐ€ ์ •์ž ์—ฌ์•ผ ๋„ค์ž„ ์ŠคํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ช…์‹œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

    gazebo::transport::init();
    gazebo::transport::run();
    gazebo::transport::NodePtr node(new gazebo::transport::Node());
    node->Init("default");

~/collision_map/command ํ•ญ๋ชฉ์—์„œ ์š”์ฒญ ๊ฒŒ์‹œ์ž๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

    gazebo::transport::PublisherPtr imagePub =
            node->Advertise<collision_map_creator_msgs::msgs::CollisionMapRequest>(
                                                        "~/collision_map/command");

๋ฉ”์‹œ์ง€๋ฅผ ๊ฒŒ์‹œํ•˜๋ ค๋ฉด ๋จผ์ € ๊ฒŒ์‹œ์ž๊ฐ€ ๋งˆ์Šคํ„ฐ์— ์—ฐ๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์šฐ๋ฆฌ๋Š” ์ง์ ‘ ๋ฉ”์‹œ์ง€๋ฅผ ๊ฒŒ์‹œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    imagePub->WaitForConnection();
    imagePub->Publish(request);

์ข…๋ฃŒํ•˜๊ธฐ ์ „์—, ํ”„๋กœ๊ทธ๋žจ์€ transport::fini() ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์„ ๋–ผ์–ด ๋‚ด์•ผํ•œ๋‹ค. gazebo::transport::fini();

CMakeLists for Plugin and Executable

์•„๋ž˜์—์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ์‹คํ–‰ ํŒŒ์ผ์„ ์ปดํŒŒ์ผํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ CMakeLists.txt ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2.8.8 required to use PROTOBUF_IMPORT_DIRS

cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR) FIND_PACKAGE( Boost 1.40 COMPONENTS system REQUIRED ) set (CMAKE_CXX_FLAGS "-g -Wall -std=c++11")

include (FindPkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(GAZEBO gazebo) pkg_check_modules(SDF sdformat) endif() include_directories( ${GAZEBO_INCLUDE_DIRS} ${SDF_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}/msgs ) link_directories(${GAZEBO_LIBRARY_DIRS} ${CMAKE_CURRENT_BINARY_DIR}/msgs) add_subdirectory(msgs)

add_executable (request_publisher request_publisher.cc) target_link_libraries(request_publisher collision_map_creator_msgs ${GAZEBO_LIBRARIES} ${Boost_LIBRARIES} ${SDF_LIBRARIES}) add_dependencies(request_publisher collision_map_creator_msgs)

add_library(collision_map_creator SHARED collision_map_creator.cc ) target_link_libraries(collision_map_creator collision_map_creator_msgs ${Boost_LIBRARIES} ${GAZEBO_LIBRARIES} ${SDF_LIBRARIES}) add_dependencies(collision_map_creator collision_map_creator_msgs)

Code Explained

Boost๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ด๋ฏธ์ง€ ์ž‘์„ฑ์ž์—๊ฒŒ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

FIND_PACKAGE( Boost 1.40 COMPONENTS system REQUIRED )

msgs ๋””๋ ‰ํ† ๋ฆฌ๋Š” ์‹คํ–‰ ํŒŒ์ผ๊ณผ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ชจ๋‘์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— include ๋””๋ ‰ํ† ๋ฆฌ์— ์ถ”๊ฐ€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

include_directories( ${GAZEBO_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}/msgs )

GAZEBO_LIBRARY_DIRS ํ‘œ์ค€ ์™ธ์—๋„ msgs ๋””๋ ‰ํ† ๋ฆฌ์— ๋งํฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. add_subdirectory ์ง€์‹œ์–ด๋Š” CMake์—๊ฒŒ CMakeLists.txt ํŒŒ์ผ์„ ์ฐพ๋„๋ก ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค. link_directories(${GAZEBO_LIBRARY_DIRS} ${SDF_LIBRARY_DIRS} ${CMAKE_CURRENT_BINARY_DIR}/msgs) add_subdirectory(msgs) ์‹คํ–‰ ํŒŒ์ผ request_publisher ๋ฅผ makefile์— ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค. collision_map_creator_msgs , GAZEBO_LIBRARIES ๋ฐ Boost_LIBRARIES ์™€ ์—ฐ๊ฒฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. add_dependencies ์ง€์‹œ์–ด๋Š” CMake์—๊ฒŒ ๋จผ์ € collision_map_creator_msgs ๋ฅผ ๋นŒ๋“œ add_dependencies ์ง€์‹œํ•œ๋‹ค.

add_executable (request_publisher request_publisher.cc) target_link_libraries(request_publisher collision_map_creator_msgs ${GAZEBO_LIBRARIES} ${Boost_LIBRARIES} ${SDF_LIBRARIES}) add_dependencies(request_publisher collision_map_creator_msgs)

์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์šฐ๋ฆฌ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค๊ณ , ํ‘œ์ค€ WorldPlugin CMakeLists.txt์™€ ๋งค์šฐ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค. ๋‹จ, collision_map_creator_msgs ์™€ ์—ฐ๊ฒฐํ•˜๊ณ ์ด๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. add_library(collision_map_creator SHARED collision_map_creator.cc ) target_link_libraries(collision_map_creator collision_map_creator_msgs ${Boost_LIBRARIES} ${GAZEBO_LIBRARIES} ${SDF_LIBRARIES}) add_dependencies(collision_map_creator collision_map_creator_msgs)

Build and Deploy

๋จผ์ €, protobuf-compiler๋ผ๋Š” ์ข…์† ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. sudo apt-get install protobuf-compiler

์ด ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œํ•˜๋ ค๋ฉด ๋นŒ๋“œ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  CMake๋ฅผ ์‹คํ–‰ ํ•œ ๋‹ค์Œ make๋ฅผ ์‹คํ–‰ํ•˜์‹ญ์‹œ์˜ค.

cd ~/collision_map_creator_plugin mkdir build cd build cmake ../ make ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ gazebo ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฒฝ๋กœ์— ์ถ”๊ฐ€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ์ด ๋นŒ๋“œ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ฐธ์กฐํ•˜๊ฑฐ๋‚˜,

export GAZEBO_PLUGIN_PATH=$GAZEBO_PLUGIN_PATH:collision_map_creator_plugin/build

๋˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋””๋ ‰ํ† ๋ฆฌ์— ๋ณต์‚ฌ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

sudo cp libcollision_map_creator.so /usr/lib/gazebo-<YOUR-GAZEBO_VERSION>/plugins/

Running

๋ชจ๋“  ๊ฒƒ์ด ์ž˜๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด, ์•„๋งˆ ๋Œ€๋žต ๊ฑฐ์นœ ๊ฐ€์ • ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์ง„์ง€ํ•˜๊ฒŒ๋Š” ์ด๊ฒƒ์€ ๊ธธ์—ˆ์Šต๋‹ˆ๋‹ค), ์‚ฌ์šฉ์ž ์ •์˜ wold ํŒŒ์ผ๋กœ Gazebo๋ฅผ ์‹คํ–‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

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

   <include>
     <uri>model://willowgarage</uri>
   </include>

   <plugin filename="libcollision_map_creator.so" name="collision_map_creator"/>
 </world>

Run Gazebo with this world:

gazebo ~/collision_map_creator_plugin/map_creator.world

~/collision_map_creator_plugin/build/request_publisher "(-10,10)(10,10)(10,-10)(-10,-10)" 10 0.01 ~/map.png

์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํ„ฐ๋ฏธ๋„์ด Gazebo์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์š”์ฒญ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ „๋ง๋Œ€ ํ„ฐ๋ฏธ๋„์— ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋˜๊ณ  ์™„๋ฃŒ ๋  ๋•Œ๊นŒ์ง€ ํผ์„ผํŠธ ์™„๋ฃŒ ํ†ต๊ณ„๊ฐ€ ํ‘œ์‹œ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. map.png๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

ยฉ 2014 ์˜คํ”ˆ ์†Œ์Šค ๋กœ๋ด‡ ๊ณตํ•™ ์žฌ๋‹จ

Gazebo๋Š” Apache 2.0์—์„œ ๋ผ์ด์„ผ์Šค๊ฐ€ ๊ณต๊ฐœ ๋œ ์˜คํ”ˆ ์†Œ์Šค์ž…๋‹ˆ๋‹ค. Google+ YouTube YouTube ~/collision_map_creator_plugin/build/request_publisher "(-10,10)(10,10)(10,-10)(-10,-10)" 10 0.01 ~/map.png

์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํ„ฐ๋ฏธ๋„์ด Gazebo์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์š”์ฒญ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. gazebo ํ„ฐ๋ฏธ๋„์— ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋˜๊ณ  ์™„๋ฃŒ ๋  ๋•Œ๊นŒ์ง€ ํผ์„ผํŠธ ์™„๋ฃŒ ํ†ต๊ณ„๊ฐ€ ํ‘œ์‹œ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

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