Home | Tutorials | Wiki | Issues
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Thanks for the answer. I already added a simple way of drawing to the Scene class. It is probably not the best way, but it works for me and allows me to continue my work.

Here is the code I used for that.

gazebo/rendering/Scene.hh

/// \brief Subscribe to draw for line drawing
private: transport::SubscriberPtr drawingSub;

/// \brief Drawing callback
/// \param[in] _msg The message data.
private: void OnDrawing(ConstDrawingPtr &_msg);

/// \brief Process a drawing message
/// \param[in] _msg The message data.
private: bool ProcessDrawingMsg(ConstDrawingPtr &_msg);

/// \def DrawingMsgs_L
/// \brief List of drawing messages.
typedef std::list<boost::shared_ptr<msgs::Drawing const> > DrawingMsgs_L;

/// \brief List of drawing message to process.
private: DrawingMsgs_L drawingMsgs;

gazebo/rendering/Scene.cc

/////////////////////////////////////////////////
void Scene::OnDrawing(ConstDrawingPtr &_msg)
{
  boost::mutex::scoped_lock lock(*this->receiveMutex);
  this->drawingMsgs.push_back(_msg);
}

/////////////////////////////////////////////////
bool Scene::ProcessDrawingMsg(ConstDrawingPtr &_msg)
{
  Ogre::SceneNode *sceneNode = NULL;
  Ogre::ManualObject *obj = NULL;
  bool attached = false;

  if (this->manager->hasManualObject(_msg->name()))
  {
    sceneNode = this->manager->getSceneNode(_msg->name());
    obj = this->manager->getManualObject(_msg->name());
    attached = true;
  }
  else
  {
    sceneNode = this->manager->getRootSceneNode()->createChildSceneNode(_msg->name());
    obj = this->manager->createManualObject(_msg->name());
  }

  sceneNode->setVisible(true);
  obj->setVisible(true);

  obj->clear();
  std::string material;
  if(_msg->has_material()) {
    material = _msg->material();
  }
  else {
    material = "Gazebo/FlatBlack";
  }

  if(!_msg->has_mode())
    obj->begin(material, Ogre::RenderOperation::OT_LINE_LIST);
  else if(_msg->mode() == msgs::Drawing::POINT_LIST)
    obj->begin(material, Ogre::RenderOperation::OT_POINT_LIST);
  else if(_msg->mode() == msgs::Drawing::LINE_LIST)
    obj->begin(material, Ogre::RenderOperation::OT_LINE_LIST);
  else if(_msg->mode() == msgs::Drawing::LINE_STRIP)
    obj->begin(material, Ogre::RenderOperation::OT_LINE_STRIP);
  else if(_msg->mode() == msgs::Drawing::TRIANGLE_LIST)
    obj->begin(material, Ogre::RenderOperation::OT_TRIANGLE_LIST);
  else if(_msg->mode() == msgs::Drawing::TRIANGLE_STRIP)
    obj->begin(material, Ogre::RenderOperation::OT_TRIANGLE_STRIP);
  else if(_msg->mode() == msgs::Drawing::TRIANGLE_FAN)
    obj->begin(material, Ogre::RenderOperation::OT_TRIANGLE_FAN);

  int p = _msg->point_size();
  for(int i=0; i<p; i++) {
    obj->position(_msg->point(i).position().x(), _msg->point(i).position().y(), _msg->point(i).position().z());
    if(_msg->point(i).has_color())
      obj->colour(Conversions::Convert(msgs::Convert(_msg->point(i).color())));
  }
  obj->end();

  if (!attached)
    sceneNode->attachObject(obj);

  return true;
}

gazebo/rendering/Scene.cc

// inside Scene::PreRender()
  static DrawingMsgs_L::iterator drawingIter;
  // Process the drawing messages
  drawingIter = this->drawingMsgs.begin();
  while (drawingIter != this->drawingMsgs.end())
  {
    if (this->ProcessDrawingMsg(*drawingIter))
      this->drawingMsgs.erase(drawingIter++);
    else
      ++drawingIter;
  }

