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)