00001 #include "polygon_array_display.h"
00002 #include "rviz/properties/parse_color.h"
00003 #include <rviz/validate_floats.h>
00004 #include <jsk_topic_tools/color_utils.h>
00005 #include <jsk_pcl_ros/geo_util.h>
00006
00007 namespace jsk_rviz_plugin
00008 {
00009 PolygonArrayDisplay::PolygonArrayDisplay()
00010 {
00011 auto_coloring_property_ = new rviz::BoolProperty("auto color", true,
00012 "automatically change the color of the polygons",
00013 this, SLOT(updateAutoColoring()));
00014 color_property_ = new rviz::ColorProperty( "Color", QColor( 25, 255, 0 ),
00015 "Color to draw the polygons.",
00016 this, SLOT( queueRender() ));
00017 alpha_property_ = new rviz::FloatProperty( "Alpha", 1.0,
00018 "Amount of transparency to apply to the polygon.",
00019 this, SLOT( queueRender() ));
00020 only_border_property_ = new rviz::BoolProperty("only border", true,
00021 "only shows the borders of polygons",
00022 this, SLOT(updateOnlyBorder()));
00023
00024 alpha_property_->setMin( 0 );
00025 alpha_property_->setMax( 1 );
00026 }
00027
00028 PolygonArrayDisplay::~PolygonArrayDisplay()
00029 {
00030 delete alpha_property_;
00031 delete color_property_;
00032
00033 delete auto_coloring_property_;
00034
00035 for (size_t i = 0; i < lines_.size(); i++) {
00036 delete lines_[i];
00037 }
00038
00039 for (size_t i = 0; i < materials_.size(); i++) {
00040 materials_[i]->unload();
00041 Ogre::MaterialManager::getSingleton().remove(materials_[i]->getName());
00042 }
00043
00044 for (size_t i = 0; i < manual_objects_.size(); i++) {
00045 scene_manager_->destroyManualObject(manual_objects_[i]);
00046 scene_manager_->destroySceneNode(scene_nodes_[i]);
00047 }
00048 }
00049
00050 void PolygonArrayDisplay::onInitialize()
00051 {
00052 MFDClass::onInitialize();
00053 updateOnlyBorder();
00054 updateAutoColoring();
00055 }
00056
00057 void PolygonArrayDisplay::allocateMaterials(int num)
00058 {
00059 if (only_border_) {
00060 return;
00061 }
00062 static uint32_t count = 0;
00063
00064 if (num > materials_.size()) {
00065 for (size_t i = materials_.size(); num > i; i++) {
00066 std::stringstream ss;
00067 ss << "PolygonArrayMaterial" << count++;
00068 Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(ss.str(), "rviz");
00069 material->setReceiveShadows(false);
00070 material->getTechnique(0)->setLightingEnabled(true);
00071 material->getTechnique(0)->setAmbient( 0.5, 0.5, 0.5 );
00072 materials_.push_back(material);
00073 }
00074 }
00075 }
00076
00077 bool validateFloats( const jsk_pcl_ros::PolygonArray& msg)
00078 {
00079 for (size_t i = 0; i < msg.polygons.size(); i++) {
00080 if (!rviz::validateFloats(msg.polygons[i].polygon.points))
00081 return false;
00082 }
00083 return true;
00084 }
00085
00086 void PolygonArrayDisplay::reset()
00087 {
00088 MFDClass::reset();
00089 for (size_t i = 0; i < manual_objects_.size(); i++) {
00090 manual_objects_[i]->clear();
00091 }
00092 }
00093
00094 void PolygonArrayDisplay::updateSceneNodes(const jsk_pcl_ros::PolygonArray::ConstPtr& msg)
00095 {
00096 int scale_factor = 2;
00097 if (only_border_) {
00098 scale_factor = 1;
00099 }
00100 if (msg->polygons.size() * scale_factor > manual_objects_.size()) {
00101 for (size_t i = manual_objects_.size(); i < msg->polygons.size() * scale_factor; i++) {
00102 Ogre::SceneNode* scene_node = scene_node_->createChildSceneNode();
00103 Ogre::ManualObject* manual_object = scene_manager_->createManualObject();
00104 manual_object->setDynamic( true );
00105 scene_node->attachObject( manual_object );
00106 manual_objects_.push_back(manual_object);
00107 scene_nodes_.push_back(scene_node);
00108 }
00109 }
00110 else if (msg->polygons.size() * scale_factor < manual_objects_.size()) {
00111 for (size_t i = msg->polygons.size() * scale_factor; i < manual_objects_.size(); i++) {
00112 manual_objects_[i]->setVisible(false);
00113 }
00114 }
00115 }
00116
00117 void PolygonArrayDisplay::updateLines(int num)
00118 {
00119 if (num > lines_.size()) {
00120 for (size_t i = lines_.size(); i < num; i++) {
00121 rviz::BillboardLine* line = new rviz::BillboardLine(context_->getSceneManager(), scene_nodes_[i]);
00122 line->setLineWidth(0.01);
00123 line->setNumLines(1);
00124 lines_.push_back(line);
00125 }
00126 }
00127 for (size_t i = 0; i < lines_.size(); i++) {
00128 lines_[i]->clear();
00129 }
00130 }
00131
00132 void PolygonArrayDisplay::processMessage(const jsk_pcl_ros::PolygonArray::ConstPtr& msg)
00133 {
00134 if (!validateFloats(*msg)) {
00135 setStatus( rviz::StatusProperty::Error, "Topic", "Message contained invalid floating point values (nans or infs)" );
00136 return;
00137 }
00138
00139 updateSceneNodes(msg);
00140 allocateMaterials(msg->polygons.size());
00141 updateLines(msg->polygons.size());
00142
00143 if (only_border_) {
00144
00145 for (size_t i = 0; i < manual_objects_.size(); i++) {
00146 manual_objects_[i]->setVisible(false);
00147 }
00148 for (size_t i = 0; i < msg->polygons.size(); i++) {
00149 geometry_msgs::PolygonStamped polygon = msg->polygons[i];
00150 if (polygon.polygon.points.size() >= 3) {
00151 Ogre::SceneNode* scene_node = scene_nodes_[i];
00152
00153 Ogre::Vector3 position;
00154 Ogre::Quaternion orientation;
00155 if( !context_->getFrameManager()->getTransform(
00156 polygon.header, position, orientation )) {
00157 ROS_DEBUG( "Error transforming from frame '%s' to frame '%s'",
00158 polygon.header.frame_id.c_str(), qPrintable( fixed_frame_ ));
00159 }
00160 scene_node->setPosition( position );
00161 scene_node->setOrientation( orientation );
00162 rviz::BillboardLine* line = lines_[i];
00163 line->clear();
00164 line->setMaxPointsPerLine(polygon.polygon.points.size() + 1);
00165
00166 Ogre::ColourValue color;
00167 if (auto_coloring_) {
00168 std_msgs::ColorRGBA ros_color = jsk_topic_tools::colorCategory20(i);
00169 color.r = ros_color.r;
00170 color.g = ros_color.g;
00171 color.b = ros_color.b;
00172 color.a = ros_color.a;
00173 }
00174 else {
00175 color = rviz::qtToOgre( color_property_->getColor() );
00176 }
00177 color.a = alpha_property_->getFloat();
00178 line->setColor(color.r, color.g, color.b, color.a);
00179
00180 for (size_t i = 0; i < polygon.polygon.points.size(); ++i) {
00181 Ogre::Vector3 step_position;
00182 step_position.x = polygon.polygon.points[i].x;
00183 step_position.y = polygon.polygon.points[i].y;
00184 step_position.z = polygon.polygon.points[i].z;
00185 line->addPoint(step_position);
00186 }
00187 Ogre::Vector3 step_position;
00188 step_position.x = polygon.polygon.points[0].x;
00189 step_position.y = polygon.polygon.points[0].y;
00190 step_position.z = polygon.polygon.points[0].z;
00191 line->addPoint(step_position);
00192 }
00193 }
00194 }
00195 else {
00196 for (size_t i = 0; i < msg->polygons.size(); i++) {
00197 Ogre::ColourValue color;
00198 if (auto_coloring_) {
00199 std_msgs::ColorRGBA ros_color = jsk_topic_tools::colorCategory20(i);
00200 color.r = ros_color.r;
00201 color.g = ros_color.g;
00202 color.b = ros_color.b;
00203 color.a = ros_color.a;
00204 }
00205 else {
00206 color = rviz::qtToOgre( color_property_->getColor() );
00207 }
00208 color.a = alpha_property_->getFloat();
00209 materials_[i]->getTechnique(0)->setAmbient( color * 0.5 );
00210 materials_[i]->getTechnique(0)->setDiffuse( color );
00211 if ( color.a < 0.9998 )
00212 {
00213 materials_[i]->getTechnique(0)->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
00214 materials_[i]->getTechnique(0)->setDepthWriteEnabled( false );
00215 }
00216 else
00217 {
00218 materials_[i]->getTechnique(0)->setSceneBlending( Ogre::SBT_REPLACE );
00219 materials_[i]->getTechnique(0)->setDepthWriteEnabled( true );
00220 }
00221
00222 materials_[i]->getTechnique(0)->setAmbient( color * 0.5 );
00223 materials_[i]->getTechnique(0)->setDiffuse( color );
00224 }
00225
00226 for (size_t i = 0; i < msg->polygons.size(); i++) {
00227 geometry_msgs::PolygonStamped polygon = msg->polygons[i];
00228 Ogre::SceneNode* scene_node = scene_nodes_[i * 2];
00229 Ogre::ManualObject* manual_object = manual_objects_[i * 2];
00230 Ogre::Vector3 position;
00231 Ogre::Quaternion orientation;
00232 if(!context_->getFrameManager()->getTransform(
00233 polygon.header, position, orientation)) {
00234 ROS_DEBUG( "Error transforming from frame '%s' to frame '%s'",
00235 polygon.header.frame_id.c_str(), qPrintable(fixed_frame_));
00236 }
00237 scene_node->setPosition( position );
00238 scene_node->setOrientation( orientation );
00239 manual_object->clear();
00240 manual_object->setVisible(true);
00241
00242 jsk_pcl_ros::Polygon geo_polygon
00243 = jsk_pcl_ros::Polygon::fromROSMsg(polygon.polygon);
00244
00245
00246
00247 std::vector<jsk_pcl_ros::Polygon::Ptr>
00248 triangles = geo_polygon.decomposeToTriangles();
00249
00250
00251 uint32_t num_points = 0;
00252 for (size_t j = 0; j < triangles.size(); j++) {
00253 num_points += triangles[j]->getNumVertices();
00254 }
00255 if( num_points > 0 ) {
00256 manual_object->estimateVertexCount(num_points * 2);
00257 manual_object->begin(
00258 materials_[i]->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST);
00259 for (size_t ii = 0; ii < triangles.size(); ii++) {
00260 jsk_pcl_ros::Polygon::Ptr triangle = triangles[ii];
00261 size_t num_vertices = triangle->getNumVertices();
00262 for (size_t j = 0; j < num_vertices; j++) {
00263 Eigen::Vector3f v = triangle->getVertex(j);
00264 manual_object->position(v[0], v[1], v[2]);
00265 }
00266 for (int j = num_vertices - 1; j >= 0; j--) {
00267 Eigen::Vector3f v = triangle->getVertex(j);
00268 manual_object->position(v[0], v[1], v[2]);
00269 }
00270 }
00271
00272
00273
00274
00275
00276 manual_object->end();
00277 }
00278 }
00279
00280 for (size_t i = 0; i < msg->polygons.size(); i++) {
00281 geometry_msgs::PolygonStamped polygon = msg->polygons[i];
00282 Ogre::SceneNode* scene_node = scene_nodes_[i * 2 + 1];
00283 Ogre::ManualObject* manual_object = manual_objects_[i * 2 + 1];
00284 Ogre::Vector3 position;
00285 Ogre::Quaternion orientation;
00286 if( !context_->getFrameManager()->getTransform( polygon.header, position, orientation )) {
00287 ROS_DEBUG( "Error transforming from frame '%s' to frame '%s'",
00288 polygon.header.frame_id.c_str(), qPrintable( fixed_frame_ ));
00289 }
00290 scene_node->setPosition( position );
00291 scene_node->setOrientation( orientation );
00292 manual_object->setVisible(false);
00293 manual_object->clear();
00294
00295 uint32_t num_points = polygon.polygon.points.size();
00296 if( num_points > 0 )
00297 {
00298 manual_object->estimateVertexCount( num_points );
00299 manual_object->begin(materials_[i]->getName(), Ogre::RenderOperation::OT_TRIANGLE_FAN );
00300 for( uint32_t i = num_points; i > 0; --i )
00301 {
00302 const geometry_msgs::Point32& msg_point = polygon.polygon.points[ i % num_points ];
00303 manual_object->position( msg_point.x, msg_point.y, msg_point.z );
00304 }
00305 manual_object->end();
00306 }
00307 }
00308
00309 }
00310
00311
00312 }
00313
00314 void PolygonArrayDisplay::updateAutoColoring()
00315 {
00316 auto_coloring_ = auto_coloring_property_->getBool();
00317 }
00318 void PolygonArrayDisplay::updateOnlyBorder()
00319 {
00320 only_border_ = only_border_property_->getBool();
00321 }
00322
00323 }
00324
00325 #include <pluginlib/class_list_macros.h>
00326 PLUGINLIB_EXPORT_CLASS( jsk_rviz_plugin::PolygonArrayDisplay, rviz::Display )