polygon_array_display.cpp
Go to the documentation of this file.
1 // -*- mode: c++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2015, JSK Lab
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of the JSK Lab nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
36 #define BOOST_PARAMETER_MAX_ARITY 7
37 
38 #include "polygon_array_display.h"
40 #include <rviz/validate_floats.h>
43 
44 namespace jsk_rviz_plugins
45 {
47  {
49  "coloring", "Auto",
50  "coloring method",
51  this, SLOT(updateColoring()));
52  coloring_property_->addOption("Auto", 0);
53  coloring_property_->addOption("Flat color", 1);
54  coloring_property_->addOption("Liekelihood", 2);
55  coloring_property_->addOption("Label", 3);
57  "Color", QColor(25, 255, 0),
58  "Color to draw the polygons.",
59  this, SLOT(queueRender()));
61  "Alpha", 1.0,
62  "Amount of transparency to apply to the polygon.",
63  this, SLOT(queueRender()));
65  "only border", true,
66  "only shows the borders of polygons",
67  this, SLOT(updateOnlyBorder()));
69  "show normal", true,
70  "show normal direction",
71  this, SLOT(updateShowNormal()));
73  "enable lighting", true,
74  "enable lighting",
75  this, SLOT(updateEnableLighting()));
77  "normal length", 0.1,
78  "normal length",
79  this, SLOT(updateNormalLength()));
81  //only_border_ = true;
84  }
85 
87  {
88  delete alpha_property_;
89  delete color_property_;
90  delete only_border_property_;
91  delete coloring_property_;
92  delete show_normal_property_;
94  for (size_t i = 0; i < lines_.size(); i++) {
95  delete lines_[i];
96  }
97 
98  for (size_t i = 0; i < materials_.size(); i++) {
99  materials_[i]->unload();
100  Ogre::MaterialManager::getSingleton().remove(materials_[i]->getName());
101  }
102 
103  for (size_t i = 0; i < manual_objects_.size(); i++) {
104  scene_manager_->destroyManualObject(manual_objects_[i]);
105  scene_manager_->destroySceneNode(scene_nodes_[i]);
106  }
107  }
108 
110  {
113  updateColoring();
116  }
117 
119  {
120  if (only_border_) {
121  return;
122  }
123  static uint32_t count = 0;
124 
125  if (num > materials_.size()) {
126  for (size_t i = materials_.size(); num > i; i++) {
127  std::stringstream ss;
128  ss << "PolygonArrayMaterial" << count++;
129  Ogre::MaterialPtr material
130  = Ogre::MaterialManager::getSingleton().create(
131  ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
132  material->setReceiveShadows(false);
133  material->getTechnique(0)->setLightingEnabled(enable_lighting_);
134  material->getTechnique(0)->setAmbient(0.5, 0.5, 0.5);
135 
136  //material->setCullingMode(Ogre::CULL_NONE);
137  materials_.push_back(material);
138  }
139  }
140  }
141 
142  bool validateFloats(const jsk_recognition_msgs::PolygonArray& msg)
143  {
144  for (size_t i = 0; i < msg.polygons.size(); i++) {
145  if (!rviz::validateFloats(msg.polygons[i].polygon.points))
146  return false;
147  }
148  return true;
149  }
150 
152  {
153  MFDClass::reset();
154  for (size_t i = 0; i < manual_objects_.size(); i++) {
155  manual_objects_[i]->clear();
156  }
157  }
158 
160  const jsk_recognition_msgs::PolygonArray::ConstPtr& msg)
161  {
162  int scale_factor = 2;
163  if (only_border_) {
164  scale_factor = 1;
165  }
166  if (msg->polygons.size() * scale_factor > manual_objects_.size()) {
167  for (size_t i = manual_objects_.size();
168  i < msg->polygons.size() * scale_factor;
169  i++) {
170  Ogre::SceneNode* scene_node
171  = scene_node_->createChildSceneNode();
172  Ogre::ManualObject* manual_object
173  = scene_manager_->createManualObject();
174  manual_object->setDynamic(true);
175  scene_node->attachObject(manual_object);
176  manual_objects_.push_back(manual_object);
177  scene_nodes_.push_back(scene_node);
178  }
179  }
180  else if (msg->polygons.size() * scale_factor < manual_objects_.size()) {
181  for (size_t i = msg->polygons.size() * scale_factor;
182  i < manual_objects_.size(); i++) {
183  manual_objects_[i]->setVisible(false);
184  }
185  }
186  // arrow nodes
187  if (msg->polygons.size() > arrow_objects_.size()) {
188  for (size_t i = arrow_objects_.size(); i < msg->polygons.size(); i++) {
189  Ogre::SceneNode* scene_node = scene_node_->createChildSceneNode();
190  ArrowPtr arrow (new rviz::Arrow(scene_manager_, scene_node));
191  scene_node->setVisible(false);
192  arrow_objects_.push_back(arrow);
193  arrow_nodes_.push_back(scene_node);
194  }
195  }
196  else if (msg->polygons.size() < manual_objects_.size()) {
197  for (size_t i = msg->polygons.size(); i < arrow_nodes_.size(); i++) {
198  //arrow_objects_[i]->setVisible(false);
199  arrow_nodes_[i]->setVisible(false);
200  }
201  }
202  }
203 
205  {
206  if (num > lines_.size()) {
207  for (size_t i = lines_.size(); i < num; i++) {
208  rviz::BillboardLine* line
210  scene_nodes_[i]);
211  line->setLineWidth(0.01);
212  line->setNumLines(1);
213  lines_.push_back(line);
214  }
215  }
216  for (size_t i = 0; i < lines_.size(); i++) {
217  lines_[i]->clear();
218  }
219  }
220 
221  Ogre::ColourValue PolygonArrayDisplay::getColor(size_t index)
222  {
223  Ogre::ColourValue color;
224  if (coloring_method_ == "auto") {
225  std_msgs::ColorRGBA ros_color = jsk_topic_tools::colorCategory20(index);
226  color.r = ros_color.r;
227  color.g = ros_color.g;
228  color.b = ros_color.b;
229  color.a = ros_color.a;
230  }
231  else if (coloring_method_ == "flat") {
233  }
234  else if (coloring_method_ == "likelihood") {
235  if (latest_msg_->likelihood.size() == 0 ||
236  latest_msg_->likelihood.size() < index) {
238  "Topic",
239  "Message does not have lieklihood fields");
240  }
241  else {
242  std_msgs::ColorRGBA ros_color
243  = jsk_topic_tools::heatColor(latest_msg_->likelihood[index]);
244  color.r = ros_color.r;
245  color.g = ros_color.g;
246  color.b = ros_color.b;
247  color.a = ros_color.a;
248  }
249  }
250  else if (coloring_method_ == "label") {
251  if (latest_msg_->labels.size() == 0 ||
252  latest_msg_->labels.size() < index) {
254  "Topic",
255  "Message does not have lebels fields");
256  }
257  else {
258  std_msgs::ColorRGBA ros_color
260  color.r = ros_color.r;
261  color.g = ros_color.g;
262  color.b = ros_color.b;
263  color.a = ros_color.a;
264  }
265  }
266  color.a = alpha_property_->getFloat();
267  return color;
268  }
269 
271  const size_t i,
272  const geometry_msgs::PolygonStamped& polygon)
273  {
274  Ogre::SceneNode* scene_node = scene_nodes_[i];
275  //Ogre::ManualObject* manual_object = manual_objects_[i];
276  Ogre::Vector3 position;
277  Ogre::Quaternion orientation;
278  if (!getTransform(polygon.header, position, orientation))
279  return;
280  scene_node->setPosition(position);
281  scene_node->setOrientation(orientation);
282  rviz::BillboardLine* line = lines_[i];
283  line->clear();
284  line->setMaxPointsPerLine(polygon.polygon.points.size() + 1);
285 
286  Ogre::ColourValue color = getColor(i);
287  line->setColor(color.r, color.g, color.b, color.a);
288 
289  for (size_t i = 0; i < polygon.polygon.points.size(); ++i) {
290  Ogre::Vector3 step_position;
291  step_position.x = polygon.polygon.points[i].x;
292  step_position.y = polygon.polygon.points[i].y;
293  step_position.z = polygon.polygon.points[i].z;
294  line->addPoint(step_position);
295  }
296  Ogre::Vector3 step_position;
297  step_position.x = polygon.polygon.points[0].x;
298  step_position.y = polygon.polygon.points[0].y;
299  step_position.z = polygon.polygon.points[0].z;
300  line->addPoint(step_position);
301  }
302 
304  {
305  Ogre::ColourValue color = getColor(i);
306  materials_[i]->getTechnique(0)->setLightingEnabled(enable_lighting_);
307  materials_[i]->getTechnique(0)->setAmbient(color * 0.5);
308  materials_[i]->getTechnique(0)->setDiffuse(color);
309  if (color.a < 0.9998) {
310  materials_[i]->getTechnique(0)->setSceneBlending(
311  Ogre::SBT_TRANSPARENT_ALPHA);
312  materials_[i]->getTechnique(0)->setDepthWriteEnabled(false);
313  }
314  else {
315  materials_[i]->getTechnique(0)->setSceneBlending(Ogre::SBT_REPLACE);
316  materials_[i]->getTechnique(0)->setDepthWriteEnabled(true);
317  }
318 
319  materials_[i]->getTechnique(0)->setAmbient(color * 0.5);
320  materials_[i]->getTechnique(0)->setDiffuse(color);
321  }
322 
324  const size_t i, const geometry_msgs::PolygonStamped& polygon)
325  {
326  Ogre::Vector3 position;
327  Ogre::Quaternion orientation;
328  if (!getTransform(polygon.header, position, orientation))
329  return;
330 
331  {
332  Ogre::SceneNode* scene_node = scene_nodes_[i * 2];
333  Ogre::ManualObject* manual_object = manual_objects_[i * 2];
334  Ogre::ColourValue color = getColor(i);
335  scene_node->setPosition(position);
336  scene_node->setOrientation(orientation);
337  manual_object->clear();
338  manual_object->setVisible(true);
339 
342  std::vector<jsk_recognition_utils::Polygon::Ptr>
343  triangles = geo_polygon.decomposeToTriangles();
344 
345  uint32_t num_points = 0;
346  for (size_t j = 0; j < triangles.size(); j++) {
347  num_points += triangles[j]->getNumVertices();
348  }
349  if(num_points > 0) {
350  manual_object->estimateVertexCount(num_points * 2);
351  manual_object->begin(
352  materials_[i]->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST);
353  for (size_t ii = 0; ii < triangles.size(); ii++) {
354  jsk_recognition_utils::Polygon::Ptr triangle = triangles[ii];
355  size_t num_vertices = triangle->getNumVertices();
356  for (size_t j = 0; j < num_vertices; j++) {
357  Eigen::Vector3f v = triangle->getVertex(j);
358  manual_object->position(v[0], v[1], v[2]);
359  manual_object->colour(color.r, color.g, color.b, color.a);
360  }
361  for (int j = num_vertices - 1; j >= 0; j--) {
362  Eigen::Vector3f v = triangle->getVertex(j);
363  manual_object->position(v[0], v[1], v[2]);
364  manual_object->colour(color.r, color.g, color.b, color.a);
365  }
366  }
367  manual_object->end();
368  }
369  }
370  }
371 
373  const size_t i, const geometry_msgs::PolygonStamped& polygon)
374  {
375  Ogre::SceneNode* scene_node = arrow_nodes_[i];
376  scene_node->setVisible(true);
377  ArrowPtr arrow = arrow_objects_[i];
378  Ogre::Vector3 position;
379  Ogre::Quaternion orientation;
380  if (!getTransform(polygon.header, position, orientation))
381  return;
382  scene_node->setPosition(position);
383  scene_node->setOrientation(orientation); // scene node is at frame pose
387  = geo_polygon.getVertices();
388  Eigen::Vector3f centroid(0, 0, 0); // should be replaced by centroid method
389  if (vertices.size() == 0) {
390  ROS_ERROR("the size of vertices is 0");
391  }
392  else {
393  for (size_t j = 0; j < vertices.size(); j++) {
394  centroid = vertices[j] + centroid;
395  }
396  centroid = centroid / vertices.size();
397  }
398  Ogre::Vector3 pos(centroid[0], centroid[1], centroid[2]);
399  Eigen::Vector3f normal = geo_polygon.getNormal();
400  Ogre::Vector3 direction(normal[0], normal[1], normal[2]);
401  if (std::isnan(direction[0]) || std::isnan(direction[1]) || std::isnan(direction[2])) {
402  ROS_ERROR("failed to compute normal direction");
403  Ogre::Vector3 zeroscale(0, 0, 0);
404  arrow->setScale(zeroscale);
405  return;
406  }
408  arrow->setPosition(pos);
409  arrow->setDirection(direction);
410 
411  arrow->setScale(scale);
412  arrow->setColor(getColor(i));
413  }
414 
416  const jsk_recognition_msgs::PolygonArray::ConstPtr& msg)
417  {
418  if (!validateFloats(*msg)) {
420  "Topic",
421  "Message contained invalid floating point values"
422  "(nans or infs)");
423  return;
424  }
426  "Topic",
427  "ok");
428  latest_msg_ = msg;
429  // create nodes and manual objects
430  updateSceneNodes(msg);
431  allocateMaterials(msg->polygons.size());
432  updateLines(msg->polygons.size());
433  if (only_border_) {
434  // use line_
435  for (size_t i = 0; i < manual_objects_.size(); i++) {
436  manual_objects_[i]->setVisible(false);
437  }
438  for (size_t i = 0; i < msg->polygons.size(); i++) {
439  geometry_msgs::PolygonStamped polygon = msg->polygons[i];
440  if (polygon.polygon.points.size() >= 3) {
441  processLine(i, polygon);
442  }
443  }
444  }
445  else {
446  for (size_t i = 0; i < msg->polygons.size(); i++) {
448  }
449 
450  for (size_t i = 0; i < msg->polygons.size(); i++) {
451  geometry_msgs::PolygonStamped polygon = msg->polygons[i];
452  processPolygon(i, polygon);
453  }
454  }
455 
456  if (show_normal_) {
457  for (size_t i = 0; i < msg->polygons.size(); i++) {
458  geometry_msgs::PolygonStamped polygon = msg->polygons[i];
459  if (polygon.polygon.points.size() >= 3) {
460  processNormal(i, polygon);
461  }
462  }
463  }
464  }
465 
467  const std_msgs::Header &header,
468  Ogre::Vector3 &position, Ogre::Quaternion &orientation)
469  {
471  header.frame_id, header.stamp,
472  position, orientation);
473  if (!ok) {
474  std::ostringstream oss;
475  oss << "Error transforming from frame '";
476  oss << header.frame_id << "' to frame '";
477  oss << qPrintable(fixed_frame_) << "'";
478  ROS_DEBUG_STREAM(oss.str());
480  "Transform", QString::fromStdString(oss.str()));
481  }
482  return ok;
483  }
484 
486  {
487  if (coloring_property_->getOptionInt() == 0) {
488  coloring_method_ = "auto";
490  }
491  else if (coloring_property_->getOptionInt() == 1) {
492  coloring_method_ = "flat";
494  }
495  else if (coloring_property_->getOptionInt() == 2) {
496  coloring_method_ = "likelihood";
498  }
499  else if (coloring_property_->getOptionInt() == 3) {
500  coloring_method_ = "label";
502  }
503  }
504 
506  {
508  }
509 
511  {
513  if (show_normal_) {
515  }
516  else {
518  for (size_t i = 0; i < arrow_nodes_.size(); i++) {
519  arrow_nodes_[i]->setVisible(false);
520  }
521  }
522  }
523 
525  {
527  }
528 
530  {
532  }
533 }
534 
std_msgs::ColorRGBA heatColor(double v)
void setMin(float min)
virtual bool getTransform(const std_msgs::Header &header, Ogre::Vector3 &position, Ogre::Quaternion &orientation)
std::vector< Ogre::SceneNode * > arrow_nodes_
void setMax(float max)
virtual void processMessage(const jsk_recognition_msgs::PolygonArray::ConstPtr &msg)
pos
void addPoint(const Ogre::Vector3 &point)
PLUGINLIB_EXPORT_CLASS(jsk_rviz_plugins::PictogramArrayDisplay, rviz::Display)
DisplayContext * context_
virtual QColor getColor() const
virtual void processLine(const size_t i, const geometry_msgs::PolygonStamped &polygon)
virtual Vertices getVertices()
static Polygon fromROSMsg(const geometry_msgs::Polygon &polygon)
Ogre::SceneNode * scene_node_
jsk_recognition_msgs::PolygonArray::ConstPtr latest_msg_
virtual void processPolygonMaterial(const size_t i)
Ogre::ColourValue qtToOgre(const QColor &c)
QString fixed_frame_
virtual void processPolygon(const size_t i, const geometry_msgs::PolygonStamped &polygon)
virtual void processNormal(const size_t i, const geometry_msgs::PolygonStamped &polygon)
virtual void addOption(const QString &option, int value=0)
virtual void updateSceneNodes(const jsk_recognition_msgs::PolygonArray::ConstPtr &msg)
std::vector< Ogre::SceneNode * > scene_nodes_
bool validateFloats(const sensor_msgs::CameraInfo &msg)
void queueRender()
virtual QString getName() const
ROSCPP_DECL bool ok()
virtual FrameManager * getFrameManager() const=0
void setColor(float r, float g, float b, float a) override
bool validateFloats(const visualization_msgs::InteractiveMarker &msg)
void setNumLines(uint32_t num)
#define ROS_DEBUG_STREAM(args)
void setMaxPointsPerLine(uint32_t max)
Ogre::SceneManager * scene_manager_
std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f > > Vertices
virtual Ogre::SceneManager * getSceneManager() const=0
std::vector< rviz::BillboardLine * > lines_
std_msgs::ColorRGBA colorCategory20(int i)
std::vector< Ogre::MaterialPtr > materials_
virtual float getFloat() const
bool getTransform(const Header &header, Ogre::Vector3 &position, Ogre::Quaternion &orientation)
std::vector< Ogre::ManualObject * > manual_objects_
virtual Ogre::ColourValue getColor(size_t index)
virtual bool getBool() const
virtual int getOptionInt()
#define ROS_ERROR(...)
virtual void setStatus(StatusProperty::Level level, const QString &name, const QString &text)
virtual std::vector< Polygon::Ptr > decomposeToTriangles()
virtual Eigen::Vector3f getNormal()
void setLineWidth(float width)


jsk_rviz_plugins
Author(s): Kei Okada , Yohei Kakiuchi , Shohei Fujii , Ryohei Ueda
autogenerated on Thu Jun 1 2023 02:45:58