00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
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     
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         
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     
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         
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     
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); 
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); 
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     
00429     updateSceneNodes(msg);
00430     allocateMaterials(msg->polygons.size());
00431     updateLines(msg->polygons.size());
00432     if (only_border_) {
00433       
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)