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
00037
00038
00039
00040 #include <OGRE/OgreSceneNode.h>
00041 #include <OGRE/OgreSceneManager.h>
00042 #include <OGRE/OgreMovableObject.h>
00043 #include <OGRE/OgreMaterialManager.h>
00044 #include <OGRE/OgreFrustum.h>
00045
00046 #include "rviz/display_context.h"
00047 #include "rviz/robot/robot.h"
00048 #include "rviz/robot/tf_link_updater.h"
00049 #include "rviz/properties/color_property.h"
00050 #include "rviz/properties/vector_property.h"
00051 #include "rviz/properties/ros_topic_property.h"
00052 #include "rviz/properties/float_property.h"
00053 #include "rviz/properties/string_property.h"
00054 #include "rviz/properties/quaternion_property.h"
00055 #include "rviz/render_panel.h"
00056 #include "rviz/validate_floats.h"
00057 #include "rviz/view_manager.h"
00058 #include "rviz/visualization_manager.h"
00059
00060 #include <image_transport/camera_common.h>
00061
00062 #include <sensor_msgs/image_encodings.h>
00063 #include <cv_bridge/cv_bridge.h>
00064 #include <opencv2/imgproc/imgproc.hpp>
00065 #include <opencv2/highgui/highgui.hpp>
00066
00067 #include "mesh_display_custom.h"
00068
00069 namespace rviz
00070 {
00071
00072 bool validateFloats(const sensor_msgs::CameraInfo& msg)
00073 {
00074 bool valid = true;
00075 valid = valid && validateFloats( msg.D );
00076 valid = valid && validateFloats( msg.K );
00077 valid = valid && validateFloats( msg.R );
00078 valid = valid && validateFloats( msg.P );
00079 return valid;
00080 }
00081
00082 MeshDisplayCustom::MeshDisplayCustom()
00083 : Display()
00084 , time_since_last_transform_( 0.0f )
00085 , initialized_(false)
00086 {
00087 display_images_topic_property_ = new RosTopicProperty( "Display Images Topic", "",
00088 QString::fromStdString( ros::message_traits::datatype<rviz_textured_quads::TexturedQuadArray>() ),
00089 "shape_msgs::Mesh topic to subscribe to.",
00090 this, SLOT( updateDisplayImages() ));
00091
00092 text_color_property_ = new ColorProperty ( "Text Color", QColor( 255, 255, 255 ),
00093 "caption color.", this, SLOT( updateMeshProperties() ) );
00094
00095 text_height_property_ = new FloatProperty( "Text Height", 0.1f,
00096 "font size of caption", this, SLOT( updateMeshProperties() ) );
00097
00098 text_bottom_offset_ = new FloatProperty( "Text Bottom Offset", 0.18f,
00099 "text placement offset below", this, SLOT( updateMeshProperties() ) );
00100 }
00101
00102 MeshDisplayCustom::~MeshDisplayCustom()
00103 {
00104 unsubscribe();
00105
00106
00107
00108
00109 for (std::vector<Ogre::ManualObject*>::iterator it = manual_objects_.begin() ; it != manual_objects_.end(); ++it)
00110 {
00111 delete (*it);
00112 }
00113 manual_objects_.clear();
00114
00115
00116 for (std::vector<Ogre::Frustum*>::iterator it = decal_frustums_.begin() ; it != decal_frustums_.end(); ++it)
00117 {
00118 delete (*it);
00119 }
00120 decal_frustums_.clear();
00121
00122
00123 for (std::vector<ROSImageTexture*>::iterator it = textures_.begin() ; it != textures_.end(); ++it)
00124 {
00125 delete (*it);
00126 }
00127 textures_.clear();
00128
00129
00130 for (std::vector<Ogre::SceneNode*>::iterator it = mesh_nodes_.begin() ; it != mesh_nodes_.end(); ++it)
00131 {
00132 delete (*it);
00133 }
00134 mesh_nodes_.clear();
00135
00136
00137 for (std::vector<rviz_textured_quads::TextNode*>::iterator it = text_nodes_.begin() ; it != text_nodes_.end(); ++it)
00138 {
00139 delete (*it);
00140 }
00141 text_nodes_.clear();
00142
00143
00144 }
00145
00146 void MeshDisplayCustom::onInitialize()
00147 {
00148 Display::onInitialize();
00149 }
00150
00151 void MeshDisplayCustom::createProjector(int index)
00152 {
00153 decal_frustums_[index] = new Ogre::Frustum();
00154
00155 projector_nodes_[index] = scene_manager_->getRootSceneNode()->createChildSceneNode();
00156 projector_nodes_[index]->attachObject(decal_frustums_[index]);
00157
00158 Ogre::SceneNode* filter_node;
00159
00160
00161 filter_frustums_[index].push_back(new Ogre::Frustum());
00162 filter_frustums_[index].back()->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
00163 filter_node = projector_nodes_[index]->createChildSceneNode();
00164 filter_node->attachObject(filter_frustums_[index].back());
00165 filter_node->setOrientation(Ogre::Quaternion(Ogre::Degree(90),Ogre::Vector3::UNIT_Y));
00166 }
00167
00168 void MeshDisplayCustom::addDecalToMaterial(int index, const Ogre::String& matName)
00169 {
00170 Ogre::MaterialPtr mat = (Ogre::MaterialPtr)Ogre::MaterialManager::getSingleton().getByName(matName);
00171 mat->setCullingMode(Ogre::CULL_NONE);
00172 Ogre::Pass* pass = mat->getTechnique(0)->createPass();
00173
00174 pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
00175 pass->setDepthBias(1);
00176
00177
00178
00179 Ogre::String resource_group_name = "decal_textures_folder";
00180 Ogre::ResourceGroupManager& resource_manager = Ogre::ResourceGroupManager::getSingleton();
00181 if(!resource_manager.resourceGroupExists(resource_group_name))
00182 {
00183 resource_manager.createResourceGroup(resource_group_name);
00184 resource_manager.addResourceLocation(ros::package::getPath("rviz_textured_quads")+"/tests/textures/", "FileSystem", resource_group_name, false);
00185 resource_manager.initialiseResourceGroup(resource_group_name);
00186 }
00187
00188 resource_manager.loadResourceGroup(resource_group_name);
00189
00190 Ogre::TextureUnitState* tex_state = pass->createTextureUnitState();
00191 tex_state->setTextureName(textures_[index]->getTexture()->getName());
00192 tex_state->setProjectiveTexturing(true, decal_frustums_[index]);
00193
00194 tex_state->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
00195 tex_state->setTextureFiltering(Ogre::FO_POINT, Ogre::FO_LINEAR, Ogre::FO_NONE);
00196 tex_state->setColourOperation(Ogre::LBO_REPLACE);
00197
00198 for(int i = 0; i < filter_frustums_[index].size(); i++)
00199 {
00200 tex_state = pass->createTextureUnitState("Decal_filter.png");
00201 tex_state->setProjectiveTexturing(true, filter_frustums_[index][i]);
00202 tex_state->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
00203 tex_state->setTextureFiltering(Ogre::TFO_NONE);
00204 }
00205 }
00206
00207 shape_msgs::Mesh MeshDisplayCustom::constructMesh( geometry_msgs::Pose mesh_origin, float width, float height, float border_size )
00208 {
00209 shape_msgs::Mesh mesh;
00210
00211 Eigen::Affine3d trans_mat;
00212 tf::poseMsgToEigen(mesh_origin, trans_mat);
00213
00214
00215
00216
00217 Eigen::Vector4d top_left(-width/2.0f - border_size, 0.0f, -height/2.0f - border_size, 1.0f);
00218 Eigen::Vector4d top_right(width/2.0f + border_size, 0.0f, -height/2.0f - border_size, 1.0f);
00219 Eigen::Vector4d bottom_left(-width/2.0f - border_size, 0.0f, height/2.0f + border_size, 1.0f);
00220 Eigen::Vector4d bottom_right(width/2.0f + border_size, 0.0f, height/2.0f + border_size, 1.0f);
00221
00222 Eigen::Vector4d trans_top_left = trans_mat.matrix() * top_left;
00223 Eigen::Vector4d trans_top_right = trans_mat.matrix() * top_right;
00224 Eigen::Vector4d trans_bottom_left = trans_mat.matrix() * bottom_left;
00225 Eigen::Vector4d trans_bottom_right = trans_mat.matrix() * bottom_right;
00226
00227 std::vector<geometry_msgs::Point> vertices(4);
00228 vertices.at(0).x = trans_top_left[0];
00229 vertices.at(0).y = trans_top_left[1];
00230 vertices.at(0).z = trans_top_left[2];
00231 vertices.at(1).x = trans_top_right[0];
00232 vertices.at(1).y = trans_top_right[1];
00233 vertices.at(1).z = trans_top_right[2];
00234 vertices.at(2).x = trans_bottom_left[0];
00235 vertices.at(2).y = trans_bottom_left[1];
00236 vertices.at(2).z = trans_bottom_left[2];
00237 vertices.at(3).x = trans_bottom_right[0];
00238 vertices.at(3).y = trans_bottom_right[1];
00239 vertices.at(3).z = trans_bottom_right[2];
00240 mesh.vertices = vertices;
00241
00242 std::vector<shape_msgs::MeshTriangle> triangles(2);
00243 triangles.at(0).vertex_indices[0] = 0;
00244 triangles.at(0).vertex_indices[1] = 1;
00245 triangles.at(0).vertex_indices[2] = 2;
00246 triangles.at(1).vertex_indices[0] = 1;
00247 triangles.at(1).vertex_indices[1] = 2;
00248 triangles.at(1).vertex_indices[2] = 3;
00249 mesh.triangles = triangles;
00250
00251 return mesh;
00252 }
00253
00254 void MeshDisplayCustom::clearStates(int num_quads)
00255 {
00256 for (int q=0; q<manual_objects_.size(); q++)
00257 {
00258 manual_objects_[q]->clear();
00259 }
00260
00261 for (int q=0; q<text_nodes_.size(); q++)
00262 {
00263 text_nodes_[q]->clear();
00264 }
00265
00266
00267 mesh_poses_.resize(num_quads);
00268 img_widths_.resize(num_quads);
00269 img_heights_.resize(num_quads);
00270 physical_widths_.resize(num_quads);
00271 physical_heights_.resize(num_quads);
00272
00273 manual_objects_.resize(num_quads);
00274 last_meshes_.resize(num_quads);
00275
00276 last_images_.resize(num_quads);
00277 textures_.resize(num_quads);
00278 decal_frustums_.resize(num_quads);
00279 projector_nodes_.resize(num_quads);
00280 filter_frustums_.resize(num_quads);
00281 mesh_materials_.resize(num_quads);
00282 mesh_nodes_.resize(num_quads);
00283 text_nodes_.resize(num_quads);
00284
00285 border_colors_.resize(num_quads);
00286 border_sizes_.resize(num_quads);
00287 }
00288
00289 void MeshDisplayCustom::constructQuads( const rviz_textured_quads::TexturedQuadArray::ConstPtr& images )
00290 {
00291 int num_quads = images->quads.size();
00292
00293 clearStates(num_quads);
00294
00295 for (int q=0; q<num_quads; q++)
00296 {
00297 processImage(q, images->quads[q].image);
00298
00299 geometry_msgs::Pose mesh_origin = images->quads[q].pose;
00300
00301
00302 Eigen::Affine3d trans_mat;
00303 tf::poseMsgToEigen(mesh_origin, trans_mat);
00304 trans_mat = trans_mat * Eigen::Quaterniond(0.70710678, -0.70710678f, 0.0f, 0.0f);
00305
00306 Eigen::Quaterniond xz_quat(trans_mat.rotation());
00307 mesh_origin.orientation.x = xz_quat.x();
00308 mesh_origin.orientation.y = xz_quat.y();
00309 mesh_origin.orientation.z = xz_quat.z();
00310 mesh_origin.orientation.w = xz_quat.w();
00311
00312 float width = images->quads[q].width;
00313 float height = images->quads[q].height;
00314
00315
00316 mesh_poses_[q] = mesh_origin;
00317 img_widths_[q] = images->quads[q].image.width;
00318 img_heights_[q] = images->quads[q].image.height;
00319
00320 border_colors_[q].resize(4);
00321
00322 if (images->quads[q].border_color.size() == 4)
00323 {
00324 border_colors_[q][0] = images->quads[q].border_color[0];
00325 border_colors_[q][1] = images->quads[q].border_color[1];
00326 border_colors_[q][2] = images->quads[q].border_color[2];
00327 border_colors_[q][3] = images->quads[q].border_color[3];
00328 }
00329 else
00330 {
00331
00332 border_colors_[q][0] = 255.0f;
00333 border_colors_[q][1] = 255.0f;
00334 border_colors_[q][2] = 255.0f;
00335 border_colors_[q][3] = 255.0f;
00336 }
00337
00338 if (images->quads[q].border_size >= 0.0f)
00339 {
00340 border_sizes_[q] = images->quads[q].border_size;
00341 }
00342 else
00343 {
00344
00345 border_sizes_[q] = 0.0f;
00346 }
00347
00348 shape_msgs::Mesh mesh = constructMesh(mesh_origin, width, height, border_sizes_[q]);
00349
00350 physical_widths_[q] = width;
00351 physical_heights_[q] = height;
00352
00353 boost::mutex::scoped_lock lock( mesh_mutex_ );
00354
00355
00356 load(q);
00357
00358 Ogre::Vector3 caption_position = Ogre::Vector3(mesh_origin.position.x, mesh_origin.position.y + 0.5f*height + text_bottom_offset_->getFloat(), mesh_origin.position.z);
00359
00360 if (!manual_objects_[q])
00361 {
00362 static uint32_t count = 0;
00363 std::stringstream ss;
00364 ss << "MeshObject" << count++ << "Index" << q;
00365 manual_objects_[q] = context_->getSceneManager()->createManualObject(ss.str());
00366 mesh_nodes_[q]->attachObject(manual_objects_[q]);
00367 }
00368
00369
00370 if (last_meshes_[q].vertices.size() > 0 && mesh.vertices.size()*2 == last_meshes_[q].vertices.size())
00371 {
00372 manual_objects_[q]->beginUpdate(0);
00373 }
00374 else
00375 {
00376 manual_objects_[q]->clear();
00377 manual_objects_[q]->estimateVertexCount(mesh.vertices.size()*2);
00378 manual_objects_[q]->begin(mesh_materials_[q]->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST);
00379 }
00380
00381 const std::vector<geometry_msgs::Point>& points = mesh.vertices;
00382 for(size_t i = 0; i < mesh.triangles.size(); i++)
00383 {
00384
00385 for(int side = 0; side < 2; side++)
00386 {
00387 std::vector<Ogre::Vector3> corners(3);
00388 for(size_t c = 0; c < 3; c++)
00389 {
00390 size_t corner = side ? 2-c : c;
00391 corners[corner] = Ogre::Vector3(points[mesh.triangles[i].vertex_indices[corner]].x, points[mesh.triangles[i].vertex_indices[corner]].y, points[mesh.triangles[i].vertex_indices[corner]].z);
00392 }
00393 Ogre::Vector3 normal = (corners[1] - corners[0]).crossProduct(corners[2] - corners[0]);
00394 normal.normalise();
00395
00396 for(size_t c = 0; c < 3; c++)
00397 {
00398 manual_objects_[q]->position(corners[c]);
00399 manual_objects_[q]->normal(normal);
00400 }
00401 }
00402 }
00403
00404 manual_objects_[q]->end();
00405
00406 mesh_materials_[q]->setCullingMode(Ogre::CULL_NONE);
00407
00408 last_meshes_[q] = mesh;
00409
00410 Ogre::ColourValue text_color(text_color_property_->getColor().redF(), text_color_property_->getColor().greenF(), text_color_property_->getColor().blueF(), 1.0f);
00411
00412 if (!text_nodes_[q])
00413 {
00414 text_nodes_[q] = new rviz_textured_quads::TextNode(context_->getSceneManager(), manual_objects_[q]->getParentSceneNode(), caption_position);
00415 text_nodes_[q]->setCaption(images->quads[q].caption);
00416 text_nodes_[q]->setCharacterHeight(text_height_property_->getFloat());
00417 text_nodes_[q]->setColor(text_color);
00418 }
00419 else
00420 {
00421 text_nodes_[q]->setCaption(images->quads[q].caption);
00422 text_nodes_[q]->setPosition(caption_position);
00423 text_nodes_[q]->setCharacterHeight(text_height_property_->getFloat());
00424 text_nodes_[q]->setColor(text_color);
00425
00426 }
00427
00428 }
00429 }
00430
00431 void MeshDisplayCustom::updateImageMeshes( const rviz_textured_quads::TexturedQuadArray::ConstPtr& images )
00432 {
00433 constructQuads(images);
00434 updateMeshProperties();
00435 }
00436
00437 void MeshDisplayCustom::updateMeshProperties()
00438 {
00439 for (int i=0; i<mesh_materials_.size(); i++)
00440 {
00441
00442 Ogre::Technique* technique = mesh_materials_[i]->getTechnique(0);
00443 Ogre::Pass* pass = technique->getPass(0);
00444
00445 Ogre::ColourValue self_illumination_color(0.0f, 0.0f, 0.0f, 0.0f);
00446 pass->setSelfIllumination(self_illumination_color);
00447
00448 Ogre::ColourValue diffuse_color(0.0f, 0.0f, 0.0f, 1.0f);
00449 pass->setDiffuse(diffuse_color);
00450
00451 Ogre::ColourValue ambient_color(border_colors_[i][0], border_colors_[i][1], border_colors_[i][2], border_colors_[i][3]);
00452 pass->setAmbient(ambient_color);
00453
00454 Ogre::ColourValue specular_color(0.0f, 0.0f, 0.0f, 1.0f);
00455 pass->setSpecular(specular_color);
00456
00457 Ogre::Real shininess = 64.0f;
00458 pass->setShininess(shininess);
00459
00460 pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
00461 pass->setDepthWriteEnabled(false);
00462
00463 context_->queueRender();
00464 }
00465
00466 }
00467
00468 void MeshDisplayCustom::updateDisplayImages()
00469 {
00470 unsubscribe();
00471 subscribe();
00472 }
00473
00474 void MeshDisplayCustom::subscribe()
00475 {
00476 if ( !isEnabled() )
00477 {
00478 return;
00479 }
00480
00481 if( !display_images_topic_property_->getTopic().isEmpty() )
00482 {
00483 try
00484 {
00485 rviz_display_images_sub_ = nh_.subscribe(display_images_topic_property_->getTopicStd(), 1, &MeshDisplayCustom::updateImageMeshes, this);
00486 setStatus( StatusProperty::Ok, "Display Images Topic", "OK" );
00487 }
00488 catch( ros::Exception& e )
00489 {
00490 setStatus( StatusProperty::Error, "Display Images Topic", QString( "Error subscribing: " ) + e.what() );
00491 }
00492 }
00493 }
00494
00495 void MeshDisplayCustom::unsubscribe()
00496 {
00497 rviz_display_images_sub_.shutdown();
00498 }
00499
00500 void MeshDisplayCustom::load(int index)
00501 {
00502 if(mesh_nodes_[index] != NULL)
00503 return;
00504
00505 static int count = 0;
00506 std::stringstream ss;
00507 ss << "MeshNode" << count++ << "GroupIndex" << index;
00508 Ogre::MaterialManager& material_manager = Ogre::MaterialManager::getSingleton();
00509 Ogre::String resource_group_name = ss.str();
00510
00511 Ogre::ResourceGroupManager& rg_mgr = Ogre::ResourceGroupManager::getSingleton();
00512
00513 Ogre::String material_name = resource_group_name+"MeshMaterial";
00514
00515 if(!rg_mgr.resourceGroupExists(resource_group_name))
00516 {
00517 rg_mgr.createResourceGroup(resource_group_name);
00518
00519 mesh_materials_[index] = material_manager.create(material_name,resource_group_name);
00520 Ogre::Technique* technique = mesh_materials_[index]->getTechnique(0);
00521 Ogre::Pass* pass = technique->getPass(0);
00522
00523 Ogre::ColourValue self_illumnation_color(0.0f, 0.0f, 0.0f, border_colors_[index][3]);
00524 pass->setSelfIllumination(self_illumnation_color);
00525
00526 Ogre::ColourValue diffuse_color(border_colors_[index][0], border_colors_[index][1], border_colors_[index][2], border_colors_[index][3]);
00527 pass->setDiffuse(diffuse_color);
00528
00529 Ogre::ColourValue ambient_color(border_colors_[index][0], border_colors_[index][1], border_colors_[index][2], border_colors_[index][3]);
00530 pass->setAmbient(ambient_color);
00531
00532 Ogre::ColourValue specular_color(1.0f, 1.0f, 1.0f, 1.0f);
00533 pass->setSpecular(specular_color);
00534
00535 Ogre::Real shininess = 64.0f;
00536 pass->setShininess(shininess);
00537
00538 pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
00539
00540 mesh_materials_[index]->setCullingMode(Ogre::CULL_NONE);
00541 }
00542
00543 mesh_nodes_[index] = this->scene_node_->createChildSceneNode();
00544
00545 }
00546
00547 void MeshDisplayCustom::onEnable()
00548 {
00549 subscribe();
00550 }
00551
00552 void MeshDisplayCustom::onDisable()
00553 {
00554 unsubscribe();
00555 }
00556
00557 void MeshDisplayCustom::update( float wall_dt, float ros_dt )
00558 {
00559 time_since_last_transform_ += wall_dt;
00560
00561 if( !display_images_topic_property_->getTopic().isEmpty() )
00562 {
00563 try
00564 {
00565 for (int i=0; i<textures_.size(); i++)
00566 {
00567 updateCamera(i, textures_[i]->update());
00568 }
00569 }
00570 catch( UnsupportedImageEncoding& e )
00571 {
00572 setStatus(StatusProperty::Error, "Display Image", e.what());
00573 }
00574 }
00575 }
00576
00577 bool MeshDisplayCustom::updateCamera(int index, bool update_image)
00578 {
00579 if(update_image)
00580 {
00581 last_images_[index] = textures_[index]->getImage();
00582 }
00583
00584 if(!img_heights_[index] || !img_widths_[index] ||
00585 !physical_widths_[index] || !physical_heights_[index] ||
00586 !last_images_[index])
00587 {
00588 return false;
00589 }
00590
00591 boost::mutex::scoped_lock lock( mesh_mutex_ );
00592
00593 float img_width = img_widths_[index];
00594 float img_height = img_heights_[index];
00595
00596 Ogre::Vector3 position;
00597 Ogre::Quaternion orientation;
00598
00599 context_->getFrameManager()->getTransform( last_images_[index]->header.frame_id, last_images_[index]->header.stamp, position, orientation );
00600
00601 Eigen::Affine3d trans_mat;
00602 tf::poseMsgToEigen(mesh_poses_[index], trans_mat);
00603
00604
00605 trans_mat = trans_mat * Eigen::Quaterniond(0.70710678, -0.70710678f, 0.0f, 0.0f);
00606
00607 float z_offset = (img_width > img_height) ? img_width : img_height;
00608 float scale_factor = 1.0f / (physical_widths_[index] > physical_heights_[index] ? physical_widths_[index] : physical_heights_[index]);
00609
00610 Eigen::Vector4d projector_origin(0.0f, 0.0f, 1.0f / (z_offset * scale_factor), 1.0f);
00611 Eigen::Vector4d projector_point = trans_mat.matrix() * projector_origin;
00612
00613 position = Ogre::Vector3(projector_point[0], projector_point[1], projector_point[2] );
00614 orientation = Ogre::Quaternion(mesh_poses_[index].orientation.w, mesh_poses_[index].orientation.x, mesh_poses_[index].orientation.y, mesh_poses_[index].orientation.z);
00615
00616
00617 orientation = orientation * Ogre::Quaternion( Ogre::Degree( -90 ), Ogre::Vector3::UNIT_X );
00618
00619
00620 orientation = orientation * Ogre::Quaternion( Ogre::Degree( 180 ), Ogre::Vector3::UNIT_Z );
00621
00622
00623
00624
00625
00626
00627
00628 if( img_width <= 0 )
00629 {
00630 ROS_ERROR( "Malformed CameraInfo on camera [%s], width = 0", qPrintable( getName() ));
00631
00632 img_width = textures_[index]->getWidth()-2;
00633 }
00634
00635 if (img_height <= 0)
00636 {
00637 ROS_ERROR( "Malformed CameraInfo on camera [%s], height = 0", qPrintable( getName() ));
00638
00639 img_height = textures_[index]->getHeight()-2;
00640 }
00641
00642
00643 if( img_height <= 0.0 || img_width <= 0.0 )
00644 {
00645 setStatus( StatusProperty::Error, "Camera Info",
00646 "Could not determine width/height of image due to malformed CameraInfo (either width or height is 0) and texture." );
00647 return false;
00648 }
00649
00650
00651 float P[12] = {1.0, 0.0, img_width / 2.0f, 0.0,
00652 0.0, 1.0, img_height / 2.0f, 0.0,
00653 0.0, 0.0, 1.0, 0.0 };
00654
00655
00656 double fx = P[0];
00657 double fy = P[5];
00658
00659
00660 double tx = -1 * (P[3] / fx);
00661 Ogre::Vector3 right = orientation * Ogre::Vector3::UNIT_X;
00662 position = position + (right * tx);
00663
00664 double ty = -1 * (P[7] / fy);
00665 Ogre::Vector3 down = orientation * Ogre::Vector3::UNIT_Y;
00666 position = position + (down * ty);
00667
00668 if( !validateFloats( position ))
00669 {
00670 ROS_ERROR( "position error");
00671 setStatus( StatusProperty::Error, "Camera Info", "CameraInfo/P resulted in an invalid position calculation (nans or infs)" );
00672 return false;
00673 }
00674
00675 if(projector_nodes_[index] != NULL)
00676 {
00677 projector_nodes_[index]->setPosition( position );
00678 projector_nodes_[index]->setOrientation( orientation );
00679 }
00680
00681
00682 double cx = P[2];
00683 double cy = P[6];
00684
00685 double far_plane = 100;
00686 double near_plane = 0.01;
00687
00688 Ogre::Matrix4 proj_matrix;
00689 proj_matrix = Ogre::Matrix4::ZERO;
00690
00691 proj_matrix[0][0]= 2.0 * fx/img_width;
00692 proj_matrix[1][1]= 2.0 * fy/img_height;
00693
00694 proj_matrix[0][2]= 2.0 * (0.5 - cx/img_width);
00695 proj_matrix[1][2]= 2.0 * (cy/img_height - 0.5);
00696
00697 proj_matrix[2][2]= -(far_plane+near_plane) / (far_plane-near_plane);
00698 proj_matrix[2][3]= -2.0*far_plane*near_plane / (far_plane-near_plane);
00699
00700 proj_matrix[3][2]= -1;
00701
00702 if(decal_frustums_[index] != NULL)
00703 decal_frustums_[index]->setCustomProjectionMatrix(true, proj_matrix);
00704
00705
00706
00707
00708
00709 setStatus( StatusProperty::Ok, "Time", "ok" );
00710 setStatus( StatusProperty::Ok, "Camera Info", "ok" );
00711
00712 if(mesh_nodes_[index] != NULL && filter_frustums_[index].size() == 0 && !mesh_materials_[index].isNull())
00713 {
00714 createProjector(index);
00715
00716 addDecalToMaterial(index, mesh_materials_[index]->getName());
00717 }
00718
00719 return true;
00720 }
00721
00722 void MeshDisplayCustom::clear()
00723 {
00724 for (int i=0; i<textures_.size(); i++)
00725 {
00726 textures_[i]->clear();
00727 }
00728
00729 context_->queueRender();
00730
00731 setStatus( StatusProperty::Warn, "Image", "No Image received");
00732 }
00733
00734 void MeshDisplayCustom::reset()
00735 {
00736 Display::reset();
00737 clear();
00738 }
00739
00740 void MeshDisplayCustom::processImage(int index, const sensor_msgs::Image& msg)
00741 {
00742
00743 cv_bridge::CvImagePtr cv_ptr;
00744
00745
00746 try
00747 {
00748 cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::RGBA8);
00749 }
00750 catch (cv_bridge::Exception& e)
00751 {
00752 ROS_ERROR("MeshDisplayCustom: cv_bridge exception: %s", e.what());
00753 return;
00754 }
00755
00756
00757 cv::Scalar value(255,255,255,0);
00758 cv::copyMakeBorder(cv_ptr->image,cv_ptr->image,1,1,1,1,cv::BORDER_CONSTANT,value);
00759 cv::flip(cv_ptr->image,cv_ptr->image,-1);
00760
00761
00762 if (textures_[index] == NULL)
00763 textures_[index] = new ROSImageTexture();
00764
00765 textures_[index]->addMessage(cv_ptr->toImageMsg());
00766 }
00767
00768 }