// Inside the Constructor
  this->drawingSub = this->node->Subscribe("~/draw", &Scene::OnDrawing, this);

gazebo/msgs/drawing.proto

package gazebo.msgs;

/// \ingroup gazebo_msgs
/// \interface Drawing 
/// \brief Message that is used to draw inside gazebo
/// \verbatim

import "vector3d.proto";
import "color.proto";

message Drawing
{
  enum Mode
  {
    POINT_LIST     = 1;
    LINE_LIST      = 2;
    LINE_STRIP     = 3;
    TRIANGLE_LIST  = 4;
    TRIANGLE_STRIP = 5;
    TRIANGLE_FAN   = 6;
  }

  message Point
  {
    required Vector3d position  = 1;
    optional Color color        = 2;
  }

  required string name          = 1;
  optional string material      = 2;
  optional Mode mode            = 3;
  repeated Point point          = 4;
}

/// \endverbatim

It is probably not the best way to solve my problem, but it works for me.

Bastian

click to hide/show revision 2
updated code, linked files

Thanks for the answer. I already added a simple way of drawing to the Scene class. It is probably not the best way, but it works for me and allows me to continue my work.

Here is the code I used for that.

Added needed stuff to the Scene header

gazebo/rendering/Scene.hh

/// \brief Subscribe to draw for line drawing
private: transport::SubscriberPtr drawingSub;

/// \brief Drawing callback
/// \param[in] _msg The message data.
private: void OnDrawing(ConstDrawingPtr &_msg);

/// \brief Process a drawing message
/// \param[in] _msg The message data.
private: bool ProcessDrawingMsg(ConstDrawingPtr &_msg);

/// \def DrawingMsgs_L
/// \brief List of drawing messages.
typedef std::list<boost::shared_ptr<msgs::Drawing const> > DrawingMsgs_L;

/// \brief List of drawing message to process.
private: DrawingMsgs_L drawingMsgs;

New functions for the drawing

gazebo/rendering/Scene.cc

/////////////////////////////////////////////////
void Scene::OnDrawing(ConstDrawingPtr &_msg)
{
  boost::mutex::scoped_lock lock(*this->receiveMutex);
  this->drawingMsgs.push_back(_msg);
}

/////////////////////////////////////////////////
bool Scene::ProcessDrawingMsg(ConstDrawingPtr &_msg)
{
  Ogre::SceneNode *sceneNode = NULL;
  Ogre::ManualObject *obj = NULL;
  bool attached = false;

  if (this->manager->hasManualObject(_msg->name()))
  {
    sceneNode = this->manager->getSceneNode(_msg->name());
    obj = this->manager->getManualObject(_msg->name());
    attached = true;
  }
  else
  {
    sceneNode = this->manager->getRootSceneNode()->createChildSceneNode(_msg->name());
    obj = this->manager->createManualObject(_msg->name());
  }

  sceneNode->setVisible(true);
  obj->setVisible(true);
sceneNode->setVisible(_msg->visible());
  obj->setVisible(_msg->has_visible());
  obj->estimateVertexCount(_msg->point_size());

  obj->clear();
  std::string material;
material = "Gazebo/Red";
  if(_msg->has_material()) {
    material = _msg->material();
  }
  else {
    material = "Gazebo/FlatBlack";
  }

  if(!_msg->has_mode())
    obj->begin(material, Ogre::RenderOperation::OT_LINE_LIST);
  else if(_msg->mode() == msgs::Drawing::POINT_LIST)
    obj->begin(material, Ogre::RenderOperation::OT_POINT_LIST);
  else if(_msg->mode() == msgs::Drawing::LINE_LIST)
    obj->begin(material, Ogre::RenderOperation::OT_LINE_LIST);
  else if(_msg->mode() == msgs::Drawing::LINE_STRIP)
    obj->begin(material, Ogre::RenderOperation::OT_LINE_STRIP);
  else if(_msg->mode() == msgs::Drawing::TRIANGLE_LIST)
    obj->begin(material, Ogre::RenderOperation::OT_TRIANGLE_LIST);
  else if(_msg->mode() == msgs::Drawing::TRIANGLE_STRIP)
    obj->begin(material, Ogre::RenderOperation::OT_TRIANGLE_STRIP);
  else if(_msg->mode() == msgs::Drawing::TRIANGLE_FAN)
    obj->begin(material, Ogre::RenderOperation::OT_TRIANGLE_FAN);

  int p = _msg->point_size();
  for(int i=0; i<p; i++) {
    obj->position(_msg->point(i).position().x(), _msg->point(i).position().y(), _msg->point(i).position().z());
    if(_msg->point(i).has_color())
      obj->colour(Conversions::Convert(msgs::Convert(_msg->point(i).color())));
  }
  obj->end();

  if (!attached)
    sceneNode->attachObject(obj);

  if(_msg->has_pose()) {
    sceneNode->setPosition(Conversions::Convert(msgs::Convert(_msg->pose().position())));
    sceneNode->setOrientation(Conversions::Convert(msgs::Convert(_msg->pose().orientation())));
  }

  return true;
}

