object_recognition_rviz_ui.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "object_recognition_gui/object_recognition_rviz_ui.h"
00031 
00032 #include "rviz_interaction_tools/image_tools.h"
00033 
00034 #include "rviz_interaction_tools/mesh_object_switcher.h"
00035 #include "rviz_interaction_tools/mesh_object.h"
00036 #include "rviz_interaction_tools/camera_tools.h"
00037 
00038 #include <OGRE/OgreManualObject.h>
00039 #include <OGRE/OgreMaterialManager.h>
00040 #include <OGRE/OgreRenderWindow.h>
00041 #include <OGRE/OgreSceneNode.h>
00042 #include <OGRE/OgreSceneManager.h>
00043 #include <OGRE/OgreRoot.h>
00044 
00045 #include <rviz/render_panel.h>
00046 #include <rviz/window_manager_interface.h>
00047 #include "rviz/display_context.h"
00048 
00049 #include "rviz_interaction_tools/image_overlay.h"
00050 #include "rviz_interaction_tools/camera_tools.h"
00051 #include "rviz_interaction_tools/unique_string_manager.h"
00052 
00053 #include "ui_object_recognition_frame.h" // generated by uic during build.
00054 
00055 using namespace rviz_interaction_tools;
00056 
00057 namespace object_recognition_gui
00058 {
00059 
00060 // material names for the different mesh colors
00061 static const std::string VALID_MAT_NAME = "object_recognition_valid";
00062 static const std::string VALID_SEL_MAT_NAME = "object_recognition_valid_selected";
00063 static const std::string INVALID_MAT_NAME = "object_recognition_invalid";
00064 static const std::string INVALID_SEL_MAT_NAME = "object_recognition_invalid_selected";
00065 
00066 
00067 ObjectRecognitionRvizUI::ObjectRecognitionRvizUI(rviz::DisplayContext* context) :
00068     QWidget(),
00069     object_recognition_server_(0),
00070     ui_( new Ui::ObjectRecognitionFrame )
00071 {
00072   ui_->setupUi( this );
00073   render_panel_ = ui_->render_panel_;
00074   connect( render_panel_, SIGNAL( mouseEvent( QMouseEvent* )),
00075            this, SLOT( onRenderWindowMouseEvent( QMouseEvent* )));
00076   connect( ui_->cancel, SIGNAL( clicked() ), this, SLOT( cancelButtonClicked() ));
00077   connect( ui_->ok, SIGNAL( clicked() ), this, SLOT( acceptButtonClicked() ));
00078 
00079   UniqueStringManager usm;
00080   
00081   //construct basic ogre scene
00082   scene_manager_ = Ogre::Root::getSingleton().createSceneManager( Ogre::ST_GENERIC, usm.unique("ObjectRecognitionRvizUI") );
00083 
00084   scene_root_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00085   
00086   image_overlay_ = new rviz_interaction_tools::ImageOverlay( scene_root_, Ogre::RENDER_QUEUE_BACKGROUND );
00087 
00088   setupRenderPanel( context );
00089 
00090   createMaterials();
00091 
00092   ray_scene_query_ = scene_manager_->createRayQuery(Ogre::Ray());
00093 }
00094 
00095 ObjectRecognitionRvizUI::~ObjectRecognitionRvizUI()
00096 {
00097   if ( object_recognition_server_ )
00098   {
00099     stopActionServer();
00100   }
00101 
00102   cleanupAndHide();
00103 
00104   scene_manager_->destroyQuery( ray_scene_query_ );
00105 
00106   render_panel_->getRenderWindow()->setActive(false);
00107 
00108   delete render_panel_;
00109   delete image_overlay_;
00110   delete ui_;
00111 
00112   Ogre::Root::getSingleton().destroySceneManager( scene_manager_ );
00113 }
00114 
00115 
00116 void ObjectRecognitionRvizUI::showBoundingBoxes( bool show )
00117 {
00118   scene_manager_->showBoundingBoxes(show);
00119 }
00120 
00121 bool ObjectRecognitionRvizUI::getShowBoundingBoxes()
00122 {
00123   return scene_manager_->getShowBoundingBoxes();
00124 }
00125 
00126 void ObjectRecognitionRvizUI::updateBoundingBoxes()
00127 {
00128   bool show = getShowBoundingBoxes();
00129   showBoundingBoxes (show);
00130 }
00131 
00132 
00133 void ObjectRecognitionRvizUI::cleanupAndHide()
00134 {
00135   for ( size_t m=0; m<mesh_switchers_.size(); ++m )
00136   {
00137     delete mesh_switchers_[m];
00138   }
00139   mesh_switchers_.clear();
00140   hide();
00141 }
00142 
00143 
00144 void ObjectRecognitionRvizUI::setupRenderPanel( rviz::DisplayContext* context )
00145 {
00146   render_panel_->initialize( scene_manager_, context );
00147 
00148   render_panel_->setAutoRender(false);
00149   render_panel_->getViewport()->setOverlaysEnabled(false);
00150   render_panel_->getViewport()->setClearEveryFrame(true);
00151   render_panel_->getRenderWindow()->setAutoUpdated(false);
00152   render_panel_->getRenderWindow()->setActive(true);
00153 
00154   //fill camera matrix with dummy values to RaySceneQuery won't crash
00155   render_panel_->getCamera()->setPosition(0.0, 0.0, 0.0);
00156   render_panel_->getCamera()->lookAt(Ogre::Vector3(0, 0, 1));
00157   render_panel_->getCamera()->roll(Ogre::Radian(3.141592653));
00158   render_panel_->getCamera()->setFOVy(Ogre::Radian(0.518));
00159   render_panel_->getCamera()->setAspectRatio(640.0 / 480.0);
00160   render_panel_->getCamera()->setNearClipDistance( 0.01f );
00161 }
00162 
00163 
00164 void ObjectRecognitionRvizUI::createMaterials()
00165 {
00166   Ogre::MaterialPtr white = Ogre::MaterialManager::getSingleton().getByName("BaseWhiteNoLighting");
00167 
00168   Ogre::Pass *pass;
00169 
00170   // clone materials + adjust rendering settings
00171 
00172   // material for valid models
00173   Ogre::MaterialPtr valid_mat = white->clone( VALID_MAT_NAME );
00174 
00175   pass = valid_mat->getTechnique(0)->getPass(0);
00176 
00177   pass->setPolygonMode( Ogre::PM_WIREFRAME );
00178   pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
00179   pass->setDepthWriteEnabled(false);
00180   pass->setDepthCheckEnabled(false);
00181   pass->setLightingEnabled(true);
00182   pass->setCullingMode( Ogre::CULL_NONE );
00183   pass->setAmbient(0.0, 0.0, 0.0);
00184   pass->setDiffuse(0.0, 0.0, 0.0, 0.3);
00185   pass->setSpecular(0.0, 0.0, 0.0, 0.3);
00186 
00187   pass->setSelfIllumination( 0.0, 0.9, 0.0 );
00188 
00189   // material for valid models when selected
00190   pass = valid_mat->clone( VALID_SEL_MAT_NAME )->getTechnique(0)->getPass(0);
00191   pass->setSelfIllumination( 0.4, 1.0, 0.4 );
00192 
00193   // material for invalid models (wrong recognition)
00194   pass = valid_mat->clone( INVALID_MAT_NAME )->getTechnique(0)->getPass(0);
00195   pass->setSelfIllumination( 0.9, 0.0, 0.0 );
00196 
00197   // material for invalid models (wrong recognition)
00198   pass = valid_mat->clone( INVALID_SEL_MAT_NAME )->getTechnique(0)->getPass(0);
00199   pass->setSelfIllumination( 1.0, 0.4, 0.4 );
00200 
00201   pass->_dirtyHash();
00202 }
00203 
00204 
00205 void ObjectRecognitionRvizUI::parseMeshes(const std::vector<interactive_perception_msgs::ModelHypothesisList> &model_hyp_list)
00206 {
00207   ROS_ASSERT( mesh_switchers_.size() == 0 );
00208 
00209   //get all the meshes from the database
00210   int num_models = model_hyp_list.size();
00211   mesh_switchers_.resize(num_models);
00212   for ( int m=0; m<num_models; ++m )
00213   {
00214     const std::vector<interactive_perception_msgs::ModelHypothesis> &hyp_list =
00215         model_hyp_list[m].hypotheses;
00216 
00217     int num_hyp = hyp_list.size();
00218     mesh_switchers_[m] = new MeshObjectSwitcher( VALID_MAT_NAME, VALID_SEL_MAT_NAME, INVALID_MAT_NAME, INVALID_SEL_MAT_NAME );
00219 
00220     if ( hyp_list.size() == 0 || hyp_list[0].mesh.triangles.size() == 0 )
00221     {
00222       continue;
00223     }
00224 
00225     for ( int h=0; h<num_hyp; ++h )
00226     {
00227       const shape_msgs::Mesh& mesh = hyp_list[h].mesh;
00228       const geometry_msgs::Pose pose = hyp_list[h].pose.pose;
00229 #if 0
00230       ROS_INFO_STREAM( "Model " << m << ", hypothesis " << h
00231           << ") has " << mesh.triangles.size() << " triangles and "
00232           << mesh.vertices.size() << " vertices." );
00233       ROS_INFO_STREAM( " Position:" << pose.position.x << " "
00234           << pose.position.y << " " << pose.position.z <<
00235           ". Orientation: " << pose.orientation.w << " " << pose.orientation.x
00236           << " " << pose.orientation.y << " " << pose.orientation.z );
00237 #endif
00238       MeshObject* mesh_object = new MeshObject( scene_manager_, scene_root_ );
00239 
00240       std::ostringstream s;
00241       s << "obj_rec model " << m << " hypothesis " << h;
00242       std::string name = s.str();
00243 
00244       mesh_object->loadMesh( name, mesh );
00245       mesh_object->setPose( pose );
00246 
00247       Ogre::Entity* entity = mesh_object->getEntity();
00248       entity->getUserObjectBindings().setUserAny( "model", Ogre::Any(m) );
00249       entity->setRenderQueueGroup(Ogre::RENDER_QUEUE_MAIN);
00250 
00251       mesh_switchers_[m]->addObject( mesh_object );
00252     }
00253 
00254     mesh_switchers_[m]->setValid( model_hyp_list[m].accept );
00255     mesh_switchers_[m]->setVisible( 0 );
00256   }
00257 }
00258 
00259 
00260 void ObjectRecognitionRvizUI::update(float wall_dt, float ros_dt)
00261 {
00262   render_panel_->getRenderWindow()->update();
00263 }
00264 
00265 
00266 void ObjectRecognitionRvizUI::onRenderWindowMouseEvent( QMouseEvent* event )
00267 {
00268   ROS_ASSERT( object_recognition_server_->isActive() );
00269 
00270   int x = event->x();
00271   int y = event->y();
00272 
00273   QSize size = render_panel_->size();
00274 
00275   //check if one object has been selected or clicked (using normalized screen coordinates x,y in [0-1]).
00276   Ogre::Ray mouse_ray = render_panel_->getCamera()->getCameraToViewportRay(x/float(size.width()), y/float(size.height()));
00277   ray_scene_query_->setRay( mouse_ray );
00278 
00279   for ( size_t m=0; m<mesh_switchers_.size(); ++m )
00280   {
00281     mesh_switchers_[m]->setSelected(false);
00282   }
00283 
00284   // Execute query
00285   ray_scene_query_->setSortByDistance(true);
00286   Ogre::RaySceneQueryResult& result = ray_scene_query_->execute();
00287   Ogre::RaySceneQueryResult::iterator iter = result.begin();
00288 
00289   int i=0;
00290   while( iter != result.end() )
00291   {
00292     Ogre::MovableObject* movable_object = iter->movable;
00293     if ( movable_object )
00294     {
00295       Ogre::Any model_any = movable_object->getUserObjectBindings().getUserAny( "model" );
00296 
00297       if ( !model_any.isEmpty() )
00298       {
00299         int model = Ogre::any_cast<int>(model_any);
00300         //ROS_INFO_STREAM( " model: " << model );
00301 
00302         if ( model >=0 && model < (int)mesh_switchers_.size() )
00303         {
00304           mesh_switchers_[model]->setSelected(true);
00305 
00306           if ( mesh_switchers_[model]->isValid() )
00307           {
00308             if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton)
00309             {
00310               mesh_switchers_[model]->next();
00311             }
00312             else if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::RightButton)
00313             {
00314               mesh_switchers_[model]->setValid( false );
00315             }
00316           }
00317           else
00318           {
00319             if ( event->type() == QEvent::MouseButtonPress )
00320             {
00321               mesh_switchers_[model]->setValid( true );
00322             }
00323           }
00324         }
00325         break;
00326       }
00327     }
00328 
00329     i++;
00330     iter++;
00331   }
00332 }
00333 
00334 
00335 void ObjectRecognitionRvizUI::acceptButtonClicked()
00336 {
00337   interactive_perception_msgs::ObjectRecognitionGuiResult result;
00338 
00339   result.selected_hypothesis_indices.resize( mesh_switchers_.size() );
00340   for ( unsigned i=0; i<mesh_switchers_.size(); ++i )
00341   {
00342     result.selected_hypothesis_indices[i] =
00343         mesh_switchers_[i]->isValid() ? mesh_switchers_[i]->getVisible() : -1;
00344   }
00345 
00346   object_recognition_server_->setSucceeded(result);
00347   cleanupAndHide();
00348 }
00349 
00350 
00351 void ObjectRecognitionRvizUI::cancelButtonClicked()
00352 {
00353   object_recognition_server_->setAborted();
00354   cleanupAndHide();
00355 }
00356 
00357 
00358 void ObjectRecognitionRvizUI::startActionServer( ros::NodeHandle &node_handle )
00359 {
00360   if ( object_recognition_server_ )
00361   {
00362     ROS_ERROR( "ObjectRecognitionGuiAction server already started!" );
00363     return;
00364   }
00365 
00366   //create non-threaded action server
00367   object_recognition_server_ =
00368     new actionlib::SimpleActionServer<interactive_perception_msgs::ObjectRecognitionGuiAction>( node_handle, "object_recognition_popup", false );
00369 
00370   object_recognition_server_->registerGoalCallback( boost::bind(&ObjectRecognitionRvizUI::acceptNewGoal, this) );
00371   object_recognition_server_->registerPreemptCallback( boost::bind(&ObjectRecognitionRvizUI::preempt, this) );
00372 
00373   object_recognition_server_->start();
00374 }
00375 
00376 
00377 void ObjectRecognitionRvizUI::stopActionServer()
00378 {
00379   if ( !object_recognition_server_ )
00380   {
00381     ROS_ERROR("ObjectRecognitionGuiAction server cannot be stopped because it is not running.");
00382     return;
00383   }
00384 
00385   //if we're currently being active, we have to cancel everything, clean up & hide the window
00386   if ( object_recognition_server_->isActive() )
00387   {
00388     ROS_WARN("Aborting ObjectRecognitionGuiAction goal.");
00389     object_recognition_server_->setAborted();
00390     cleanupAndHide();
00391   }
00392 
00393   delete object_recognition_server_;
00394   object_recognition_server_ = 0;
00395 }
00396 
00397 void ObjectRecognitionRvizUI::acceptNewGoal()
00398 {
00399   const interactive_perception_msgs::ObjectRecognitionGuiGoal::ConstPtr &goal = object_recognition_server_->acceptNewGoal();
00400 
00401   try {
00402     image_overlay_->setImage( goal->image );
00403     image_overlay_->update();
00404   } catch ( ... )
00405   {
00406     ROS_ERROR("Could not set the overlay image!");
00407     object_recognition_server_->setAborted();
00408     return;
00409   }
00410 
00411   rviz_interaction_tools::updateCamera( render_panel_->getCamera(), goal->camera_info );
00412 
00413   parseMeshes( goal->model_hypotheses );
00414 
00415   show();
00416 }
00417 
00418 void ObjectRecognitionRvizUI::preempt()
00419 {
00420   object_recognition_server_->setPreempted();
00421   cleanupAndHide();
00422 }
00423 
00424 
00425 
00426 
00427 }


object_recognition_gui
Author(s): David Gossow
autogenerated on Mon Oct 6 2014 11:53:20