polygon_array_display.cpp
Go to the documentation of this file.
00001 // -*- mode: c++ -*-
00002 /*********************************************************************
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2015, JSK Lab
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/o2r other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the JSK Lab nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *********************************************************************/
00035 
00036 #define BOOST_PARAMETER_MAX_ARITY 7
00037 
00038 #include "polygon_array_display.h"
00039 #include "rviz/properties/parse_color.h"
00040 #include <rviz/validate_floats.h>
00041 #include <jsk_topic_tools/color_utils.h>
00042 #include <jsk_recognition_utils/geo/polygon.h>
00043 
00044 namespace jsk_rviz_plugins
00045 {
00046   PolygonArrayDisplay::PolygonArrayDisplay()
00047   {
00048     coloring_property_ = new rviz::EnumProperty(
00049       "coloring", "Auto",
00050       "coloring method",
00051       this, SLOT(updateColoring()));
00052     coloring_property_->addOption("Auto", 0);
00053     coloring_property_->addOption("Flat color", 1);
00054     coloring_property_->addOption("Liekelihood", 2);
00055     coloring_property_->addOption("Label", 3);
00056     color_property_ = new rviz::ColorProperty(
00057       "Color", QColor(25, 255, 0),
00058       "Color to draw the polygons.",
00059       this, SLOT(queueRender()));
00060     alpha_property_ = new rviz::FloatProperty(
00061       "Alpha", 1.0,
00062       "Amount of transparency to apply to the polygon.",
00063       this, SLOT(queueRender()));
00064     only_border_property_ = new rviz::BoolProperty(
00065       "only border", true,
00066       "only shows the borders of polygons",
00067       this, SLOT(updateOnlyBorder()));
00068     show_normal_property_ = new rviz::BoolProperty(
00069       "show normal", true,
00070       "show normal direction",
00071       this, SLOT(updateShowNormal()));
00072     enable_lighting_property_ = new rviz::BoolProperty(
00073       "enable lighting", true,
00074       "enable lighting",
00075       this, SLOT(updateEnableLighting()));
00076     normal_length_property_ = new rviz::FloatProperty(
00077       "normal length", 0.1,
00078       "normal length",
00079       this, SLOT(updateNormalLength()));
00080     normal_length_property_->setMin(0);
00081     //only_border_ = true;
00082     alpha_property_->setMin(0);
00083     alpha_property_->setMax(1);
00084   }
00085   
00086   PolygonArrayDisplay::~PolygonArrayDisplay()
00087   {
00088     delete alpha_property_;
00089     delete color_property_;
00090     delete only_border_property_;
00091     delete coloring_property_;
00092     delete show_normal_property_;
00093     delete normal_length_property_;
00094     for (size_t i = 0; i < lines_.size(); i++) {
00095       delete lines_[i];
00096     }
00097     
00098     for (size_t i = 0; i < materials_.size(); i++) {
00099       materials_[i]->unload();
00100       Ogre::MaterialManager::getSingleton().remove(materials_[i]->getName());
00101     }
00102     
00103     for (size_t i = 0; i < manual_objects_.size(); i++) {
00104       scene_manager_->destroyManualObject(manual_objects_[i]);
00105       scene_manager_->destroySceneNode(scene_nodes_[i]);
00106     }
00107   }
00108   
00109   void PolygonArrayDisplay::onInitialize()
00110   {
00111     MFDClass::onInitialize();
00112     updateOnlyBorder();
00113     updateColoring();
00114     updateShowNormal();
00115     updateNormalLength();
00116   }
00117 
00118   void PolygonArrayDisplay::allocateMaterials(int num)
00119   {
00120     if (only_border_) {
00121       return;
00122     }
00123     static uint32_t count = 0;
00124     
00125     if (num > materials_.size()) {
00126       for (size_t i = materials_.size(); num > i; i++) {
00127         std::stringstream ss;
00128         ss << "PolygonArrayMaterial" << count++;
00129         Ogre::MaterialPtr material
00130           = Ogre::MaterialManager::getSingleton().create(ss.str(), "rviz");
00131         material->setReceiveShadows(false);
00132         material->getTechnique(0)->setLightingEnabled(enable_lighting_);
00133         material->getTechnique(0)->setAmbient(0.5, 0.5, 0.5);
00134 
00135         //material->setCullingMode(Ogre::CULL_NONE);
00136         materials_.push_back(material);
00137       }
00138     }
00139   }
00140   
00141   bool validateFloats(const jsk_recognition_msgs::PolygonArray& msg)
00142   {
00143     for (size_t i = 0; i < msg.polygons.size(); i++) {
00144       if (!rviz::validateFloats(msg.polygons[i].polygon.points))
00145         return false;
00146     }
00147     return true;
00148   }
00149   
00150   void PolygonArrayDisplay::reset()
00151   {
00152     MFDClass::reset();
00153     for (size_t i = 0; i < manual_objects_.size(); i++) {
00154       manual_objects_[i]->clear();
00155     }
00156   }
00157 
00158   void PolygonArrayDisplay::updateSceneNodes(
00159     const jsk_recognition_msgs::PolygonArray::ConstPtr& msg)
00160   {
00161     int scale_factor = 2;
00162     if (only_border_) {
00163       scale_factor = 1;
00164     }
00165     if (msg->polygons.size() * scale_factor > manual_objects_.size()) {
00166       for (size_t i = manual_objects_.size();
00167            i < msg->polygons.size() * scale_factor;
00168            i++) {
00169         Ogre::SceneNode* scene_node
00170           = scene_node_->createChildSceneNode();
00171         Ogre::ManualObject* manual_object
00172           = scene_manager_->createManualObject();
00173         manual_object->setDynamic(true);
00174         scene_node->attachObject(manual_object);
00175         manual_objects_.push_back(manual_object);
00176         scene_nodes_.push_back(scene_node);
00177       }
00178     }
00179     else if (msg->polygons.size() * scale_factor < manual_objects_.size()) {
00180       for (size_t i = msg->polygons.size() * scale_factor;
00181            i < manual_objects_.size(); i++) {
00182         manual_objects_[i]->setVisible(false);
00183       }
00184     }
00185     // arrow nodes
00186     if (msg->polygons.size() > arrow_objects_.size()) {
00187       for (size_t i = arrow_objects_.size(); i < msg->polygons.size(); i++) {
00188         Ogre::SceneNode* scene_node = scene_node_->createChildSceneNode();
00189         ArrowPtr arrow (new rviz::Arrow(scene_manager_, scene_node));
00190         scene_node->setVisible(false);
00191         arrow_objects_.push_back(arrow);
00192         arrow_nodes_.push_back(scene_node);
00193       }
00194     }
00195     else if (msg->polygons.size() < manual_objects_.size()) {
00196       for (size_t i = msg->polygons.size(); i < arrow_nodes_.size(); i++) {
00197         //arrow_objects_[i]->setVisible(false);
00198         arrow_nodes_[i]->setVisible(false);
00199       }
00200     }
00201   }
00202 
00203   void PolygonArrayDisplay::updateLines(int num)
00204   {
00205     if (num > lines_.size()) {
00206       for (size_t i = lines_.size(); i < num; i++) {
00207         rviz::BillboardLine* line
00208           = new rviz::BillboardLine(context_->getSceneManager(),
00209                                     scene_nodes_[i]);
00210         line->setLineWidth(0.01);
00211         line->setNumLines(1);
00212         lines_.push_back(line);
00213       }
00214     }
00215     for (size_t i = 0; i < lines_.size(); i++) {
00216       lines_[i]->clear();
00217     }
00218   }
00219   
00220   Ogre::ColourValue PolygonArrayDisplay::getColor(size_t index)
00221   {
00222     Ogre::ColourValue color;
00223     if (coloring_method_ == "auto") {
00224       std_msgs::ColorRGBA ros_color = jsk_topic_tools::colorCategory20(index);
00225       color.r = ros_color.r;
00226       color.g = ros_color.g;
00227       color.b = ros_color.b;
00228       color.a = ros_color.a;
00229     }
00230     else if (coloring_method_ == "flat") {
00231       color = rviz::qtToOgre(color_property_->getColor());
00232     }
00233     else if (coloring_method_ == "likelihood") {
00234       if (latest_msg_->likelihood.size() == 0 ||
00235           latest_msg_->likelihood.size() < index) {
00236         setStatus(rviz::StatusProperty::Error,
00237                   "Topic",
00238                   "Message does not have lieklihood fields");
00239       }
00240       else {
00241         std_msgs::ColorRGBA ros_color
00242           = jsk_topic_tools::heatColor(latest_msg_->likelihood[index]);
00243         color.r = ros_color.r;
00244         color.g = ros_color.g;
00245         color.b = ros_color.b;
00246         color.a = ros_color.a;
00247       }
00248     }
00249     else if (coloring_method_ == "label") {
00250       if (latest_msg_->labels.size() == 0 ||
00251           latest_msg_->labels.size() < index) {
00252         setStatus(rviz::StatusProperty::Error,
00253                   "Topic",
00254                   "Message does not have lebels fields");
00255       }
00256       else {
00257         std_msgs::ColorRGBA ros_color
00258           = jsk_topic_tools::colorCategory20(latest_msg_->labels[index]);
00259         color.r = ros_color.r;
00260         color.g = ros_color.g;
00261         color.b = ros_color.b;
00262         color.a = ros_color.a;
00263       }
00264     }
00265     color.a = alpha_property_->getFloat();
00266     return color;
00267   }
00268 
00269   void PolygonArrayDisplay::processLine(
00270     const size_t i,
00271     const geometry_msgs::PolygonStamped& polygon)
00272   {
00273     Ogre::SceneNode* scene_node = scene_nodes_[i];
00274     //Ogre::ManualObject* manual_object = manual_objects_[i];
00275     Ogre::Vector3 position;
00276     Ogre::Quaternion orientation;
00277     if (!getTransform(polygon.header, position, orientation))
00278       return;
00279     scene_node->setPosition(position);
00280     scene_node->setOrientation(orientation);
00281     rviz::BillboardLine* line = lines_[i];
00282     line->clear();
00283     line->setMaxPointsPerLine(polygon.polygon.points.size() + 1);
00284         
00285     Ogre::ColourValue color = getColor(i);
00286     line->setColor(color.r, color.g, color.b, color.a);
00287 
00288     for (size_t i = 0; i < polygon.polygon.points.size(); ++i) {
00289       Ogre::Vector3 step_position;
00290       step_position.x = polygon.polygon.points[i].x;
00291       step_position.y = polygon.polygon.points[i].y;
00292       step_position.z = polygon.polygon.points[i].z;
00293       line->addPoint(step_position);
00294     }
00295     Ogre::Vector3 step_position;
00296     step_position.x = polygon.polygon.points[0].x;
00297     step_position.y = polygon.polygon.points[0].y;
00298     step_position.z = polygon.polygon.points[0].z;
00299     line->addPoint(step_position);
00300   }
00301 
00302   void PolygonArrayDisplay::processPolygonMaterial(const size_t i)
00303   {
00304     Ogre::ColourValue color = getColor(i);
00305     materials_[i]->getTechnique(0)->setLightingEnabled(enable_lighting_);
00306     materials_[i]->getTechnique(0)->setAmbient(color * 0.5);
00307     materials_[i]->getTechnique(0)->setDiffuse(color);
00308     if (color.a < 0.9998) {
00309       materials_[i]->getTechnique(0)->setSceneBlending(
00310         Ogre::SBT_TRANSPARENT_ALPHA);
00311       materials_[i]->getTechnique(0)->setDepthWriteEnabled(false);
00312     }
00313     else {
00314       materials_[i]->getTechnique(0)->setSceneBlending(Ogre::SBT_REPLACE);
00315       materials_[i]->getTechnique(0)->setDepthWriteEnabled(true);
00316     }
00317 
00318     materials_[i]->getTechnique(0)->setAmbient(color * 0.5);
00319     materials_[i]->getTechnique(0)->setDiffuse(color);
00320   }
00321 
00322   void PolygonArrayDisplay::processPolygon(
00323     const size_t i, const geometry_msgs::PolygonStamped& polygon)
00324   {
00325     Ogre::Vector3 position;
00326     Ogre::Quaternion orientation;
00327     if (!getTransform(polygon.header, position, orientation))
00328       return;
00329     
00330     {
00331       Ogre::SceneNode* scene_node = scene_nodes_[i * 2];
00332       Ogre::ManualObject* manual_object = manual_objects_[i * 2];
00333       Ogre::ColourValue color = getColor(i);
00334       scene_node->setPosition(position);
00335       scene_node->setOrientation(orientation);
00336       manual_object->clear();
00337       manual_object->setVisible(true);
00338       
00339       jsk_recognition_utils::Polygon geo_polygon
00340         = jsk_recognition_utils::Polygon::fromROSMsg(polygon.polygon);
00341       std::vector<jsk_recognition_utils::Polygon::Ptr>
00342         triangles = geo_polygon.decomposeToTriangles();
00343         
00344       uint32_t num_points = 0;
00345       for (size_t j = 0; j < triangles.size(); j++) {
00346         num_points += triangles[j]->getNumVertices();
00347       }
00348       if(num_points > 0) {
00349         manual_object->estimateVertexCount(num_points * 2);
00350         manual_object->begin(
00351           materials_[i]->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST);
00352         for (size_t ii = 0; ii < triangles.size(); ii++) {
00353           jsk_recognition_utils::Polygon::Ptr triangle = triangles[ii];
00354           size_t num_vertices = triangle->getNumVertices();
00355           for (size_t j = 0; j < num_vertices; j++) {
00356             Eigen::Vector3f v = triangle->getVertex(j);
00357             manual_object->position(v[0], v[1], v[2]);
00358             manual_object->colour(color.r, color.g, color.b, color.a);
00359           }
00360           for (int j = num_vertices - 1; j >= 0; j--) {
00361             Eigen::Vector3f v = triangle->getVertex(j);
00362             manual_object->position(v[0], v[1], v[2]);
00363             manual_object->colour(color.r, color.g, color.b, color.a);
00364           }
00365         }
00366         manual_object->end();
00367       }
00368     }
00369   }
00370   
00371   void PolygonArrayDisplay::processNormal(
00372     const size_t i, const geometry_msgs::PolygonStamped& polygon)
00373   {
00374     Ogre::SceneNode* scene_node = arrow_nodes_[i];
00375     scene_node->setVisible(true);
00376     ArrowPtr arrow = arrow_objects_[i];
00377     Ogre::Vector3 position;
00378     Ogre::Quaternion orientation;
00379     if (!getTransform(polygon.header, position, orientation))
00380       return;
00381     scene_node->setPosition(position);
00382     scene_node->setOrientation(orientation); // scene node is at frame pose
00383     jsk_recognition_utils::Polygon geo_polygon
00384       = jsk_recognition_utils::Polygon::fromROSMsg(polygon.polygon);
00385     jsk_recognition_utils::Vertices vertices
00386       = geo_polygon.getVertices();
00387     Eigen::Vector3f centroid(0, 0, 0); // should be replaced by centroid method
00388     if (vertices.size() == 0) {
00389       ROS_ERROR("the size of vertices is 0");
00390     }
00391     else {
00392       for (size_t j = 0; j < vertices.size(); j++) {
00393         centroid = vertices[j] + centroid;
00394       }
00395       centroid = centroid / vertices.size();
00396     }
00397     Ogre::Vector3 pos(centroid[0], centroid[1], centroid[2]);
00398     Eigen::Vector3f normal = geo_polygon.getNormal();
00399     Ogre::Vector3 direction(normal[0], normal[1], normal[2]);
00400     if (std::isnan(direction[0]) || std::isnan(direction[1]) || std::isnan(direction[2])) {
00401       ROS_ERROR("failed to compute normal direction");
00402       Ogre::Vector3 zeroscale(0, 0, 0);
00403       arrow->setScale(zeroscale);
00404       return;
00405     }
00406     Ogre::Vector3 scale(normal_length_, normal_length_, normal_length_);
00407     arrow->setPosition(pos);
00408     arrow->setDirection(direction);
00409     
00410     arrow->setScale(scale);
00411     arrow->setColor(getColor(i));
00412   }
00413   
00414   void PolygonArrayDisplay::processMessage(
00415     const jsk_recognition_msgs::PolygonArray::ConstPtr& msg)
00416   {
00417     if (!validateFloats(*msg)) {
00418       setStatus(rviz::StatusProperty::Error,
00419                 "Topic",
00420                 "Message contained invalid floating point values"
00421                 "(nans or infs)");
00422       return;
00423     }
00424     setStatus(rviz::StatusProperty::Ok,
00425               "Topic",
00426               "ok");
00427     latest_msg_ = msg;
00428     // create nodes and manual objects
00429     updateSceneNodes(msg);
00430     allocateMaterials(msg->polygons.size());
00431     updateLines(msg->polygons.size());
00432     if (only_border_) {
00433       // use line_
00434       for (size_t i = 0; i < manual_objects_.size(); i++) {
00435         manual_objects_[i]->setVisible(false);
00436       }
00437       for (size_t i = 0; i < msg->polygons.size(); i++) {
00438         geometry_msgs::PolygonStamped polygon = msg->polygons[i];
00439         if (polygon.polygon.points.size() >= 3) {
00440           processLine(i, polygon);
00441         }
00442       }
00443     }
00444     else {
00445       for (size_t i = 0; i < msg->polygons.size(); i++) {
00446         processPolygonMaterial(i);
00447       }
00448       
00449       for (size_t i = 0; i < msg->polygons.size(); i++) {
00450         geometry_msgs::PolygonStamped polygon = msg->polygons[i];
00451         processPolygon(i, polygon);
00452       }
00453     }
00454 
00455     if (show_normal_) {
00456       for (size_t i = 0; i < msg->polygons.size(); i++) {
00457         geometry_msgs::PolygonStamped polygon = msg->polygons[i];
00458         processNormal(i, polygon);
00459       }
00460     }
00461   }
00462 
00463   bool PolygonArrayDisplay::getTransform(
00464       const std_msgs::Header &header,
00465       Ogre::Vector3 &position, Ogre::Quaternion &orientation)
00466   {
00467     bool ok = context_->getFrameManager()->getTransform(
00468         header.frame_id, header.stamp,
00469         position, orientation);
00470     if (!ok) {
00471       std::ostringstream oss;
00472       oss << "Error transforming from frame '";
00473       oss << header.frame_id << "' to frame '";
00474       oss << qPrintable(fixed_frame_) << "'";
00475       ROS_DEBUG_STREAM(oss.str());
00476       setStatus(rviz::StatusProperty::Error,
00477                 "Transform", QString::fromStdString(oss.str()));
00478     }
00479     return ok;
00480   }
00481 
00482   void PolygonArrayDisplay::updateColoring()
00483   {
00484     if (coloring_property_->getOptionInt() == 0) {
00485       coloring_method_ = "auto";
00486       color_property_->hide();
00487     }
00488     else if (coloring_property_->getOptionInt() == 1) {
00489       coloring_method_ = "flat";
00490       color_property_->show();
00491     }
00492     else if (coloring_property_->getOptionInt() == 2) {
00493       coloring_method_ = "likelihood";
00494       color_property_->hide();
00495     }
00496     else if (coloring_property_->getOptionInt() == 3) {
00497       coloring_method_ = "label";
00498       color_property_->hide();
00499     }
00500   }
00501 
00502   void PolygonArrayDisplay::updateOnlyBorder()
00503   {
00504     only_border_ = only_border_property_->getBool();
00505   }
00506 
00507   void PolygonArrayDisplay::updateShowNormal()
00508   {
00509     show_normal_ = show_normal_property_->getBool();
00510     if (show_normal_) {
00511       normal_length_property_->show();
00512     }
00513     else {
00514       normal_length_property_->hide();
00515       for (size_t i = 0; i < arrow_nodes_.size(); i++) {
00516         arrow_nodes_[i]->setVisible(false);
00517       }
00518     }
00519   }
00520 
00521   void PolygonArrayDisplay::updateEnableLighting()
00522   {
00523     enable_lighting_ = enable_lighting_property_->getBool();
00524   }
00525 
00526   void PolygonArrayDisplay::updateNormalLength()
00527   {
00528     normal_length_ = normal_length_property_->getFloat();
00529   }
00530 }
00531 
00532 #include <pluginlib/class_list_macros.h>
00533 PLUGINLIB_EXPORT_CLASS(jsk_rviz_plugins::PolygonArrayDisplay, rviz::Display)


jsk_rviz_plugins
Author(s): Kei Okada , Yohei Kakiuchi , Shohei Fujii , Ryohei Ueda
autogenerated on Wed May 1 2019 02:40:22