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 #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
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
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);
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
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;
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;
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);
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
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
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)