bounding_box_array_display.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2013, Ryohei Ueda and JSK Lab
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/o2r other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the JSK Lab nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 #include "bounding_box_array_display.h"
00036 #include <jsk_topic_tools/color_utils.h>
00037 namespace jsk_rviz_plugins
00038 {  
00039   BoundingBoxArrayDisplay::BoundingBoxArrayDisplay()
00040   {
00041     coloring_property_ = new rviz::EnumProperty(
00042       "coloring", "Auto",
00043       "coloring method",
00044       this, SLOT(updateColoring()));
00045     coloring_property_->addOption("Auto", 0);
00046     coloring_property_->addOption("Flat color", 1);
00047     coloring_property_->addOption("Label", 2);
00048     coloring_property_->addOption("Value", 3);
00049     
00050     color_property_ = new rviz::ColorProperty(
00051       "color", QColor(25, 255, 0),
00052       "color to draw the bounding boxes",
00053       this, SLOT(updateColor()));
00054     alpha_property_ = new rviz::FloatProperty(
00055       "alpha", 0.8,
00056       "alpha value to draw the bounding boxes",
00057       this, SLOT(updateAlpha()));
00058     only_edge_property_ = new rviz::BoolProperty(
00059       "only edge", false,
00060       "show only the edges of the boxes",
00061       this, SLOT(updateOnlyEdge()));
00062     line_width_property_ = new rviz::FloatProperty(
00063       "line width", 0.005,
00064       "line width of the edges",
00065       this, SLOT(updateLineWidth()));
00066     show_coords_property_ = new rviz::BoolProperty(
00067       "show coords", true,
00068       "show coordinate of bounding box",
00069       this, SLOT(updateShowCoords()));
00070   }
00071 
00072   BoundingBoxArrayDisplay::~BoundingBoxArrayDisplay()
00073   {
00074     delete color_property_;
00075     delete alpha_property_;
00076     delete only_edge_property_;
00077     delete coloring_property_;
00078     delete show_coords_property_;
00079   }
00080 
00081   QColor BoundingBoxArrayDisplay::getColor(
00082     size_t index,
00083     const jsk_recognition_msgs::BoundingBox& box,
00084     double min_value,
00085     double max_value)
00086   {
00087     if (coloring_method_ == "auto") {
00088       std_msgs::ColorRGBA ros_color = jsk_topic_tools::colorCategory20(index);
00089       return QColor(ros_color.r * 255.0,
00090                     ros_color.g * 255.0,
00091                     ros_color.b * 255.0,
00092                     ros_color.a * 255.0);
00093     }
00094     else if (coloring_method_ == "flat") {
00095       return color_;
00096     }
00097     else if (coloring_method_ == "label") {
00098       std_msgs::ColorRGBA ros_color = jsk_topic_tools::colorCategory20(box.label);
00099       return QColor(ros_color.r * 255.0,
00100                     ros_color.g * 255.0,
00101                     ros_color.b * 255.0,
00102                     ros_color.a * 255.0);
00103     }
00104     else if (coloring_method_ == "value") {
00105       if (min_value != max_value) {
00106         std_msgs::ColorRGBA ros_color = jsk_topic_tools::heatColor((box.value - min_value) / (max_value - min_value));
00107         return QColor(ros_color.r * 255.0,
00108                       ros_color.g * 255.0,
00109                       ros_color.b * 255.0,
00110                       ros_color.a * 255.0);
00111       }
00112       else {
00113         return QColor(255.0, 255.0, 255.0, 255.0);
00114       }
00115     }
00116   }
00117   
00118   void BoundingBoxArrayDisplay::onInitialize()
00119   {
00120     MFDClass::onInitialize();
00121     scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00122 
00123     updateColor();
00124     updateAlpha();
00125     updateOnlyEdge();
00126     updateColoring();
00127     updateLineWidth();
00128     updateShowCoords();
00129   }
00130 
00131   void BoundingBoxArrayDisplay::updateLineWidth()
00132   {
00133     line_width_ = line_width_property_->getFloat();
00134     if (latest_msg_) {
00135       processMessage(latest_msg_);
00136     }
00137   }
00138   
00139   void BoundingBoxArrayDisplay::updateColor()
00140   {
00141     color_ = color_property_->getColor();
00142     if (latest_msg_) {
00143       processMessage(latest_msg_);
00144     }
00145   }
00146 
00147   void BoundingBoxArrayDisplay::updateAlpha()
00148   {
00149     alpha_ = alpha_property_->getFloat();
00150     if (latest_msg_) {
00151       processMessage(latest_msg_);
00152     }
00153   }
00154 
00155   void BoundingBoxArrayDisplay::updateOnlyEdge()
00156   {
00157     only_edge_ = only_edge_property_->getBool();
00158     if (only_edge_) {
00159       line_width_property_->show();
00160     }
00161     else {
00162       line_width_property_->hide();;
00163     }
00164     // Imediately apply attribute
00165     if (latest_msg_) {
00166       if (only_edge_) {
00167         showEdges(latest_msg_);
00168       }
00169       else {
00170         showBoxes(latest_msg_);
00171       }
00172     }
00173   }
00174 
00175   void BoundingBoxArrayDisplay::updateColoring()
00176   {
00177     if (coloring_property_->getOptionInt() == 0) {
00178       coloring_method_ = "auto";
00179       color_property_->hide();
00180     }
00181     else if (coloring_property_->getOptionInt() == 1) {
00182       coloring_method_ = "flat";
00183       color_property_->show();
00184     }
00185     else if (coloring_property_->getOptionInt() == 2) {
00186       coloring_method_ = "label";
00187       color_property_->hide();
00188     }
00189     else if (coloring_property_->getOptionInt() == 3) {
00190       coloring_method_ = "value";
00191       color_property_->hide();
00192     }
00193     
00194     if (latest_msg_) {
00195       processMessage(latest_msg_);
00196     }
00197   }
00198   
00199   void BoundingBoxArrayDisplay::updateShowCoords()
00200   {
00201     show_coords_ = show_coords_property_->getBool();
00202     // Immediately apply show_coords attribute
00203     if (!show_coords_) {
00204       hideCoords();
00205     }
00206     else if (show_coords_ && latest_msg_) {
00207       showCoords(latest_msg_);
00208     }
00209   }
00210 
00211   void BoundingBoxArrayDisplay::reset()
00212   {
00213     MFDClass::reset();
00214     shapes_.clear();
00215     edges_.clear();
00216     coords_nodes_.clear();
00217     coords_objects_.clear();
00218     latest_msg_.reset();
00219   }
00220 
00221   void BoundingBoxArrayDisplay::allocateShapes(int num)
00222   {
00223     if (num > shapes_.size()) {
00224       for (size_t i = shapes_.size(); i < num; i++) {
00225         ShapePtr shape (new rviz::Shape(
00226                           rviz::Shape::Cube, context_->getSceneManager(),
00227                           scene_node_));
00228         shapes_.push_back(shape);
00229       }
00230     }
00231     else if (num < shapes_.size())
00232     {
00233       shapes_.resize(num);
00234     }
00235   }
00236 
00237   void BoundingBoxArrayDisplay::allocateBillboardLines(int num)
00238   {
00239     if (num > edges_.size()) {
00240       for (size_t i = edges_.size(); i < num; i++) {
00241         BillboardLinePtr line(new rviz::BillboardLine(
00242                                 context_->getSceneManager(), scene_node_));
00243         edges_.push_back(line);
00244       }
00245     }
00246     else if (num < edges_.size())
00247       {
00248         edges_.resize(num);       // ok??
00249       }
00250   }
00251 
00252   void BoundingBoxArrayDisplay::allocateCoords(int num)
00253   {
00254     if (num > coords_objects_.size()) {
00255       for (size_t i = coords_objects_.size(); i < num; i++) {
00256         Ogre::SceneNode* scene_node = scene_node_->createChildSceneNode();
00257         std::vector<ArrowPtr> coord;
00258         for (int i = 0; i < 3; i++) {
00259           ArrowPtr arrow (new rviz::Arrow(scene_manager_, scene_node));
00260           coord.push_back(arrow);
00261         }
00262         coords_nodes_.push_back(scene_node);
00263         coords_objects_.push_back(coord);
00264       }
00265     }
00266     else if (num < coords_objects_.size()) {
00267       coords_objects_.resize(num);
00268     }
00269   }
00270 
00271   bool BoundingBoxArrayDisplay::isValid(
00272     const jsk_recognition_msgs::BoundingBoxArray::ConstPtr& msg)
00273   {
00274     // Check size
00275     for (size_t i = 0; i < msg->boxes.size(); i++) {
00276       jsk_recognition_msgs::BoundingBox box = msg->boxes[i];
00277       if (box.dimensions.x < 1.0e-9 || 
00278           box.dimensions.y < 1.0e-9 ||
00279           box.dimensions.z < 1.0e-9 ||
00280           std::isnan(box.dimensions.x) ||
00281           std::isnan(box.dimensions.y) ||
00282           std::isnan(box.dimensions.z)) {
00283         ROS_FATAL("Size of bounding box is [%f, %f, %f]",
00284                   box.dimensions.x,
00285                   box.dimensions.y,
00286                   box.dimensions.z);
00287         return false;
00288       }
00289     }
00290     return true;
00291   }
00292 
00293   void BoundingBoxArrayDisplay::showBoxes(
00294     const jsk_recognition_msgs::BoundingBoxArray::ConstPtr& msg)
00295   {
00296     edges_.clear();
00297     allocateShapes(msg->boxes.size());
00298     float min_value = DBL_MAX;
00299     float max_value = -DBL_MAX;
00300     for (size_t i = 0; i < msg->boxes.size(); i++) {
00301       min_value = std::min(min_value, msg->boxes[i].value);
00302       max_value = std::max(max_value, msg->boxes[i].value);
00303     }
00304     for (size_t i = 0; i < msg->boxes.size(); i++) {
00305       jsk_recognition_msgs::BoundingBox box = msg->boxes[i];
00306       ShapePtr shape = shapes_[i];
00307       Ogre::Vector3 position;
00308       Ogre::Quaternion quaternion;
00309       if(!context_->getFrameManager()->transform(box.header, box.pose,
00310                                                  position,
00311                                                  quaternion)) {
00312         ROS_ERROR( "Error transforming pose"
00313                    "'%s' from frame '%s' to frame '%s'",
00314                    qPrintable( getName() ), box.header.frame_id.c_str(),
00315                    qPrintable( fixed_frame_ ));
00316         return;                 // return?
00317       }
00318       shape->setPosition(position);
00319       shape->setOrientation(quaternion);
00320       Ogre::Vector3 dimensions;
00321       dimensions[0] = box.dimensions.x;
00322       dimensions[1] = box.dimensions.y;
00323       dimensions[2] = box.dimensions.z;
00324       shape->setScale(dimensions);
00325       QColor color = getColor(i, box, min_value, max_value);
00326       shape->setColor(color.red() / 255.0,
00327                       color.green() / 255.0,
00328                       color.blue() / 255.0,
00329                       alpha_);
00330     }
00331   }
00332 
00333   void BoundingBoxArrayDisplay::showEdges(
00334     const jsk_recognition_msgs::BoundingBoxArray::ConstPtr& msg)
00335   {
00336     shapes_.clear();
00337     allocateBillboardLines(msg->boxes.size());
00338     float min_value = DBL_MAX;
00339     float max_value = -DBL_MAX;
00340     for (size_t i = 0; i < msg->boxes.size(); i++) {
00341       min_value = std::min(min_value, msg->boxes[i].value);
00342       max_value = std::max(max_value, msg->boxes[i].value);
00343     }
00344 
00345     for (size_t i = 0; i < msg->boxes.size(); i++) {
00346       jsk_recognition_msgs::BoundingBox box = msg->boxes[i];
00347       geometry_msgs::Vector3 dimensions = box.dimensions;
00348       
00349       BillboardLinePtr edge = edges_[i];
00350       edge->clear();
00351       Ogre::Vector3 position;
00352       Ogre::Quaternion quaternion;
00353       if(!context_->getFrameManager()->transform(box.header, box.pose,
00354                                                  position,
00355                                                  quaternion)) {
00356         ROS_ERROR( "Error transforming pose"
00357                    "'%s' from frame '%s' to frame '%s'",
00358                    qPrintable( getName() ), box.header.frame_id.c_str(),
00359                    qPrintable( fixed_frame_ ));
00360         return;                 // return?
00361       }
00362       edge->setPosition(position);
00363       edge->setOrientation(quaternion);
00364 
00365       edge->setMaxPointsPerLine(2);
00366       edge->setNumLines(12);
00367       edge->setLineWidth(line_width_);
00368       QColor color = getColor(i, box, min_value, max_value);
00369       edge->setColor(color.red() / 255.0,
00370                      color.green() / 255.0,
00371                      color.blue() / 255.0,
00372                      alpha_);
00373 
00374 
00375       
00376       Ogre::Vector3 A, B, C, D, E, F, G, H;
00377       A[0] = dimensions.x / 2.0;
00378       A[1] = dimensions.y / 2.0;
00379       A[2] = dimensions.z / 2.0;
00380       B[0] = - dimensions.x / 2.0;
00381       B[1] = dimensions.y / 2.0;
00382       B[2] = dimensions.z / 2.0;
00383       C[0] = - dimensions.x / 2.0;
00384       C[1] = - dimensions.y / 2.0;
00385       C[2] = dimensions.z / 2.0;
00386       D[0] = dimensions.x / 2.0;
00387       D[1] = - dimensions.y / 2.0;
00388       D[2] = dimensions.z / 2.0;
00389 
00390       E[0] = dimensions.x / 2.0;
00391       E[1] = dimensions.y / 2.0;
00392       E[2] = - dimensions.z / 2.0;
00393       F[0] = - dimensions.x / 2.0;
00394       F[1] = dimensions.y / 2.0;
00395       F[2] = - dimensions.z / 2.0;
00396       G[0] = - dimensions.x / 2.0;
00397       G[1] = - dimensions.y / 2.0;
00398       G[2] = - dimensions.z / 2.0;
00399       H[0] = dimensions.x / 2.0;
00400       H[1] = - dimensions.y / 2.0;
00401       H[2] = - dimensions.z / 2.0;
00402       
00403       edge->addPoint(A); edge->addPoint(B); edge->newLine();
00404       edge->addPoint(B); edge->addPoint(C); edge->newLine();
00405       edge->addPoint(C); edge->addPoint(D); edge->newLine();
00406       edge->addPoint(D); edge->addPoint(A); edge->newLine();
00407       edge->addPoint(E); edge->addPoint(F); edge->newLine();
00408       edge->addPoint(F); edge->addPoint(G); edge->newLine();
00409       edge->addPoint(G); edge->addPoint(H); edge->newLine();
00410       edge->addPoint(H); edge->addPoint(E); edge->newLine();
00411       edge->addPoint(A); edge->addPoint(E); edge->newLine();
00412       edge->addPoint(B); edge->addPoint(F); edge->newLine();
00413       edge->addPoint(C); edge->addPoint(G); edge->newLine();
00414       edge->addPoint(D); edge->addPoint(H);
00415     }
00416   }
00417 
00418   void BoundingBoxArrayDisplay::showCoords(
00419     const jsk_recognition_msgs::BoundingBoxArray::ConstPtr& msg)
00420   {
00421     allocateCoords(msg->boxes.size());
00422     for (size_t i = 0; i < msg->boxes.size(); i++) {
00423       jsk_recognition_msgs::BoundingBox box = msg->boxes[i];
00424       std::vector<ArrowPtr> coord = coords_objects_[i];
00425 
00426       Ogre::SceneNode* scene_node = coords_nodes_[i];
00427       scene_node->setVisible(true);
00428       Ogre::Vector3 position;
00429       Ogre::Quaternion orientation;
00430       if(!context_->getFrameManager()->getTransform(
00431            box.header, position, orientation)) {
00432         ROS_DEBUG("Error transforming from frame '%s' to frame '%s'",
00433                   box.header.frame_id.c_str(), qPrintable(fixed_frame_));
00434         return;
00435       }
00436       scene_node->setPosition(position);
00437       scene_node->setOrientation(orientation); // scene node is at frame pose
00438 
00439       float color[3][3] = {{1, 0, 0},
00440                            {0, 1, 0},
00441                            {0, 0, 1}};
00442       for (int j = 0; j < 3; j++) {
00443         // check radius diraction
00444         Ogre::Vector3 scale;
00445         if (color[j][0] == 1) {
00446           scale = Ogre::Vector3(
00447             box.dimensions.x,
00448             std::min(box.dimensions.y, box.dimensions.z),
00449             std::min(box.dimensions.y, box.dimensions.z));
00450         }
00451         if (color[j][1] == 1) {
00452           scale = Ogre::Vector3(
00453             box.dimensions.y,
00454             std::min(box.dimensions.x, box.dimensions.z),
00455             std::min(box.dimensions.x, box.dimensions.z));
00456         }
00457         if (color[j][2] == 1) {
00458           scale = Ogre::Vector3(
00459             box.dimensions.z,
00460             std::min(box.dimensions.x, box.dimensions.y),
00461             std::min(box.dimensions.x, box.dimensions.y));
00462         }
00463           
00464         Ogre::Vector3 direction(color[j][0], color[j][1], color[j][2]);
00465         Ogre::Vector3 pos(box.pose.position.x,
00466                           box.pose.position.y,
00467                           box.pose.position.z);
00468         Ogre::Quaternion qua(box.pose.orientation.w,
00469                              box.pose.orientation.x,
00470                              box.pose.orientation.y,
00471                              box.pose.orientation.z);
00472         direction = qua * direction;
00473         Ogre::ColourValue rgba;
00474         rgba.a = 1;
00475         rgba.r = color[j][0];
00476         rgba.g = color[j][1];
00477         rgba.b = color[j][2];
00478 
00479         ArrowPtr arrow = coords_objects_[i][j];
00480         arrow->setPosition(pos);
00481         arrow->setDirection(direction);
00482         arrow->setScale(scale);
00483         arrow->setColor(rgba);
00484       }
00485     }
00486   }
00487 
00488   void BoundingBoxArrayDisplay::hideCoords()
00489   {
00490     for (size_t i = 0; i < coords_nodes_.size(); i++) {
00491       coords_nodes_[i]->setVisible(false);
00492     }
00493   }
00494   
00495   void BoundingBoxArrayDisplay::processMessage(
00496     const jsk_recognition_msgs::BoundingBoxArray::ConstPtr& msg)
00497   {
00498     if (!isValid(msg)) {
00499       return;
00500     }
00501     // Store latest message
00502     latest_msg_ = msg;
00503     
00504     if (!only_edge_) {
00505       showBoxes(msg);
00506     }
00507     else {
00508       showEdges(msg);
00509     }
00510 
00511     if (show_coords_) {
00512       showCoords(msg);
00513     }
00514     else {
00515       hideCoords();
00516     }
00517   }
00518 }
00519 
00520 #include <pluginlib/class_list_macros.h>
00521 PLUGINLIB_EXPORT_CLASS(
00522   jsk_rviz_plugins::BoundingBoxArrayDisplay, rviz::Display)


jsk_rviz_plugins
Author(s): Kei Okada , Yohei Kakiuchi , Shohei Fujii , Ryohei Ueda
autogenerated on Sun Sep 13 2015 22:29:03