Changes adding the new function to be processed during prerender

gazebo/rendering/Scene.cc

void Scene::PreRender()
{
  // inside Scene::PreRender()
...
  static SensorMsgs_L::iterator sensorIter;
  static LinkMsgs_L::iterator linkIter;
  static DrawingMsgs_L::iterator drawingIter;

  // ...
  // Process the link messages
  linkIter = this->linkMsgs.begin();
  while (linkIter != this->linkMsgs.end())
  {
    if (this->ProcessLinkMsg(*linkIter))
      this->linkMsgs.erase(linkIter++);
    else
      ++linkIter;
  }

  // Process the drawing messages
  drawingIter = this->drawingMsgs.begin();
  while (drawingIter != this->drawingMsgs.end())
  {
    if (this->ProcessDrawingMsg(*drawingIter))
      this->drawingMsgs.erase(drawingIter++);
    else
      ++drawingIter;
  }
  // Inside the Constructor
...
}

Registering the new subscriber

gazebo/rendering/Scene.cc

Scene::Scene(const std::string &_name, bool _enableVisualizations)
{
  // ...
  this->sceneSub = this->node->Subscribe("~/scene", &Scene::OnScene, this);

  this->drawingSub = this->node->Subscribe("~/draw", &Scene::OnDrawing, this);
  // ...
}

Message definition

gazebo/msgs/drawing.proto

package gazebo.msgs;

/// \ingroup gazebo_msgs
/// \interface Drawing 
/// \brief Message that is used to draw inside gazebo
/// \verbatim

import "vector3d.proto";
import "pose.proto";
import "color.proto";

message Drawing
{
  enum Mode
  {
    POINT_LIST     = 1;
    LINE_LIST      = 2;
    LINE_STRIP     = 3;
    TRIANGLE_LIST  = 4;
    TRIANGLE_STRIP = 5;
    TRIANGLE_FAN   = 6;
  }

  message Point
  {
    required Vector3d position  = 1;
    optional Color color        = 2;
  }

   required string name          = 1;
  required bool visible         = 2;
  optional Pose pose            = 3;
  optional string material      = 2;
4;
  optional Mode mode            = 3;
5;
  repeated Point point          = 4;
6;
}

/// \endverbatim

It is probably not the best way to solve my problem, but it works for me.

Bastian

Here are the files/patches, hope everything works, since I am not familiar with diff

Drawing.proto

Patch for CMakeLists.txt

Patch for Scene.cc

Patch for Scene.hh